PSI update
r1464 | ffr | 2007-02-12 12:20:21 +1100 (Mon, 12 Feb 2007) | 2 lines
This commit is contained in:

committed by
Douglas Clowes

parent
634f2023b1
commit
3168325921
11
HistDriv.i
11
HistDriv.i
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#line 462 "histogram.w"
|
#line 465 "histogram.w"
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
H I S T D R I V
|
H I S T D R I V
|
||||||
@ -58,6 +58,9 @@
|
|||||||
SConnection *pCon);
|
SConnection *pCon);
|
||||||
float (*GetTime)(pHistDriver self,
|
float (*GetTime)(pHistDriver self,
|
||||||
SConnection *pCon);
|
SConnection *pCon);
|
||||||
|
HistInt *(*SubSample)(pHistDriver self,
|
||||||
|
SConnection *pCon,int bank,
|
||||||
|
char *command);
|
||||||
int (*Preset)(pHistDriver self,
|
int (*Preset)(pHistDriver self,
|
||||||
SConnection *pCon,
|
SConnection *pCon,
|
||||||
HistInt iVal);
|
HistInt iVal);
|
||||||
@ -69,17 +72,17 @@
|
|||||||
void *pPriv;
|
void *pPriv;
|
||||||
} HistDriver;
|
} HistDriver;
|
||||||
|
|
||||||
#line 474 "histogram.w"
|
#line 477 "histogram.w"
|
||||||
|
|
||||||
|
|
||||||
#line 229 "histogram.w"
|
#line 232 "histogram.w"
|
||||||
|
|
||||||
pHistDriver CreateHistDriver(pStringDict pDict);
|
pHistDriver CreateHistDriver(pStringDict pDict);
|
||||||
void DeleteHistDriver(pHistDriver self);
|
void DeleteHistDriver(pHistDriver self);
|
||||||
int HistDriverConfig(pHistDriver self, pStringDict pOpt,
|
int HistDriverConfig(pHistDriver self, pStringDict pOpt,
|
||||||
SConnection *pCon);
|
SConnection *pCon);
|
||||||
|
|
||||||
#line 475 "histogram.w"
|
#line 478 "histogram.w"
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
16
HistMem.h
16
HistMem.h
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#line 435 "histogram.w"
|
#line 438 "histogram.w"
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------
|
/*--------------------------------------------------------------------------
|
||||||
H I S T M E M
|
H I S T M E M
|
||||||
@ -42,22 +42,22 @@
|
|||||||
eReflect
|
eReflect
|
||||||
} OverFlowMode;
|
} OverFlowMode;
|
||||||
|
|
||||||
#line 455 "histogram.w"
|
#line 458 "histogram.w"
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#line 287 "histogram.w"
|
#line 290 "histogram.w"
|
||||||
|
|
||||||
pHistMem CreateHistMemory(char *drivername);
|
pHistMem CreateHistMemory(char *drivername);
|
||||||
void DeleteHistMemory(void *self);
|
void DeleteHistMemory(void *self);
|
||||||
|
|
||||||
#line 303 "histogram.w"
|
#line 306 "histogram.w"
|
||||||
|
|
||||||
int HistGetOption(pHistMem self, char *name, char *result, int iResultLen);
|
int HistGetOption(pHistMem self, char *name, char *result, int iResultLen);
|
||||||
int HistSetOption(pHistMem self, char *name, char *value);
|
int HistSetOption(pHistMem self, char *name, char *value);
|
||||||
int HistConfigure(pHistMem self, SConnection *pCon, SicsInterp *pSics);
|
int HistConfigure(pHistMem self, SConnection *pCon, SicsInterp *pSics);
|
||||||
|
|
||||||
#line 331 "histogram.w"
|
#line 334 "histogram.w"
|
||||||
|
|
||||||
float GetHistPreset(pHistMem self);
|
float GetHistPreset(pHistMem self);
|
||||||
int SetHistPreset(pHistMem self, float fVal);
|
int SetHistPreset(pHistMem self, float fVal);
|
||||||
@ -73,7 +73,7 @@
|
|||||||
void HistDirty(pHistMem self);
|
void HistDirty(pHistMem self);
|
||||||
|
|
||||||
|
|
||||||
#line 361 "histogram.w"
|
#line 364 "histogram.w"
|
||||||
|
|
||||||
int SetHistogram(pHistMem self, SConnection *pCon,
|
int SetHistogram(pHistMem self, SConnection *pCon,
|
||||||
int i,int iStart, int iEnd, HistInt *lData);
|
int i,int iStart, int iEnd, HistInt *lData);
|
||||||
@ -85,7 +85,7 @@
|
|||||||
HistInt *lData, int iDataLen);
|
HistInt *lData, int iDataLen);
|
||||||
int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal);
|
int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal);
|
||||||
|
|
||||||
#line 404 "histogram.w"
|
#line 407 "histogram.w"
|
||||||
|
|
||||||
int MakeHistMemory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
int MakeHistMemory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
@ -94,7 +94,7 @@
|
|||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
|
|
||||||
|
|
||||||
#line 457 "histogram.w"
|
#line 460 "histogram.w"
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#line 480 "histogram.w"
|
#line 483 "histogram.w"
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
H I S T M E M -- Internal
|
H I S T M E M -- Internal
|
||||||
@ -11,7 +11,7 @@
|
|||||||
#ifndef SICSHISTMEMINT
|
#ifndef SICSHISTMEMINT
|
||||||
#define SICSHISTMEMINT
|
#define SICSHISTMEMINT
|
||||||
|
|
||||||
#line 251 "histogram.w"
|
#line 254 "histogram.w"
|
||||||
|
|
||||||
typedef struct __HistMem {
|
typedef struct __HistMem {
|
||||||
pObjectDescriptor pDes;
|
pObjectDescriptor pDes;
|
||||||
@ -23,7 +23,7 @@
|
|||||||
pICallBack pCall;
|
pICallBack pCall;
|
||||||
} HistMem;
|
} HistMem;
|
||||||
|
|
||||||
#line 490 "histogram.w"
|
#line 493 "histogram.w"
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
69
SCinter.c
69
SCinter.c
@ -41,7 +41,7 @@
|
|||||||
Mark Koennecke, August 2001, modified SicsWriteStatus to write motor
|
Mark Koennecke, August 2001, modified SicsWriteStatus to write motor
|
||||||
positions on demand.
|
positions on demand.
|
||||||
|
|
||||||
Made ListObjects moe intelligent: list objects according to interface etc.
|
Made ListObjects more intelligent: list objects according to interface etc.
|
||||||
Mark Koennecke, December 2003
|
Mark Koennecke, December 2003
|
||||||
|
|
||||||
Extended 'dir' command (function ListObjects) to list via typename from
|
Extended 'dir' command (function ListObjects) to list via typename from
|
||||||
@ -50,6 +50,8 @@
|
|||||||
|
|
||||||
Modified printXXX functions to fix duplicate write of last buffer line.
|
Modified printXXX functions to fix duplicate write of last buffer line.
|
||||||
Paul Hathaway, May 2004
|
Paul Hathaway, May 2004
|
||||||
|
|
||||||
|
Added FindAlias function, Mark Koennecke, January 2007
|
||||||
---------------------------------------------------------------------------*/
|
---------------------------------------------------------------------------*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -67,6 +69,7 @@
|
|||||||
#include "motor.h"
|
#include "motor.h"
|
||||||
#include "obdes.h"
|
#include "obdes.h"
|
||||||
#include "lld.h"
|
#include "lld.h"
|
||||||
|
#include "dynstring.h"
|
||||||
|
|
||||||
/* M.Z. */
|
/* M.Z. */
|
||||||
#include "definealias.h"
|
#include "definealias.h"
|
||||||
@ -134,6 +137,7 @@ static void freeList(int listID);
|
|||||||
SICSLogWrite(pBueffel,eInternal);
|
SICSLogWrite(pBueffel,eInternal);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
memset(pNew,0,sizeof(CommandList));
|
||||||
|
|
||||||
/* if no data given, initialise with Dummy struct */
|
/* if no data given, initialise with Dummy struct */
|
||||||
if(!pData)
|
if(!pData)
|
||||||
@ -431,7 +435,7 @@ extern char *SkipSpace(char *pPtr);
|
|||||||
}
|
}
|
||||||
if(fVal > -990.)
|
if(fVal > -990.)
|
||||||
{
|
{
|
||||||
fprintf(fd,"run %s %f\n",pCurrent->pName, fVal);
|
fprintf(fd,"drive %s %f\n",pCurrent->pName, fVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1041,3 +1045,64 @@ static void freeList(int listID)
|
|||||||
pCurrent = pNext;
|
pCurrent = pNext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
char *FindAliases(SicsInterp *pSics, char *name)
|
||||||
|
{
|
||||||
|
pDynString result = NULL;
|
||||||
|
CommandList *pOri = NULL, *pCom = NULL;
|
||||||
|
char *pTrans = NULL, *charResult = NULL;
|
||||||
|
int first;
|
||||||
|
|
||||||
|
pOri = FindCommand(pSics, name);
|
||||||
|
if(pOri == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(pOri->pData == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = CreateDynString(64,64);
|
||||||
|
if(result == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try first to locate Markus style aliases */
|
||||||
|
pTrans = TranslateAlias(&pSics->AList,name);
|
||||||
|
if(strcmp(pTrans,name) != 0)
|
||||||
|
{
|
||||||
|
DynStringCopy(result,pTrans);
|
||||||
|
charResult = strdup(GetCharArray(result));
|
||||||
|
DeleteDynString(result);
|
||||||
|
return charResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* locate SicsAlias style aliases by comparing the original
|
||||||
|
* data pointer with the data pointers of other commands
|
||||||
|
*/
|
||||||
|
first = 1;
|
||||||
|
pCom = pSics->pCList;
|
||||||
|
while(pCom != NULL)
|
||||||
|
{
|
||||||
|
if(pCom != pOri && pCom->pData == pOri->pData)
|
||||||
|
{
|
||||||
|
if(first)
|
||||||
|
{
|
||||||
|
DynStringCopy(result,pCom->pName);
|
||||||
|
first = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DynStringConcat(result,",");
|
||||||
|
DynStringConcat(result,pCom->pName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pCom = pCom->pNext;
|
||||||
|
}
|
||||||
|
charResult = strdup(GetCharArray(result));
|
||||||
|
DeleteDynString(result);
|
||||||
|
return charResult;
|
||||||
|
}
|
||||||
|
@ -51,7 +51,8 @@ typedef enum {
|
|||||||
eEvent,
|
eEvent,
|
||||||
eWarning,
|
eWarning,
|
||||||
eError,
|
eError,
|
||||||
eHdb
|
eHdbValue,
|
||||||
|
eHdbEvent
|
||||||
} OutCode;
|
} OutCode;
|
||||||
|
|
||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
|
@ -113,6 +113,7 @@ static long ColliderSetValue(void *pData, SConnection *pCon, float fTarget){
|
|||||||
iRet = Tcl_Eval(pServ->pSics->pTcl,Tcl_DStringValue(&command));
|
iRet = Tcl_Eval(pServ->pSics->pTcl,Tcl_DStringValue(&command));
|
||||||
if(iRet != TCL_OK){
|
if(iRet != TCL_OK){
|
||||||
SCWrite(pCon,"ERROR: Movement not possible or bad collider script",eError);
|
SCWrite(pCon,"ERROR: Movement not possible or bad collider script",eError);
|
||||||
|
SCWrite(pCon,Tcl_DStringValue(&command),eError);
|
||||||
/*
|
/*
|
||||||
SCWrite(pCon,pServ->pSics->pTcl->result,eError);
|
SCWrite(pCon,pServ->pSics->pTcl->result,eError);
|
||||||
*/
|
*/
|
||||||
|
85
conman.c
85
conman.c
@ -39,6 +39,8 @@
|
|||||||
fields.
|
fields.
|
||||||
Mark Koennecke, December 2004
|
Mark Koennecke, December 2004
|
||||||
|
|
||||||
|
Aded buffering support, Mark Koennecke, July 2006
|
||||||
|
|
||||||
Copyright: see copyright.h
|
Copyright: see copyright.h
|
||||||
-----------------------------------------------------------------------------*/
|
-----------------------------------------------------------------------------*/
|
||||||
#include "fortify.h"
|
#include "fortify.h"
|
||||||
@ -92,6 +94,8 @@ extern pServer pServ;
|
|||||||
static int iName = 0;
|
static int iName = 0;
|
||||||
static SConnection *freeConnections = NULL;
|
static SConnection *freeConnections = NULL;
|
||||||
static long lastIdent = 0;
|
static long lastIdent = 0;
|
||||||
|
/*------------- sending connection (prevent double write when listening) ----*/
|
||||||
|
static SConnection *sendingConnection = NULL;
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
static char *ConName(long ident) {
|
static char *ConName(long ident) {
|
||||||
static char name[32];
|
static char name[32];
|
||||||
@ -457,6 +461,11 @@ extern pServer pServ;
|
|||||||
DeleteCommandStack(pVictim->pStack);
|
DeleteCommandStack(pVictim->pStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* remove possible buffers */
|
||||||
|
if(pVictim->data != NULL)
|
||||||
|
{
|
||||||
|
DeleteDynString(pVictim->data);
|
||||||
|
}
|
||||||
|
|
||||||
pVictim->lMagic=0; /* make a write to a freed connection harmless */
|
pVictim->lMagic=0; /* make a write to a freed connection harmless */
|
||||||
/* finally free pVictim*/
|
/* finally free pVictim*/
|
||||||
@ -692,11 +701,22 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
|||||||
SICSLogWrite(buffer,iOut);
|
SICSLogWrite(buffer,iOut);
|
||||||
|
|
||||||
/* write to commandlog if user or manager privilege */
|
/* write to commandlog if user or manager privilege */
|
||||||
if(SCGetRights(self) <= usUser && self->iMacro != 1)
|
if(SCGetRights(self) <= usUser)
|
||||||
|
{
|
||||||
|
if(self->iMacro != 1)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"To sock %d :",iRet);
|
sprintf(pBueffel,"To sock %d :",iRet);
|
||||||
WriteToCommandLog(pBueffel,buffer);
|
WriteToCommandLog(pBueffel,buffer);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(iOut == eError || iOut == eWarning)
|
||||||
|
{
|
||||||
|
sprintf(pBueffel,"To sock %d :",iRet);
|
||||||
|
WriteToCommandLog(pBueffel,buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* put it into the interpreter if present */
|
/* put it into the interpreter if present */
|
||||||
if(SCinMacro(self))
|
if(SCinMacro(self))
|
||||||
@ -754,7 +774,9 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
|||||||
if(SCGetRights(self) <= usUser && self->iMacro != 1)
|
if(SCGetRights(self) <= usUser && self->iMacro != 1)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"To sock %d :",iRet);
|
sprintf(pBueffel,"To sock %d :",iRet);
|
||||||
|
sendingConnection = self;
|
||||||
WriteToCommandLog(pBueffel,buffer);
|
WriteToCommandLog(pBueffel,buffer);
|
||||||
|
sendingConnection = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -809,6 +831,52 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
|||||||
free(bufPtr);
|
free(bufPtr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int SCBufferWrite(SConnection *self, char *buffer, int iOut)
|
||||||
|
{
|
||||||
|
if(!VerifyConnection(self))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
assert(self->data != NULL);
|
||||||
|
DynStringConcat(self->data,buffer);
|
||||||
|
if(strchr(buffer,'\n') == NULL){
|
||||||
|
DynStringConcat(self->data,"\n");
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
int SCStartBuffering(SConnection *pCon)
|
||||||
|
{
|
||||||
|
if(!VerifyConnection(pCon))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(pCon->data != NULL)
|
||||||
|
{
|
||||||
|
DeleteDynString(pCon->data);
|
||||||
|
}
|
||||||
|
pCon->data = CreateDynString(128,128);
|
||||||
|
if(pCon->data == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pCon->oldWriteFunc = pCon->write;
|
||||||
|
pCon->write = SCBufferWrite;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
pDynString SCEndBuffering(SConnection *pCon)
|
||||||
|
{
|
||||||
|
if(!VerifyConnection(pCon))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
assert(pCon->oldWriteFunc != NULL);
|
||||||
|
pCon->write = pCon->oldWriteFunc;
|
||||||
|
pCon->oldWriteFunc = NULL;
|
||||||
|
return pCon->data;
|
||||||
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
int SCOnlySockWrite(SConnection *self, char *buffer, int iOut)
|
int SCOnlySockWrite(SConnection *self, char *buffer, int iOut)
|
||||||
{
|
{
|
||||||
@ -1378,7 +1446,16 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
|||||||
{
|
{
|
||||||
strcat(pBueffel,"CONT or CRON>> ");
|
strcat(pBueffel,"CONT or CRON>> ");
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* This is a fix to suppress cron messages in the success
|
||||||
|
* case
|
||||||
|
*/
|
||||||
|
if(SCGetWriteFunc(self) != SCNotWrite)
|
||||||
|
{
|
||||||
|
sendingConnection = self;
|
||||||
WriteToCommandLog(pBueffel,pCommand);
|
WriteToCommandLog(pBueffel,pCommand);
|
||||||
|
sendingConnection = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* invoke */
|
/* invoke */
|
||||||
@ -1900,8 +1977,8 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
|||||||
SCSetRights(self,iRet);
|
SCSetRights(self,iRet);
|
||||||
pHost[0] = '\0';
|
pHost[0] = '\0';
|
||||||
NETInfo(self->pSock,pHost,131);
|
NETInfo(self->pSock,pHost,131);
|
||||||
sprintf(pBueffel,"Accepted connection on socket %d from %s",
|
sprintf(pBueffel,"Accepted connection %s on socket %d from %s",
|
||||||
self->pSock->sockid, pHost);
|
ConName(self->ident), self->pSock->sockid, pHost);
|
||||||
SICSLogWrite(pBueffel,eInternal);
|
SICSLogWrite(pBueffel,eInternal);
|
||||||
WriteToCommandLog("SYS >", pBueffel);
|
WriteToCommandLog("SYS >", pBueffel);
|
||||||
free(pPtr);
|
free(pPtr);
|
||||||
@ -1965,7 +2042,7 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
|||||||
else if(iSignal == COMLOG && self->listening == 1)
|
else if(iSignal == COMLOG && self->listening == 1)
|
||||||
{
|
{
|
||||||
pPtr = (char *)pSigData;
|
pPtr = (char *)pSigData;
|
||||||
if(pPtr != NULL)
|
if(pPtr != NULL && self != sendingConnection)
|
||||||
{
|
{
|
||||||
doSockWrite(self,pPtr);
|
doSockWrite(self,pPtr);
|
||||||
}
|
}
|
||||||
|
10
conman.h
10
conman.h
@ -24,6 +24,7 @@
|
|||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "obdes.h"
|
#include "obdes.h"
|
||||||
#include "commandcontext.h"
|
#include "commandcontext.h"
|
||||||
|
#include "dynstring.h"
|
||||||
|
|
||||||
#define MAXLOGFILES 10
|
#define MAXLOGFILES 10
|
||||||
|
|
||||||
@ -60,6 +61,12 @@ typedef int (*writeFunc)(struct __SConnection *pCon,
|
|||||||
int parameterChange;
|
int parameterChange;
|
||||||
int sicsError;
|
int sicsError;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* for I/O Buffering
|
||||||
|
*/
|
||||||
|
pDynString data;
|
||||||
|
writeFunc oldWriteFunc;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
stuff supporting the sycamore protocol and a
|
stuff supporting the sycamore protocol and a
|
||||||
command context
|
command context
|
||||||
@ -116,6 +123,9 @@ typedef int (*writeFunc)(struct __SConnection *pCon,
|
|||||||
int SCNotWrite(SConnection *self, char *buffer, int iOut);
|
int SCNotWrite(SConnection *self, char *buffer, int iOut);
|
||||||
int SCNormalWrite(SConnection *self, char *buffer, int iOut);
|
int SCNormalWrite(SConnection *self, char *buffer, int iOut);
|
||||||
int SCWriteWithOutcode(SConnection *self, char *buffer, int iOut);
|
int SCWriteWithOutcode(SConnection *self, char *buffer, int iOut);
|
||||||
|
/*********************** I/O Buffering ***********************************/
|
||||||
|
int SCStartBuffering(SConnection *pCon);
|
||||||
|
pDynString SCEndBuffering(SConnection *pCon);
|
||||||
/************************* CallBack *********************************** */
|
/************************* CallBack *********************************** */
|
||||||
int SCRegister(SConnection *pCon, SicsInterp *pSics,
|
int SCRegister(SConnection *pCon, SicsInterp *pSics,
|
||||||
void *pInter, long lID);
|
void *pInter, long lID);
|
||||||
|
@ -88,4 +88,10 @@
|
|||||||
* file: mcstascounter.c
|
* file: mcstascounter.c
|
||||||
*/
|
*/
|
||||||
pCounterDriver NewMcStasCounter(char *name);
|
pCounterDriver NewMcStasCounter(char *name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* for regression testing
|
||||||
|
* file: regresscter.c
|
||||||
|
*/
|
||||||
|
pCounterDriver NewRegressCounter(char *name);
|
||||||
#endif
|
#endif
|
||||||
|
10
counter.c
10
counter.c
@ -314,7 +314,7 @@
|
|||||||
for(i = 0; i < 3; i++)
|
for(i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
iRet = self->pDriv->ReadValues(self->pDriv);
|
iRet = self->pDriv->ReadValues(self->pDriv);
|
||||||
if(iRet)
|
if(iRet == OKOK)
|
||||||
{
|
{
|
||||||
self->isUpToDate = 1;
|
self->isUpToDate = 1;
|
||||||
return OKOK;
|
return OKOK;
|
||||||
@ -529,6 +529,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* test for regression testing counter
|
||||||
|
*/
|
||||||
|
if(strcmp(argv[2],"regress") == 0){
|
||||||
|
pDriv = NewRegressCounter(argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* test for McStas simulation counter driver
|
* test for McStas simulation counter driver
|
||||||
*/
|
*/
|
||||||
@ -907,6 +914,7 @@
|
|||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
return 1;
|
return 1;
|
||||||
case 11: /* status */
|
case 11: /* status */
|
||||||
|
self->pCountInt->TransferData(self,pCon);
|
||||||
if(GetCounterMode(self) == ePreset)
|
if(GetCounterMode(self) == ePreset)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"%s.CountStatus = %d %d Beam: %ld E6",
|
sprintf(pBueffel,"%s.CountStatus = %d %d Beam: %ld E6",
|
||||||
|
32
devexec.c
32
devexec.c
@ -70,18 +70,23 @@ static FILE *devLog = NULL;
|
|||||||
int openDevexecLog(){
|
int openDevexecLog(){
|
||||||
char *fileName = NULL;
|
char *fileName = NULL;
|
||||||
char fileBuffer[1024];
|
char fileBuffer[1024];
|
||||||
|
time_t iDate;
|
||||||
|
struct tm *psTime;
|
||||||
|
|
||||||
|
|
||||||
if(devLog == NULL){
|
if(devLog == NULL){
|
||||||
fileName = IFindOption(pSICSOptions,"devexeclog");
|
fileName = IFindOption(pSICSOptions,"devexeclog");
|
||||||
if(fileName != NULL){
|
if(fileName != NULL){
|
||||||
strcpy(fileBuffer,fileName);
|
strcpy(fileBuffer,fileName);
|
||||||
} else {
|
} else {
|
||||||
|
iDate = time(NULL);
|
||||||
|
psTime = localtime(&iDate);
|
||||||
fileBuffer[0] = '\0';
|
fileBuffer[0] = '\0';
|
||||||
fileName = getenv("HOME");
|
fileName = getenv("HOME");
|
||||||
if(fileName != NULL){
|
if(fileName != NULL){
|
||||||
strcpy(fileBuffer,fileName);
|
snprintf(fileBuffer,1023,"%s/log/devexec%4.4d.log",
|
||||||
|
fileName, psTime->tm_year + 1900);
|
||||||
}
|
}
|
||||||
strcat(fileBuffer,"/log/devexec.log");
|
|
||||||
}
|
}
|
||||||
devLog = fopen(fileBuffer,"a+");
|
devLog = fopen(fileBuffer,"a+");
|
||||||
}
|
}
|
||||||
@ -168,6 +173,20 @@ typedef struct {
|
|||||||
} ExeList;
|
} ExeList;
|
||||||
|
|
||||||
static pExeList pExecutor = NULL;
|
static pExeList pExecutor = NULL;
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static void *DevexecInterface(void *pData, int iInter)
|
||||||
|
{
|
||||||
|
pExeList self = NULL;
|
||||||
|
|
||||||
|
self = (pExeList)pData;
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
if(iInter == CALLBACKINTERFACE)
|
||||||
|
{
|
||||||
|
return self->pCall;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
pExeList CreateExeList(pTaskMan pTask)
|
pExeList CreateExeList(pTaskMan pTask)
|
||||||
{
|
{
|
||||||
@ -200,8 +219,10 @@ typedef struct {
|
|||||||
pRes->lTask = -1;
|
pRes->lTask = -1;
|
||||||
pRes->iLock = 0;
|
pRes->iLock = 0;
|
||||||
pRes->drivePrint = 0;
|
pRes->drivePrint = 0;
|
||||||
|
pRes->paused = 0;
|
||||||
pRes->pCall = CreateCallBackInterface();
|
pRes->pCall = CreateCallBackInterface();
|
||||||
pRes->lastRun = time(NULL);
|
pRes->lastRun = time(NULL);
|
||||||
|
pRes->pDes->GetInterface = DevexecInterface;
|
||||||
return pRes;
|
return pRes;
|
||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
@ -508,7 +529,7 @@ typedef struct {
|
|||||||
ExeInterest(self, pDev, "finished");
|
ExeInterest(self, pDev, "finished");
|
||||||
DeleteDevEntry(pDev);
|
DeleteDevEntry(pDev);
|
||||||
LLDnodeDelete(self->iList);
|
LLDnodeDelete(self->iList);
|
||||||
SCWrite(pCon, "Finished", eFinish);
|
SCWrite(pCon, "", eFinish);
|
||||||
iRet = LLDnodePtr2Prev(self->iList);
|
iRet = LLDnodePtr2Prev(self->iList);
|
||||||
if(SCGetInterrupt(self->pOwner) != eContinue)
|
if(SCGetInterrupt(self->pOwner) != eContinue)
|
||||||
{
|
{
|
||||||
@ -667,7 +688,6 @@ static int errorDevice(pCheckContext pCheck){
|
|||||||
|
|
||||||
ExeInterest(pCheck->self, pCheck->pDev, "finished with problem");
|
ExeInterest(pCheck->self, pCheck->pDev, "finished with problem");
|
||||||
DevexecLog("STOP",pCheck->pDev->name);
|
DevexecLog("STOP",pCheck->pDev->name);
|
||||||
DeleteDevEntry(pCheck->pDev);
|
|
||||||
LLDnodeDelete(pCheck->self->iList);
|
LLDnodeDelete(pCheck->self->iList);
|
||||||
status = LLDnodePtr2Prev(pCheck->self->iList);
|
status = LLDnodePtr2Prev(pCheck->self->iList);
|
||||||
SCWrite(pCheck->self->pOwner, "", eFinish);
|
SCWrite(pCheck->self->pOwner, "", eFinish);
|
||||||
@ -675,7 +695,9 @@ static int errorDevice(pCheckContext pCheck){
|
|||||||
if(pCheck->pDrivInt != NULL) {
|
if(pCheck->pDrivInt != NULL) {
|
||||||
pCheck->pDrivInt->iErrorCount++;
|
pCheck->pDrivInt->iErrorCount++;
|
||||||
}
|
}
|
||||||
return checkInterrupt(pCheck,status);
|
status = checkInterrupt(pCheck,status);
|
||||||
|
DeleteDevEntry(pCheck->pDev);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
static int testFinish(pExeList self){
|
static int testFinish(pExeList self){
|
||||||
|
10
devexec.h
10
devexec.h
@ -118,6 +118,8 @@
|
|||||||
#line 259 "devexec.w"
|
#line 259 "devexec.w"
|
||||||
|
|
||||||
/*-------------------------- Commands ------------------------------------*/
|
/*-------------------------- Commands ------------------------------------*/
|
||||||
|
int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]);
|
||||||
int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,
|
int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
/*
|
/*
|
||||||
@ -152,11 +154,7 @@
|
|||||||
/*
|
/*
|
||||||
continues execution
|
continues execution
|
||||||
*/
|
*/
|
||||||
int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
||||||
int argc, char *argv[]);
|
|
||||||
/*
|
|
||||||
* various commands
|
|
||||||
*/
|
|
||||||
/*--------------------------- Locking ---------------------------------*/
|
/*--------------------------- Locking ---------------------------------*/
|
||||||
|
|
||||||
#line 183 "devexec.w"
|
#line 183 "devexec.w"
|
||||||
@ -165,7 +163,7 @@
|
|||||||
void UnlockDeviceExecutor(pExeList self);
|
void UnlockDeviceExecutor(pExeList self);
|
||||||
|
|
||||||
|
|
||||||
#line 297 "devexec.w"
|
#line 299 "devexec.w"
|
||||||
|
|
||||||
/* -------------------------- Executor management -------------------------*/
|
/* -------------------------- Executor management -------------------------*/
|
||||||
|
|
||||||
|
@ -312,6 +312,8 @@ to the global SICS device executor.
|
|||||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||||
\mbox{}\verb@@$\langle$devstop {\footnotesize ?}$\rangle$\verb@@\\
|
\mbox{}\verb@@$\langle$devstop {\footnotesize ?}$\rangle$\verb@@\\
|
||||||
\mbox{}\verb@/*-------------------------- Commands ------------------------------------*/@\\
|
\mbox{}\verb@/*-------------------------- Commands ------------------------------------*/@\\
|
||||||
|
\mbox{}\verb@ int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||||
|
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||||
\mbox{}\verb@ int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
\mbox{}\verb@ int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||||
\mbox{}\verb@ /*@\\
|
\mbox{}\verb@ /*@\\
|
||||||
|
@ -258,6 +258,8 @@ to the global SICS device executor.
|
|||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
@<devstop@>
|
@<devstop@>
|
||||||
/*-------------------------- Commands ------------------------------------*/
|
/*-------------------------- Commands ------------------------------------*/
|
||||||
|
int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]);
|
||||||
int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,
|
int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
/*
|
/*
|
||||||
|
@ -104,7 +104,7 @@ the dictionary file:
|
|||||||
would denote the normal counting tube at a scanning type of
|
would denote the normal counting tube at a scanning type of
|
||||||
experiment.
|
experiment.
|
||||||
</dl>
|
</dl>
|
||||||
<dt>nxscript puthm hmAlias hmName ?start? ?length?
|
<dt>nxscript puthm hmAlias hmName ?start? ?length? ?bank?
|
||||||
<dd>Writes data from the histogram memory hmName to a NeXus file using
|
<dd>Writes data from the histogram memory hmName to a NeXus file using
|
||||||
the alias hmAlias. Nxscript automatically updates the dim0, dim1, ..., timedim
|
the alias hmAlias. Nxscript automatically updates the dim0, dim1, ..., timedim
|
||||||
dictionary variables. Thus these can be used to define the dimensions in the
|
dictionary variables. Thus these can be used to define the dimensions in the
|
||||||
@ -116,7 +116,9 @@ subset writing, the dimensions have to be specified in the definition
|
|||||||
string belonging to the alias. Nxscript sets a variable timedim in the
|
string belonging to the alias. Nxscript sets a variable timedim in the
|
||||||
dictionary though which contains the length of a time binning if
|
dictionary though which contains the length of a time binning if
|
||||||
appropriate. This is a special feauture for writing extra detectors at
|
appropriate. This is a special feauture for writing extra detectors at
|
||||||
SANS and AMOR.
|
SANS and AMOR. Optionally, together with start and length, a bank number can
|
||||||
|
be given. This is a feauture to support the rare case of having multiple banks
|
||||||
|
in one histogram memory. If not give bank defaults to 0.
|
||||||
<dt>nxscript puttimebinning aliasName hmName
|
<dt>nxscript puttimebinning aliasName hmName
|
||||||
<dd>Writes the time binning at histogram memory hmName to file using
|
<dd>Writes the time binning at histogram memory hmName to file using
|
||||||
the alias aliasName. The length of the time binning data is
|
the alias aliasName. The length of the time binning data is
|
||||||
@ -125,11 +127,19 @@ automatically appended to the definition string for the alias.
|
|||||||
<dd>Writes the Tcl array arrayName to file using the aliasName. The
|
<dd>Writes the Tcl array arrayName to file using the aliasName. The
|
||||||
definiton string belonging to aliasName does not need to contain a
|
definiton string belonging to aliasName does not need to contain a
|
||||||
-dim argument as this is set by this routine. The parameter length is
|
-dim argument as this is set by this routine. The parameter length is
|
||||||
the length of the array. Only rank 1 arrays are supported.
|
the length of the array. Only rank 1 arrays are supported. The array is
|
||||||
|
considered a float array.
|
||||||
|
<dt>nxscript putintarray aliasName arrayName length
|
||||||
|
<dd>The same as above, but the data is considered integer.
|
||||||
<dt>nxsript putglobal attName bla bla bla
|
<dt>nxsript putglobal attName bla bla bla
|
||||||
<dd>This writes an global attribute attName. Everything after attName
|
<dd>This writes an global attribute attName. Everything after attName
|
||||||
is concatenated to a string which then respresents the value of the
|
is concatenated to a string which then respresents the value of the
|
||||||
attribute.
|
attribute.
|
||||||
|
<dt>nxscript putsicsdata alias dataname
|
||||||
|
<dd>Writes the sicsdata array dataname to alias.
|
||||||
|
<dt>nxscript putattribute alias name value
|
||||||
|
<dd>Add another text attribute to alias. The name of the attribute is name, the
|
||||||
|
value value.
|
||||||
<dt>nxscript makelink targetAlias victimAlias
|
<dt>nxscript makelink targetAlias victimAlias
|
||||||
<dd>This creates a symbolic link for victimAlias in the group
|
<dd>This creates a symbolic link for victimAlias in the group
|
||||||
designated by targetAlias.
|
designated by targetAlias.
|
||||||
|
@ -65,6 +65,9 @@ file.
|
|||||||
<dt>updateintervall
|
<dt>updateintervall
|
||||||
<dd>The time intervall in seconds between updates. The defualt is
|
<dd>The time intervall in seconds between updates. The defualt is
|
||||||
1200, eg. 20 minutes.
|
1200, eg. 20 minutes.
|
||||||
|
<dt>onoff
|
||||||
|
<dd>can be 1 or 0. Switches automatic updates on or off. It might be usefule for
|
||||||
|
scans to switch this off.
|
||||||
</dl>
|
</dl>
|
||||||
</p>
|
</p>
|
||||||
</BODY>
|
</BODY>
|
||||||
|
@ -21,6 +21,37 @@ The TAS requires the following initializations in its instrument file:
|
|||||||
<dt>MakeTasUB tasub
|
<dt>MakeTasUB tasub
|
||||||
<dd>Installs the TAS crystallographic calculation module into SICS. It will
|
<dd>Installs the TAS crystallographic calculation module into SICS. It will
|
||||||
have the name tasub (recommended).
|
have the name tasub (recommended).
|
||||||
|
<dt>MakeTasUB tasub a1 a2 mcv mch a3 a4 sgu sgl a5 a6 acv ach
|
||||||
|
<dd>Installs the TAS crystallographic calculation module into SICS. It will
|
||||||
|
have the name tasub (recommended). This versions allows to specifiy motor names for functions. If there is no motor for
|
||||||
|
a function it can be replaced with a placeholder in the parameter list, like dummy. This is only allowed for the
|
||||||
|
curvature motors. The motor functions:
|
||||||
|
<dl>
|
||||||
|
<dt>a1
|
||||||
|
<dd>monochormator rotation
|
||||||
|
<dt>a2
|
||||||
|
<dd>monochromator two theta
|
||||||
|
<dt>mcv
|
||||||
|
<dd>monochromator vertical curvature
|
||||||
|
<dt>mch
|
||||||
|
<dd>monochromator horizontal curvature
|
||||||
|
<dt>a3
|
||||||
|
<dd> sample rotation
|
||||||
|
<dt>a4
|
||||||
|
<dd>sample tow theta
|
||||||
|
<dt>sgu
|
||||||
|
<dd>sample tilt
|
||||||
|
<dt>sgl
|
||||||
|
<dd>second sample tilt
|
||||||
|
<dt>a5
|
||||||
|
<dd>analyzer rotation
|
||||||
|
<dt>a6
|
||||||
|
<dd>analyzer two theta
|
||||||
|
<dt>acv
|
||||||
|
<dd>analyzer vertical curvature
|
||||||
|
<dt>ach
|
||||||
|
<dd>analyzer horizontal curvature
|
||||||
|
</dl>
|
||||||
<dt>MakeTasScan iscan tasub
|
<dt>MakeTasScan iscan tasub
|
||||||
<dd>Installs the module with the TAS specific scan functions into SICS. The
|
<dd>Installs the module with the TAS specific scan functions into SICS. The
|
||||||
TAS implements its own data format resembling the ILL TAS data format.
|
TAS implements its own data format resembling the ILL TAS data format.
|
||||||
|
@ -35,6 +35,11 @@ started. In order to make this work a ServerOption with the name logstartfile
|
|||||||
must exist in the instrument configuration file. The value of this option
|
must exist in the instrument configuration file. The value of this option
|
||||||
must be the full path name of the file to execute.
|
must be the full path name of the file to execute.
|
||||||
</P>
|
</P>
|
||||||
|
<p>
|
||||||
|
<b>Note:</b> with the command <it>config listen 1</it> you can have the output
|
||||||
|
to the command log printed into your client, too. With <it>config listen 0</it> you can switch this off again. This is useful for listening into a running
|
||||||
|
instrument.
|
||||||
|
</p>
|
||||||
</BODY>
|
</BODY>
|
||||||
</HTML>
|
</HTML>
|
||||||
|
|
||||||
|
@ -45,6 +45,13 @@ named buffer within the stack of nested buffers.
|
|||||||
<dt>Clears the queue of batch buffers
|
<dt>Clears the queue of batch buffers
|
||||||
<dt>exe queue
|
<dt>exe queue
|
||||||
<dd>Prints the content of the batch buffer queue.
|
<dd>Prints the content of the batch buffer queue.
|
||||||
|
<dt>exe fullpath filename
|
||||||
|
<dd>Prints the full path name for filename if the file can be located
|
||||||
|
somewhere in exe paths. Else an error is printed. The purpose is to use
|
||||||
|
exe file management facilties in scripts.
|
||||||
|
<dt>exe makepath filename
|
||||||
|
<dd>Prints the full path name for filename in the first direcory of batch path.
|
||||||
|
This is a tool to have scripts open files in the proper user directory.
|
||||||
<dt>exe run
|
<dt>exe run
|
||||||
<dd>Starts executing the batch buffers in the queue.
|
<dd>Starts executing the batch buffers in the queue.
|
||||||
<dt>exe print buffername
|
<dt>exe print buffername
|
||||||
@ -58,7 +65,12 @@ most useful for SICS clients watching the progress of the experiment.
|
|||||||
<dt>exe append some text
|
<dt>exe append some text
|
||||||
<dd> Appends a line with everything after append to the upload buffer
|
<dd> Appends a line with everything after append to the upload buffer
|
||||||
<dt>exe save filename
|
<dt>exe save filename
|
||||||
<dd>saves the recently uploaded buffer under filename on the SICS server.
|
<dd>saves the recently uploaded buffer under filename on the SICS server. Does not overwrite
|
||||||
|
existing files.
|
||||||
|
<dt>exe forcesave filename
|
||||||
|
<dd>saves the recently uploaded buffer under filename on the SICS server. Overwrites existing file.
|
||||||
|
<dt>exe clearupload
|
||||||
|
<dd>clears any pending upload operations.
|
||||||
</dl>
|
</dl>
|
||||||
</P>
|
</P>
|
||||||
</BODY>
|
</BODY>
|
||||||
|
@ -29,6 +29,18 @@ maximum number of cycles was reached. This routine requires that the
|
|||||||
instrument is currently placed somewhere on the peak and not miles away.
|
instrument is currently placed somewhere on the peak and not miles away.
|
||||||
</P>
|
</P>
|
||||||
<p>
|
<p>
|
||||||
|
The peak optimiser supports another optimisation algorithm which is faster but
|
||||||
|
may not be as accurate. This is hill climbing:
|
||||||
|
<pre>
|
||||||
|
while errors gt precision and cycles lt maxcycles
|
||||||
|
for all variables
|
||||||
|
find the direction into which the intensity rises
|
||||||
|
step into this direction until the intensity drops
|
||||||
|
end for
|
||||||
|
end while
|
||||||
|
</pre>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
The Peak Optimiser is implemented as an object with the name opti. It
|
The Peak Optimiser is implemented as an object with the name opti. It
|
||||||
understand the following commands:
|
understand the following commands:
|
||||||
<DL>
|
<DL>
|
||||||
@ -43,7 +55,10 @@ and number of steps parameters should cover the whole peak. However, the
|
|||||||
Optimiser will extend the scan is the specified range is not sufficient.
|
Optimiser will extend the scan is the specified range is not sufficient.
|
||||||
<DT>opti run
|
<DT>opti run
|
||||||
<DD>Starts the optimiser. It will then optimise the peak. This may take some
|
<DD>Starts the optimiser. It will then optimise the peak. This may take some
|
||||||
time.
|
time as it uses a time consuming scan based algorithm.
|
||||||
|
<DT>opti climb
|
||||||
|
<DD>Starts the optimiser in hill climbing mode. Hill climbing is faster but may
|
||||||
|
not be as accurate as a scan based optimization.
|
||||||
</DL>
|
</DL>
|
||||||
The behaviour of the optimiser can be configured by modifying some
|
The behaviour of the optimiser can be configured by modifying some
|
||||||
parameters. The synatx is easy: <b>opti parameter</b> prints the value of the
|
parameters. The synatx is easy: <b>opti parameter</b> prints the value of the
|
||||||
@ -72,5 +87,12 @@ status of the countmode parameter this is either a preset time or a preset
|
|||||||
monitor.
|
monitor.
|
||||||
</DL>
|
</DL>
|
||||||
</p>
|
</p>
|
||||||
|
<p>
|
||||||
|
It is the users reponsability to provide meaningful step widths. Usually this is
|
||||||
|
dependent on the instrument resolution and thus fairly constant. Also these
|
||||||
|
optimisation algorithms will fail if the instrument is not positioned at the
|
||||||
|
flank of a peak. Probaly the best will be to do several cycles of hill
|
||||||
|
climbing first, followed by one cycle of scan optimisation for extra accuracy.
|
||||||
|
</p>
|
||||||
</BODY>
|
</BODY>
|
||||||
</HTML>
|
</HTML>
|
||||||
|
5284
doc/user/sansdocbook.xml
Normal file
5284
doc/user/sansdocbook.xml
Normal file
File diff suppressed because it is too large
Load Diff
@ -81,6 +81,12 @@ In order to calculate a UB matrix a list of reflections must be maintained. This
|
|||||||
<dd>Add a new reflection to the list. Besides the indices all angles are given:
|
<dd>Add a new reflection to the list. Besides the indices all angles are given:
|
||||||
a3, the sample rotation, a4, sample two theta, sgu, upper tilt cradle, sgl, lower tilt
|
a3, the sample rotation, a4, sample two theta, sgu, upper tilt cradle, sgl, lower tilt
|
||||||
cradle and incoming energey ei and outgoing energy ef.
|
cradle and incoming energey ei and outgoing energy ef.
|
||||||
|
<dt>tasub addauxref qh qk ql
|
||||||
|
<dd>Adds an auxiliary reflection with indices qh, qk, ql to the list. A4 is
|
||||||
|
calculated from cell constants. A3 is either left alone or is calculated to
|
||||||
|
have the correct angular difference to a previous reflection. This is a help
|
||||||
|
for setting up the instrument or running powder mode. When a UB has been
|
||||||
|
generated from auxiliary reflections, a3, sgu and sgl angles will be incorrect.
|
||||||
</dl>
|
</dl>
|
||||||
</p>
|
</p>
|
||||||
<h3>Calculations</h3>
|
<h3>Calculations</h3>
|
||||||
|
@ -971,12 +971,15 @@ static void ErrReport(pEVControl self)
|
|||||||
{
|
{
|
||||||
ObPar *pPar = NULL;
|
ObPar *pPar = NULL;
|
||||||
char pBueffel[512];
|
char pBueffel[512];
|
||||||
int iRet;
|
int iRet, savedStatus;
|
||||||
|
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(pCon);
|
assert(pCon);
|
||||||
|
|
||||||
|
savedStatus = GetStatus(); /* fool status check in ObParSet (avoid "Cannot change parameter while running" message */
|
||||||
|
SetStatus(eBatch);
|
||||||
iRet = ObParSet(self->pParam,self->pName,name,fVal,pCon);
|
iRet = ObParSet(self->pParam,self->pName,name,fVal,pCon);
|
||||||
|
SetStatus(savedStatus);
|
||||||
if(!iRet)
|
if(!iRet)
|
||||||
{
|
{
|
||||||
return iRet;
|
return iRet;
|
||||||
@ -1102,8 +1105,11 @@ static void ErrReport(pEVControl self)
|
|||||||
iRet = EVCGetPos(self,pCon,&fPos);
|
iRet = EVCGetPos(self,pCon,&fPos);
|
||||||
if(iRet)
|
if(iRet)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
sprintf(pBueffel,"%s.%s = %g",self->pName,"CurrentValue", fPos);
|
sprintf(pBueffel,"%s.%s = %g",self->pName,"CurrentValue", fPos);
|
||||||
SCWrite(pCon,pBueffel,eValue);
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
|
*/
|
||||||
|
SCPrintf(pCon, eValue, "%s = %g", self->pName, fPos);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
5
event.c
5
event.c
@ -64,6 +64,11 @@
|
|||||||
"BATCHAREA",
|
"BATCHAREA",
|
||||||
"BATCHEND",
|
"BATCHEND",
|
||||||
"DRIVSTAT",
|
"DRIVSTAT",
|
||||||
|
"STATUS",
|
||||||
|
"POSITION",
|
||||||
|
"HDBVAL",
|
||||||
|
"STATESTART",
|
||||||
|
"STATEEND",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
20
event.h
20
event.h
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#line 89 "event.w"
|
#line 103 "event.w"
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
E V E N T
|
E V E N T
|
||||||
@ -14,15 +14,15 @@
|
|||||||
#ifndef SICSEVENT
|
#ifndef SICSEVENT
|
||||||
#define SICSEVENT
|
#define SICSEVENT
|
||||||
|
|
||||||
#line 13 "event.w"
|
#line 14 "event.w"
|
||||||
|
|
||||||
int Text2Event(char *pText);
|
int Text2Event(char *pText);
|
||||||
|
|
||||||
#line 102 "event.w"
|
#line 116 "event.w"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#line 20 "event.w"
|
#line 21 "event.w"
|
||||||
|
|
||||||
#define VALUECHANGE 0
|
#define VALUECHANGE 0
|
||||||
#define MOTDRIVE 1
|
#define MOTDRIVE 1
|
||||||
@ -43,13 +43,17 @@
|
|||||||
#define BATCHEND 16
|
#define BATCHEND 16
|
||||||
#define DRIVSTAT 17
|
#define DRIVSTAT 17
|
||||||
#define STATUS 18
|
#define STATUS 18
|
||||||
#define POSITION 19 /* Position event for motors - ffr */
|
#define POSITION 19
|
||||||
#line 104 "event.w"
|
#define HDBVAL 20
|
||||||
|
#define STSTART 21
|
||||||
|
#define STEND 22
|
||||||
|
|
||||||
|
#line 118 "event.w"
|
||||||
|
|
||||||
|
|
||||||
/*--------------- Signals for the Signalfunction of each task ------------*/
|
/*--------------- Signals for the Signalfunction of each task ------------*/
|
||||||
|
|
||||||
#line 73 "event.w"
|
#line 87 "event.w"
|
||||||
|
|
||||||
#define SICSINT 300
|
#define SICSINT 300
|
||||||
#define SICSBROADCAST 301
|
#define SICSBROADCAST 301
|
||||||
@ -57,6 +61,6 @@
|
|||||||
#define TOKENRELEASE 303
|
#define TOKENRELEASE 303
|
||||||
#define COMLOG 304
|
#define COMLOG 304
|
||||||
|
|
||||||
#line 107 "event.w"
|
#line 121 "event.w"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -53,6 +53,9 @@ $\langle$VE {\footnotesize ?}$\rangle\equiv$
|
|||||||
\mbox{}\verb@#define BATCHAREA 15@\\
|
\mbox{}\verb@#define BATCHAREA 15@\\
|
||||||
\mbox{}\verb@#define BATCHEND 16@\\
|
\mbox{}\verb@#define BATCHEND 16@\\
|
||||||
\mbox{}\verb@#define DRIVSTAT 17@\\
|
\mbox{}\verb@#define DRIVSTAT 17@\\
|
||||||
|
\mbox{}\verb@#define STATUS 18@\\
|
||||||
|
\mbox{}\verb@#define POSITION 19@\\
|
||||||
|
\mbox{}\verb@#define HDBVAL 20@\\
|
||||||
\mbox{}\verb@@$\diamond$
|
\mbox{}\verb@@$\diamond$
|
||||||
\end{list}
|
\end{list}
|
||||||
\vspace{-1ex}
|
\vspace{-1ex}
|
||||||
@ -87,6 +90,10 @@ operation.
|
|||||||
\item[BATCHEND] signals the end of the batch buffers processing.
|
\item[BATCHEND] signals the end of the batch buffers processing.
|
||||||
\item[DRIVSTAT] signals a change in the status of a driving operation
|
\item[DRIVSTAT] signals a change in the status of a driving operation
|
||||||
(start, finished, fault)
|
(start, finished, fault)
|
||||||
|
\item[STATUS] ANSTO defined code.
|
||||||
|
\item[POSITION] ANSTO defined code
|
||||||
|
\item[HDBVAL] The Hdb is notified of a value change. The eventData will be
|
||||||
|
the object on which the data changed.
|
||||||
\end{description}
|
\end{description}
|
||||||
|
|
||||||
Furthermore event contains system wide signal codes which are interpreted in
|
Furthermore event contains system wide signal codes which are interpreted in
|
||||||
|
7
event.w
7
event.w
@ -36,6 +36,9 @@ if the event code is not known, else the apropriate event code.
|
|||||||
#define BATCHAREA 15
|
#define BATCHAREA 15
|
||||||
#define BATCHEND 16
|
#define BATCHEND 16
|
||||||
#define DRIVSTAT 17
|
#define DRIVSTAT 17
|
||||||
|
#define STATUS 18
|
||||||
|
#define POSITION 19
|
||||||
|
#define HDBVAL 20
|
||||||
@}
|
@}
|
||||||
\begin{description}
|
\begin{description}
|
||||||
\item[VALUECHANGE] This is a variable changing its value. As event data a pointer to the
|
\item[VALUECHANGE] This is a variable changing its value. As event data a pointer to the
|
||||||
@ -62,6 +65,10 @@ operation.
|
|||||||
\item[BATCHEND] signals the end of the batch buffers processing.
|
\item[BATCHEND] signals the end of the batch buffers processing.
|
||||||
\item[DRIVSTAT] signals a change in the status of a driving operation
|
\item[DRIVSTAT] signals a change in the status of a driving operation
|
||||||
(start, finished, fault)
|
(start, finished, fault)
|
||||||
|
\item[STATUS] ANSTO defined code.
|
||||||
|
\item[POSITION] ANSTO defined code
|
||||||
|
\item[HDBVAL] The Hdb is notified of a value change. The eventData will be
|
||||||
|
the object on which the data changed.
|
||||||
\end{description}
|
\end{description}
|
||||||
|
|
||||||
Furthermore event contains system wide signal codes which are interpreted in
|
Furthermore event contains system wide signal codes which are interpreted in
|
||||||
|
1
exe.w
1
exe.w
@ -173,6 +173,7 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics,
|
int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics,
|
||||||
char *name);
|
char *name);
|
||||||
|
pDynString findBatchFile(SicsInterp *pSics, char *name);
|
||||||
@}
|
@}
|
||||||
|
|
||||||
@o exeman.i -d @{
|
@o exeman.i -d @{
|
||||||
|
4
exebuf.h
4
exebuf.h
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#line 209 "exe.w"
|
#line 210 "exe.w"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer handling code for the Exe Buffer batch file processing
|
* Buffer handling code for the Exe Buffer batch file processing
|
||||||
@ -89,7 +89,7 @@
|
|||||||
*/
|
*/
|
||||||
char *exeBufName(pExeBuf self);
|
char *exeBufName(pExeBuf self);
|
||||||
|
|
||||||
#line 222 "exe.w"
|
#line 223 "exe.w"
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
4
exebuf.i
4
exebuf.i
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#line 200 "exe.w"
|
#line 201 "exe.w"
|
||||||
|
|
||||||
/*--------------------------------------------------------------------
|
/*--------------------------------------------------------------------
|
||||||
Internal header file for the exe buffer module. Do not edit. This is
|
Internal header file for the exe buffer module. Do not edit. This is
|
||||||
@ -16,6 +16,6 @@ typedef struct __EXEBUF{
|
|||||||
int lineno;
|
int lineno;
|
||||||
} ExeBuf;
|
} ExeBuf;
|
||||||
|
|
||||||
#line 205 "exe.w"
|
#line 206 "exe.w"
|
||||||
|
|
||||||
|
|
||||||
|
56
exeman.c
56
exeman.c
@ -175,6 +175,43 @@ static pDynString locateBatchBuffer(pExeMan self, char *name){
|
|||||||
DeleteDynString(result);
|
DeleteDynString(result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/*-------------------------------------------------------------------
|
||||||
|
* Generate a full path name for the argument in the first
|
||||||
|
* directory of batch path
|
||||||
|
* -------------------------------------------------------------------*/
|
||||||
|
static int makeExePath(pExeMan self, SConnection *pCon, int argc, char *argv[]){
|
||||||
|
char buffer[512], *pPtr = NULL, pPath[132];
|
||||||
|
|
||||||
|
if(argc < 3) {
|
||||||
|
SCWrite(pCon,"ERROR: require a file name for makepath",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
strcpy(buffer,"exe.makepath = ");
|
||||||
|
/*
|
||||||
|
* do nothing to absolute path
|
||||||
|
*/
|
||||||
|
if(argv[2][0] == '/'){
|
||||||
|
strncat(buffer,argv[2],511-strlen(buffer));
|
||||||
|
SCWrite(pCon,buffer,eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
pPtr = self->batchPath;
|
||||||
|
pPtr = stptok(pPtr,pPath,131,":");
|
||||||
|
strncat(buffer,pPath,511-strlen(buffer));
|
||||||
|
strncat(buffer,"/",511-strlen(buffer));
|
||||||
|
strncat(buffer,argv[2],511-strlen(buffer));
|
||||||
|
SCWrite(pCon,buffer,eValue);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
pDynString findBatchFile(SicsInterp *pSics, char *name){
|
||||||
|
pExeMan self = (pExeMan)FindCommandData(pSics,"exe","ExeManager");
|
||||||
|
if(self == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return locateBatchBuffer(self,name);
|
||||||
|
}
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
static int runBatchBuffer(pExeMan self, SConnection *pCon,
|
static int runBatchBuffer(pExeMan self, SConnection *pCon,
|
||||||
SicsInterp *pSics, char *name){
|
SicsInterp *pSics, char *name){
|
||||||
@ -937,6 +974,7 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
char pBufferName[256];
|
char pBufferName[256];
|
||||||
int status;
|
int status;
|
||||||
pDynString dirList = NULL;
|
pDynString dirList = NULL;
|
||||||
|
pDynString fullPath = NULL;
|
||||||
|
|
||||||
self = (pExeMan)pData;
|
self = (pExeMan)pData;
|
||||||
assert(self != NULL);
|
assert(self != NULL);
|
||||||
@ -1012,6 +1050,24 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
SCWrite(pCon,"Nothing found",eValue);
|
SCWrite(pCon,"Nothing found",eValue);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
}else if(strcmp(argv[1],"fullpath") == 0){
|
||||||
|
if(argc < 2){
|
||||||
|
SCWrite(pCon,"ERROR: not enough arguments to exe fullpath",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
fullPath = locateBatchBuffer(self,argv[2]);
|
||||||
|
if(fullPath == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: buffer NOT found",eError);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
DynStringInsert(fullPath,"exe.fullpath=",0);
|
||||||
|
SCWrite(pCon,GetCharArray(fullPath),eValue);
|
||||||
|
DeleteDynString(fullPath);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}else if(strcmp(argv[1],"makepath") == 0){
|
||||||
|
return makeExePath(self,pCon,argc,argv);
|
||||||
}else if(strcmp(argv[1],"clear") == 0){
|
}else if(strcmp(argv[1],"clear") == 0){
|
||||||
clearQueue(self);
|
clearQueue(self);
|
||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
|
1
exeman.h
1
exeman.h
@ -15,5 +15,6 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics,
|
int runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics,
|
||||||
char *name);
|
char *name);
|
||||||
|
pDynString findBatchFile(SicsInterp *pSics, char *name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
4
exeman.i
4
exeman.i
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
#line 178 "exe.w"
|
#line 179 "exe.w"
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
/*-------------------------------------------------------------------
|
||||||
Internal header file for the exe manager module. Do not edit. This
|
Internal header file for the exe manager module. Do not edit. This
|
||||||
@ -20,5 +20,5 @@ typedef struct __EXEMAN{
|
|||||||
int echo;
|
int echo;
|
||||||
}ExeMan, *pExeMan;
|
}ExeMan, *pExeMan;
|
||||||
|
|
||||||
#line 183 "exe.w"
|
#line 184 "exe.w"
|
||||||
|
|
||||||
|
13
fitcenter.c
13
fitcenter.c
@ -421,6 +421,7 @@
|
|||||||
pFit self = NULL;
|
pFit self = NULL;
|
||||||
int iRet;
|
int iRet;
|
||||||
char pBueffel[256];
|
char pBueffel[256];
|
||||||
|
pDynString buf = NULL;
|
||||||
|
|
||||||
self = (pFit)pData;
|
self = (pFit)pData;
|
||||||
assert(self);
|
assert(self);
|
||||||
@ -467,9 +468,17 @@
|
|||||||
SCWrite(pCon,pBueffel,eValue);
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if(strcmp(argv[1],"data") == 0)
|
||||||
|
{
|
||||||
|
snprintf(pBueffel,255,"%f,%f,%ld",
|
||||||
|
self->fCenter, self->FWHM, self->lPeak);
|
||||||
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* print results */
|
/* print results */
|
||||||
|
SCStartBuffering(pCon);
|
||||||
sprintf(pBueffel,"Estimated Peak Center: %f, StdDev: %f \n",
|
sprintf(pBueffel,"Estimated Peak Center: %f, StdDev: %f \n",
|
||||||
self->fCenter,self->fStddev);
|
self->fCenter,self->fStddev);
|
||||||
SCWrite(pCon,pBueffel,eValue);
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
@ -477,6 +486,10 @@
|
|||||||
SCWrite(pCon,pBueffel,eValue);
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
sprintf(pBueffel,"Approximate FWHM: %f\n",self->FWHM);
|
sprintf(pBueffel,"Approximate FWHM: %f\n",self->FWHM);
|
||||||
SCWrite(pCon,pBueffel,eValue);
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
|
buf = SCEndBuffering(pCon);
|
||||||
|
if(buf != NULL){
|
||||||
|
SCWrite(pCon,GetCharArray(buf),eValue);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
24
fourlib.c
24
fourlib.c
@ -625,6 +625,10 @@ int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4],
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(testFunc(userData, fSet, mask) == 1){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
for(psi = .0; psi < 360.; psi += .5){
|
for(psi = .0; psi < 360.; psi += .5){
|
||||||
rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi);
|
rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi);
|
||||||
fTest[0] = stt;
|
fTest[0] = stt;
|
||||||
@ -638,6 +642,26 @@ int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4],
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* if chi close to 0, or 180, try to wrap phi onto om
|
||||||
|
*/
|
||||||
|
if(ABS(fTest[2] - .0) < .1 || ABS(fTest[2] - 180.) < .1){
|
||||||
|
fTest[1] -= fTest[3];
|
||||||
|
fTest[3] = .0;
|
||||||
|
if(fTest[1] < 0.){
|
||||||
|
fTest[1] += 360.;
|
||||||
|
}
|
||||||
|
if(fTest[1] > 360.0){
|
||||||
|
fTest[1] -= 360.;
|
||||||
|
}
|
||||||
|
status = testFunc(userData,fTest,mask);
|
||||||
|
if(status == 1){
|
||||||
|
for(i = 0; i < 4; i++){
|
||||||
|
fSet[i] = fTest[i];
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
if(mask[0] == 0) {
|
if(mask[0] == 0) {
|
||||||
/*
|
/*
|
||||||
* useless: when two theta problem there is no solution
|
* useless: when two theta problem there is no solution
|
||||||
|
291
hdbcommand.c
Normal file
291
hdbcommand.c
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
/**
|
||||||
|
* This module implements a generalized scheme for executing functions.
|
||||||
|
* Functions are described by a special data structure containing the
|
||||||
|
* parameters as a Hipadaba list and and an execute function which implements
|
||||||
|
* the actual operation. This is augmented by list mechanisms in order to
|
||||||
|
* allow for a list of functions. This shall facilitate a couple of things:
|
||||||
|
* - when functions are defined in such a structured form, general invocation
|
||||||
|
* functions can be devised for handling the interpreter interface.
|
||||||
|
* - The set of functions of an object can be configured and extended at
|
||||||
|
* runtime.
|
||||||
|
* - A common usage case: execute a function with the same arguments, can be
|
||||||
|
* easily catered for.
|
||||||
|
* All this is not new and was pioneered in the language self or other
|
||||||
|
* dynamic object systems.
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke, September 2006
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <hdbcommand.h>
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int debug = 1;
|
||||||
|
/* ============================= live and death ============================*/
|
||||||
|
pHdbCommand CreateHdbCommand(char *name, int (*execute)(pHdb parameters)){
|
||||||
|
pHdbCommand result = NULL;
|
||||||
|
|
||||||
|
assert(name != NULL);
|
||||||
|
assert(execute != NULL);
|
||||||
|
|
||||||
|
result = malloc(sizeof(hdbCommand));
|
||||||
|
if(result == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(result,0,sizeof(hdbCommand));
|
||||||
|
result->name = strdup(name);
|
||||||
|
if(result->name == NULL){
|
||||||
|
free(result);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
result->execute = execute;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
void AppendHdbCommandToList(pHdbCommand commandList, pHdbCommand command){
|
||||||
|
pHdbCommand current = NULL;
|
||||||
|
|
||||||
|
assert(commandList != NULL);
|
||||||
|
assert(command != NULL);
|
||||||
|
|
||||||
|
current = commandList;
|
||||||
|
while(current->next != NULL){
|
||||||
|
current = (pHdbCommand)current->next;
|
||||||
|
}
|
||||||
|
command->previous = (struct __hdbCommand *)current;
|
||||||
|
current->next = (struct __hdbCommand *)command;
|
||||||
|
command->next = NULL;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
void AppendCommandParameter(pHdbCommand command, pHdb par){
|
||||||
|
assert(command != NULL);
|
||||||
|
assert(par != NULL);
|
||||||
|
|
||||||
|
AddHipadabaChild(command->parameters,par,NULL);
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
void KillHdbCommandList(pHdbCommand commandList){
|
||||||
|
pHdbCommand next = NULL, current = NULL;
|
||||||
|
|
||||||
|
assert(commandList != NULL);
|
||||||
|
|
||||||
|
current = commandList;
|
||||||
|
next = (pHdbCommand)current->next;
|
||||||
|
while(current != NULL){
|
||||||
|
if(current->name != NULL){
|
||||||
|
free(current->name);
|
||||||
|
}
|
||||||
|
if(current->parameters != NULL){
|
||||||
|
DeleteHipadabaNode(current->parameters,NULL);
|
||||||
|
}
|
||||||
|
free(current);
|
||||||
|
current = next;
|
||||||
|
if(current != NULL){
|
||||||
|
next = (pHdbCommand)current->next;
|
||||||
|
} else {
|
||||||
|
next = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*======================= Invocation =======================================*/
|
||||||
|
static pHdbCommand locateCommand(pHdbCommand commandList, char *name){
|
||||||
|
pHdbCommand current = NULL;
|
||||||
|
|
||||||
|
current = commandList;
|
||||||
|
while(current != NULL){
|
||||||
|
if(strcmp(current->name,name) == 0) {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
current = (pHdbCommand)current->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int HdbCommandInvoke(pHdbCommand commandList, char *name, ...){
|
||||||
|
va_list ap;
|
||||||
|
pHdbCommand toInvoke = NULL;
|
||||||
|
pHdb currentPar = NULL;
|
||||||
|
char *txt = NULL;
|
||||||
|
hdbValue *v = NULL;
|
||||||
|
|
||||||
|
va_start(ap,name);
|
||||||
|
toInvoke = locateCommand(commandList,name);
|
||||||
|
if(toInvoke == NULL){
|
||||||
|
return HDBCOMNOCOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPar = toInvoke->parameters;
|
||||||
|
while(currentPar != NULL){
|
||||||
|
/*
|
||||||
|
* I cannot call a function for this as ap would be undefined after
|
||||||
|
* a call to a function here
|
||||||
|
*/
|
||||||
|
switch(currentPar->value.dataType){
|
||||||
|
case HIPNONE:
|
||||||
|
break;
|
||||||
|
case HIPINT:
|
||||||
|
currentPar->value.v.intValue = va_arg(ap,int);
|
||||||
|
if(debug == 1){
|
||||||
|
printf("Read %d for parameter %s\n",
|
||||||
|
currentPar->value.v.intValue, currentPar->name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HIPFLOAT:
|
||||||
|
currentPar->value.v.doubleValue = va_arg(ap,double);
|
||||||
|
if(debug == 1){
|
||||||
|
printf("Read %lf for parameter %s\n",
|
||||||
|
currentPar->value.v.doubleValue, currentPar->name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HIPTEXT:
|
||||||
|
txt = va_arg(ap,char *);
|
||||||
|
if(currentPar->value.v.text != NULL){
|
||||||
|
free(currentPar->value.v.text);
|
||||||
|
}
|
||||||
|
currentPar->value.v.text = strdup(txt);
|
||||||
|
if(debug == 1){
|
||||||
|
printf("Read %s for parameter %s\n",
|
||||||
|
currentPar->value.v.text, currentPar->name);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HIPOBJ:
|
||||||
|
currentPar->value.v.obj = va_arg(ap,void *);
|
||||||
|
break;
|
||||||
|
case HIPINTAR:
|
||||||
|
case HIPINTVARAR:
|
||||||
|
case HIPFLOATAR:
|
||||||
|
case HIPFLOATVARAR:
|
||||||
|
v = (hdbValue *)va_arg(ap,void *);
|
||||||
|
copyHdbValue(v,¤tPar->value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
currentPar = currentPar->next;
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
return toInvoke->execute(toInvoke->parameters);
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static void *(*objMap)(char *name) = NULL;
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
void SetHdbComObjMapper(void *(*mapObj)(char *name)){
|
||||||
|
objMap = mapObj;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int readParArguments(pHdb parNode, int argc, char *argv[]){
|
||||||
|
int i, intVal;
|
||||||
|
double doVal;
|
||||||
|
|
||||||
|
switch(parNode->value.dataType){
|
||||||
|
case HIPNONE:
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case HIPINT:
|
||||||
|
if(argc < 1){
|
||||||
|
return HDBCOMNOARGS;
|
||||||
|
}
|
||||||
|
if(sscanf(argv[0],"%d",&parNode->value.v.intValue) != 1){
|
||||||
|
return HDBCOMBADARG;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case HIPFLOAT:
|
||||||
|
if(argc < 1){
|
||||||
|
return HDBCOMNOARGS;
|
||||||
|
}
|
||||||
|
if(sscanf(argv[0],"%lf",&parNode->value.v.doubleValue) != 1){
|
||||||
|
return HDBCOMBADARG;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case HIPOBJ:
|
||||||
|
if(objMap != NULL){
|
||||||
|
parNode->value.v.obj = objMap(argv[0]);
|
||||||
|
if(parNode->value.v.obj == NULL){
|
||||||
|
return HDBCOMBADOBJ;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case HIPTEXT:
|
||||||
|
if(argc < 1){
|
||||||
|
return HDBCOMNOARGS;
|
||||||
|
}
|
||||||
|
if(parNode->value.v.text != NULL){
|
||||||
|
free(parNode->value.v.text);
|
||||||
|
}
|
||||||
|
parNode->value.v.text = strdup(argv[0]);
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case HIPINTAR:
|
||||||
|
if(parNode->value.arrayLength > argc){
|
||||||
|
return HDBCOMNOARGS;
|
||||||
|
}
|
||||||
|
for(i = 0; i < parNode->value.arrayLength; i++){
|
||||||
|
if(sscanf(argv[i],"%d",&intVal) != 1){
|
||||||
|
return HDBCOMBADARG;
|
||||||
|
}
|
||||||
|
parNode->value.v.intArray[i] = intVal;
|
||||||
|
}
|
||||||
|
return parNode->value.arrayLength;
|
||||||
|
break;
|
||||||
|
case HIPFLOATAR:
|
||||||
|
if(parNode->value.arrayLength > argc){
|
||||||
|
return HDBCOMNOARGS;
|
||||||
|
}
|
||||||
|
for(i = 0; i < parNode->value.arrayLength; i++){
|
||||||
|
if(sscanf(argv[i],"%lf",&doVal) != 1){
|
||||||
|
return HDBCOMBADARG;
|
||||||
|
}
|
||||||
|
parNode->value.v.floatArray[i] = doVal;
|
||||||
|
}
|
||||||
|
return parNode->value.arrayLength;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* I cannot process such variables
|
||||||
|
*/
|
||||||
|
return HDBCOMINVARG;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
int HdbCommandTextInvoke(pHdbCommand commandList, int argc, char *argv[]){
|
||||||
|
pHdbCommand toInvoke = NULL;
|
||||||
|
pHdb currentPar = NULL;
|
||||||
|
int argPointer, status;
|
||||||
|
|
||||||
|
assert(commandList != NULL);
|
||||||
|
|
||||||
|
if(argc < 1){
|
||||||
|
return HDBCOMNOARGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
toInvoke = locateCommand(commandList,argv[0]);
|
||||||
|
if(toInvoke == NULL){
|
||||||
|
return HDBCOMNOCOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPar = toInvoke->parameters;
|
||||||
|
argPointer = 1;
|
||||||
|
while(currentPar != NULL){
|
||||||
|
status = readParArguments(currentPar,argc-argPointer,
|
||||||
|
&argv[argPointer]);
|
||||||
|
if(status < 0){
|
||||||
|
return status;
|
||||||
|
} else {
|
||||||
|
argPointer += status;
|
||||||
|
}
|
||||||
|
currentPar = currentPar->next;
|
||||||
|
}
|
||||||
|
return toInvoke->execute(toInvoke->parameters);
|
||||||
|
}
|
96
hdbcommand.h
Normal file
96
hdbcommand.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* This module implements a generalized scheme for executing functions.
|
||||||
|
* Functions are described by a special data structure containing the
|
||||||
|
* parameters as a Hipadaba list and and an execute function which implements
|
||||||
|
* the actual operation. This is augmented by list mechanisms in order to
|
||||||
|
* allow for a list of functions. This shall facilitate a couple of things:
|
||||||
|
* - when functions are defined in such a structured form, general invocation
|
||||||
|
* functions can be devised for handling the interpreter interface.
|
||||||
|
* - The set of functions of an object can be configured and extended at
|
||||||
|
* runtime.
|
||||||
|
* - A common usage case: execute a function with the same arguments, can be
|
||||||
|
* easily catered for.
|
||||||
|
* All this is not new and was pioneered in the language self or other
|
||||||
|
* dynamic object systems.
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke, September 2006
|
||||||
|
*/
|
||||||
|
#ifndef HDBCOMMAND_H_
|
||||||
|
#define HDBCOMMAND_H_
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <hipadaba.h>
|
||||||
|
/*--------------- error codes ----------------------------------------------*/
|
||||||
|
#define HDCOMNOMEM -7801
|
||||||
|
#define HDBCOMNOCOM -7802
|
||||||
|
#define HDBCOMNOARGS -7803
|
||||||
|
#define HDBCOMBADARG -7804
|
||||||
|
#define HDBCOMINVARG -7805
|
||||||
|
#define HDBCOMBADOBJ -7806
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
typedef struct __hdbCommmand {
|
||||||
|
char *name;
|
||||||
|
pHdb parameters;
|
||||||
|
int (*execute)(pHdb parameters);
|
||||||
|
struct __hdbCommand *next;
|
||||||
|
struct __hdbCommand *previous;
|
||||||
|
}hdbCommand, *pHdbCommand;
|
||||||
|
/*======================= live and death ===================================*/
|
||||||
|
/**
|
||||||
|
* create a hdbCommand with an empty parameter list
|
||||||
|
* @param name The name of teh command
|
||||||
|
* @param execute The execute function for this command
|
||||||
|
* @return a fresh hdbCommand or NULL when out of memory
|
||||||
|
* */
|
||||||
|
pHdbCommand CreateHdbCommand(char *name, int (*execute)(pHdb parameters));
|
||||||
|
/**
|
||||||
|
* append a hdbCommand to a command list
|
||||||
|
* @param commandList The list to append the command to
|
||||||
|
* @param command The command to append
|
||||||
|
* @return 1 on success, a negative error code else.
|
||||||
|
*/
|
||||||
|
void AppendHdbCommandToList(pHdbCommand commandList, pHdbCommand command);
|
||||||
|
/**
|
||||||
|
* append a parameter to the parameter list
|
||||||
|
* @param command The command to append the parameter too
|
||||||
|
* @param par The parameter to append
|
||||||
|
*/
|
||||||
|
void AppendCommandParameter(pHdbCommand command, pHdb par);
|
||||||
|
/**
|
||||||
|
* delete a command list recursively
|
||||||
|
* @param commandList The command list to delete
|
||||||
|
*/
|
||||||
|
void KillHdbCommandList(pHdbCommand commandList);
|
||||||
|
/*===================== invocation ========================================*/
|
||||||
|
/**
|
||||||
|
* invoke a hdbCommand name. This does a lot: it locates the command,
|
||||||
|
* it assigne the parameter values and finally calls the execute function.
|
||||||
|
* @param commandList The command list in which to search for the command
|
||||||
|
* @param name The name of the command
|
||||||
|
* @param ... arguments to the command. ints, double, text and objects (pointers)
|
||||||
|
* are accepted as is.Arrays have to be passed in a pointers to a
|
||||||
|
* hdbValue structure. Otherwise there is not eonough information to safely
|
||||||
|
* copy array data.
|
||||||
|
* @return Negative error codes on invocation error, else the return
|
||||||
|
* value of the execute function.
|
||||||
|
*/
|
||||||
|
int HdbCommandInvoke(pHdbCommand commandList, char *name, ...);
|
||||||
|
/**
|
||||||
|
* invoke a hdbCommand name. This does a lot: it locates the command,
|
||||||
|
* it assigne the parameter values and finally calls the execute function.
|
||||||
|
* The name of the command must be in argv[0]
|
||||||
|
* @param commandList The command list in which to search for the command
|
||||||
|
* @param argc The number of arguments
|
||||||
|
* @param argv[] An array of strings holding the argument data
|
||||||
|
* @return Negative error codes on invocation error, else the return
|
||||||
|
* value of the execute function.
|
||||||
|
*/
|
||||||
|
int HdbCommandTextInvoke(pHdbCommand commandList, int argc, char *argv[]);
|
||||||
|
/**
|
||||||
|
* set a mapper which returns a void pointer for a name in order to resolve
|
||||||
|
* object references
|
||||||
|
* @param mapfunc
|
||||||
|
*/
|
||||||
|
void SetHdbComObjMapper(void *(*mapObj)(char *name));
|
||||||
|
#endif /*HDBCOMMAND_H_*/
|
343
hipadaba.c
343
hipadaba.c
@ -38,6 +38,10 @@ static void DeleteNodeData(pHdb node){
|
|||||||
DeleteCallbackChain(node->writeCallbacks);
|
DeleteCallbackChain(node->writeCallbacks);
|
||||||
DeleteCallbackChain(node->updateCallbacks);
|
DeleteCallbackChain(node->updateCallbacks);
|
||||||
DeleteCallbackChain(node->readCallbacks);
|
DeleteCallbackChain(node->readCallbacks);
|
||||||
|
DeleteCallbackChain(node->treeChangeCallbacks);
|
||||||
|
if(node->properties != NULL){
|
||||||
|
DeleteStringDict(node->properties);
|
||||||
|
}
|
||||||
|
|
||||||
if(node->name != NULL){
|
if(node->name != NULL){
|
||||||
free(node->name);
|
free(node->name);
|
||||||
@ -52,8 +56,24 @@ static void DeleteNodeData(pHdb node){
|
|||||||
}
|
}
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int InvokeCallbackChain(pHdbCallback root, pHdb node,
|
||||||
|
void *callData, hdbValue v){
|
||||||
|
pHdbCallback current = root;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
while(current != NULL){
|
||||||
|
status = current->userCallback(current->userData,callData,
|
||||||
|
node,v);
|
||||||
|
if(status != 1){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
void RemoveHdbNodeFromParent(pHdb node){
|
void RemoveHdbNodeFromParent(pHdb node, void *callData){
|
||||||
pHdb parent = NULL;
|
pHdb parent = NULL;
|
||||||
pHdb current = NULL;
|
pHdb current = NULL;
|
||||||
|
|
||||||
@ -68,6 +88,8 @@ void RemoveHdbNodeFromParent(pHdb node){
|
|||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
current->next = current->next->next;
|
current->next = current->next->next;
|
||||||
|
InvokeCallbackChain(parent->treeChangeCallbacks,
|
||||||
|
parent,callData,parent->value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
@ -174,22 +196,6 @@ static pHdbCallback DeleteForInternalID(pHdbCallback root, int id){
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
static int InvokeCallbackChain(pHdbCallback root, pHdb node,
|
|
||||||
void *callData, hdbValue v){
|
|
||||||
pHdbCallback current = root;
|
|
||||||
int status;
|
|
||||||
|
|
||||||
while(current != NULL){
|
|
||||||
status = current->userCallback(current->userData,callData,
|
|
||||||
node,v);
|
|
||||||
if(status != 1){
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
current = current->next;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
char *hdbTrim(char *str)
|
char *hdbTrim(char *str)
|
||||||
{
|
{
|
||||||
@ -270,9 +276,9 @@ hdbValue makeHdbValue(int datatype, int length){
|
|||||||
case HIPINTAR:
|
case HIPINTAR:
|
||||||
case HIPINTVARAR:
|
case HIPINTVARAR:
|
||||||
val.arrayLength = length;
|
val.arrayLength = length;
|
||||||
val.v.intArray = malloc(length*sizeof(long));
|
val.v.intArray = malloc(length*sizeof(int));
|
||||||
if(val.v.intArray != NULL){
|
if(val.v.intArray != NULL){
|
||||||
memset(val.v.intArray,0,length*sizeof(long));
|
memset(val.v.intArray,0,length*sizeof(int));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HIPFLOATAR:
|
case HIPFLOATAR:
|
||||||
@ -285,6 +291,61 @@ hdbValue makeHdbValue(int datatype, int length){
|
|||||||
break;
|
break;
|
||||||
case HIPTEXT:
|
case HIPTEXT:
|
||||||
val.v.text = strdup("UNKNOWN");
|
val.v.text = strdup("UNKNOWN");
|
||||||
|
val.arrayLength = length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
hdbValue makeHdbData(int datatype, int length, void *data){
|
||||||
|
hdbValue val;
|
||||||
|
|
||||||
|
memset(&val,0,sizeof(hdbValue));
|
||||||
|
val.dataType = datatype;
|
||||||
|
|
||||||
|
switch(datatype){
|
||||||
|
case HIPINT:
|
||||||
|
if(data != NULL){
|
||||||
|
memcpy(&val.v.intValue,data,sizeof(int));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HIPFLOAT:
|
||||||
|
if(data != NULL){
|
||||||
|
memcpy(&val.v.doubleValue,data,sizeof(double));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HIPINTAR:
|
||||||
|
case HIPINTVARAR:
|
||||||
|
val.arrayLength = length;
|
||||||
|
val.v.intArray = malloc(length*sizeof(int));
|
||||||
|
if(val.v.intArray != NULL){
|
||||||
|
memset(val.v.intArray,0,length*sizeof(int));
|
||||||
|
}
|
||||||
|
if(data != NULL){
|
||||||
|
memcpy(val.v.intArray,data,length*sizeof(int));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HIPFLOATAR:
|
||||||
|
case HIPFLOATVARAR:
|
||||||
|
val.arrayLength = length;
|
||||||
|
val.v.floatArray = malloc(length*sizeof(double));
|
||||||
|
if(val.v.floatArray != NULL){
|
||||||
|
memset(val.v.floatArray,0,length*sizeof(double));
|
||||||
|
}
|
||||||
|
if(data != NULL){
|
||||||
|
memcpy(val.v.floatArray,data,length*sizeof(double));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HIPTEXT:
|
||||||
|
if(data != NULL){
|
||||||
|
val.v.text = strdup((char *)data);
|
||||||
|
} else {
|
||||||
|
val.v.text = strdup("UNKNOWN");
|
||||||
|
}
|
||||||
|
val.arrayLength = strlen(val.v.text);
|
||||||
|
break;
|
||||||
|
case HIPOBJ:
|
||||||
|
val.v.obj = data;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
@ -294,6 +355,7 @@ hdbValue MakeHdbInt(int initValue){
|
|||||||
hdbValue result;
|
hdbValue result;
|
||||||
|
|
||||||
result.dataType = HIPINT;
|
result.dataType = HIPINT;
|
||||||
|
result.arrayLength = 1;
|
||||||
result.v.intValue = initValue;
|
result.v.intValue = initValue;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -302,6 +364,7 @@ hdbValue MakeHdbFloat(double initValue){
|
|||||||
hdbValue result;
|
hdbValue result;
|
||||||
|
|
||||||
result.dataType = HIPFLOAT;
|
result.dataType = HIPFLOAT;
|
||||||
|
result.arrayLength = 1;
|
||||||
result.v.doubleValue = initValue;
|
result.v.doubleValue = initValue;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -311,10 +374,11 @@ hdbValue MakeHdbText(char *initText){
|
|||||||
|
|
||||||
result.dataType = HIPTEXT;
|
result.dataType = HIPTEXT;
|
||||||
result.v.text = initText;
|
result.v.text = initText;
|
||||||
|
result.arrayLength = strlen(initText);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
hdbValue MakeHdbIntArray(int length, long *data){
|
hdbValue MakeHdbIntArray(int length, int *data){
|
||||||
hdbValue result;
|
hdbValue result;
|
||||||
|
|
||||||
result.dataType = HIPINTAR;
|
result.dataType = HIPINTAR;
|
||||||
@ -409,6 +473,13 @@ int compareHdbValue(hdbValue v1, hdbValue v2){
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
case HIPOBJ:
|
||||||
|
if(v2.v.obj == v1.v.obj) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
@ -422,6 +493,35 @@ int cloneHdbValue(hdbValue *source, hdbValue *clone){
|
|||||||
clone->dataType = source->dataType;
|
clone->dataType = source->dataType;
|
||||||
return copyHdbValue(source, clone);
|
return copyHdbValue(source, clone);
|
||||||
}
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
int getHdbValueLength(hdbValue v){
|
||||||
|
int length = 0;
|
||||||
|
switch(v.dataType){
|
||||||
|
case HIPNONE:
|
||||||
|
break;
|
||||||
|
case HIPINT:
|
||||||
|
length = sizeof(int);
|
||||||
|
break;
|
||||||
|
case HIPFLOAT:
|
||||||
|
length = sizeof(double);
|
||||||
|
break;
|
||||||
|
case HIPINTAR:
|
||||||
|
case HIPINTVARAR:
|
||||||
|
length = v.arrayLength * sizeof(int);
|
||||||
|
break;
|
||||||
|
case HIPFLOATAR:
|
||||||
|
case HIPFLOATVARAR:
|
||||||
|
length = v.arrayLength * sizeof(double);
|
||||||
|
break;
|
||||||
|
case HIPTEXT:
|
||||||
|
length = strlen(v.v.text);
|
||||||
|
break;
|
||||||
|
case HIPOBJ:
|
||||||
|
length = sizeof(void *);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
/*================= node functions ========================================*/
|
/*================= node functions ========================================*/
|
||||||
pHdb MakeHipadabaNode(char *name, int datatype, int length){
|
pHdb MakeHipadabaNode(char *name, int datatype, int length){
|
||||||
pHdb pNew = NULL;
|
pHdb pNew = NULL;
|
||||||
@ -434,15 +534,19 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length){
|
|||||||
pNew->magic = HDBMAGICK;
|
pNew->magic = HDBMAGICK;
|
||||||
pNew->name = strdup(name);
|
pNew->name = strdup(name);
|
||||||
pNew->value.dataType = datatype;
|
pNew->value.dataType = datatype;
|
||||||
|
pNew->properties = CreateStringDict();
|
||||||
|
if(pNew->properties == NULL || pNew->name == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
switch(datatype){
|
switch(datatype){
|
||||||
case HIPINTAR:
|
case HIPINTAR:
|
||||||
case HIPINTVARAR:
|
case HIPINTVARAR:
|
||||||
pNew->value.arrayLength = length;
|
pNew->value.arrayLength = length;
|
||||||
pNew->value.v.intArray = malloc(length*sizeof(long));
|
pNew->value.v.intArray = malloc(length*sizeof(int));
|
||||||
if(pNew->value.v.intArray == NULL){
|
if(pNew->value.v.intArray == NULL){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
memset(pNew->value.v.intArray,0,length*sizeof(long));
|
memset(pNew->value.v.intArray,0,length*sizeof(int));
|
||||||
break;
|
break;
|
||||||
case HIPFLOATAR:
|
case HIPFLOATAR:
|
||||||
case HIPFLOATVARAR:
|
case HIPFLOATVARAR:
|
||||||
@ -454,16 +558,20 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length){
|
|||||||
memset(pNew->value.v.floatArray,0,length*sizeof(double));
|
memset(pNew->value.v.floatArray,0,length*sizeof(double));
|
||||||
break;
|
break;
|
||||||
case HIPTEXT:
|
case HIPTEXT:
|
||||||
|
pNew->value.arrayLength = length;
|
||||||
pNew->value.v.text = strdup("UNKNOWN");
|
pNew->value.v.text = strdup("UNKNOWN");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return pNew;
|
return pNew;
|
||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
void AddHipadabaChild(pHdb parent, pHdb child){
|
void AddHipadabaChild(pHdb parent, pHdb child, void *callData){
|
||||||
pHdb current = NULL, prev = NULL;
|
pHdb current = NULL, prev = NULL;
|
||||||
|
|
||||||
assert(parent != NULL && child != NULL);
|
assert(parent != NULL);
|
||||||
|
if(child == NULL){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
current = parent->child;
|
current = parent->child;
|
||||||
child->mama = parent;
|
child->mama = parent;
|
||||||
@ -481,16 +589,18 @@ void AddHipadabaChild(pHdb parent, pHdb child){
|
|||||||
child->next = NULL;
|
child->next = NULL;
|
||||||
prev->next = child;
|
prev->next = child;
|
||||||
}
|
}
|
||||||
|
InvokeCallbackChain(parent->treeChangeCallbacks,
|
||||||
|
parent,callData,parent->value);
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
void DeleteHipadabaNode(pHdb node){
|
void DeleteHipadabaNode(pHdb node, void *callData){
|
||||||
pHdb current = NULL, tmp = NULL;
|
pHdb current = NULL, tmp = NULL;
|
||||||
|
|
||||||
if(node == NULL){
|
if(node == NULL){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoveHdbNodeFromParent(node);
|
RemoveHdbNodeFromParent(node, callData);
|
||||||
|
|
||||||
DeleteNodeData(node);
|
DeleteNodeData(node);
|
||||||
}
|
}
|
||||||
@ -637,6 +747,14 @@ void AppendHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
|||||||
current = node->readCallbacks;
|
current = node->readCallbacks;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case HCBTREE:
|
||||||
|
if(node->treeChangeCallbacks == NULL){
|
||||||
|
node->treeChangeCallbacks = newCB;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
current = node->treeChangeCallbacks;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
@ -649,7 +767,6 @@ void AppendHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
|||||||
newCB->previous = current;
|
newCB->previous = current;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------------*/
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void PrependHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
void PrependHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
||||||
switch(type){
|
switch(type){
|
||||||
@ -683,6 +800,16 @@ void PrependHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
|||||||
node->readCallbacks = newCB;
|
node->readCallbacks = newCB;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case HCBTREE:
|
||||||
|
if(node->treeChangeCallbacks == NULL){
|
||||||
|
node->treeChangeCallbacks = newCB;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
newCB->next = node->treeChangeCallbacks;
|
||||||
|
node->treeChangeCallbacks->previous = newCB;
|
||||||
|
node->treeChangeCallbacks = newCB;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
@ -695,6 +822,7 @@ void RemoveHipadabaCallback(pHdb root, int id){
|
|||||||
root->writeCallbacks = DeleteForID(root->writeCallbacks,id);
|
root->writeCallbacks = DeleteForID(root->writeCallbacks,id);
|
||||||
root->updateCallbacks = DeleteForID(root->updateCallbacks,id);
|
root->updateCallbacks = DeleteForID(root->updateCallbacks,id);
|
||||||
root->readCallbacks = DeleteForID(root->readCallbacks,id);
|
root->readCallbacks = DeleteForID(root->readCallbacks,id);
|
||||||
|
root->treeChangeCallbacks = DeleteForID(root->treeChangeCallbacks,id);
|
||||||
|
|
||||||
current = root->child;
|
current = root->child;
|
||||||
while(current != NULL){
|
while(current != NULL){
|
||||||
@ -709,6 +837,7 @@ void InternalRemoveHipadabaCallback(pHdb root, int internalID){
|
|||||||
root->writeCallbacks = DeleteForInternalID(root->writeCallbacks,internalID);
|
root->writeCallbacks = DeleteForInternalID(root->writeCallbacks,internalID);
|
||||||
root->updateCallbacks = DeleteForInternalID(root->updateCallbacks,internalID);
|
root->updateCallbacks = DeleteForInternalID(root->updateCallbacks,internalID);
|
||||||
root->readCallbacks = DeleteForInternalID(root->readCallbacks,internalID);
|
root->readCallbacks = DeleteForInternalID(root->readCallbacks,internalID);
|
||||||
|
root->treeChangeCallbacks = DeleteForInternalID(root->treeChangeCallbacks,internalID);
|
||||||
|
|
||||||
current = root->child;
|
current = root->child;
|
||||||
while(current != NULL){
|
while(current != NULL){
|
||||||
@ -741,24 +870,26 @@ int copyHdbValue(hdbValue *source, hdbValue *target){
|
|||||||
break;
|
break;
|
||||||
case HIPINTAR:
|
case HIPINTAR:
|
||||||
case HIPINTVARAR:
|
case HIPINTVARAR:
|
||||||
if(target->arrayLength != source->arrayLength){
|
if(target->arrayLength != source->arrayLength || target->v.intArray == NULL){
|
||||||
if(target->v.intArray != NULL){
|
if(target->v.intArray != NULL){
|
||||||
free(target->v.intArray);
|
free(target->v.intArray);
|
||||||
}
|
}
|
||||||
target->v.intArray = malloc(source->arrayLength * sizeof(long));
|
target->v.intArray = malloc(source->arrayLength * sizeof(int));
|
||||||
if(target->v.intArray == NULL){
|
if(target->v.intArray == NULL){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memset(target->v.intArray,0,source->arrayLength * sizeof(long));
|
memset(target->v.intArray,0,source->arrayLength * sizeof(int));
|
||||||
target->arrayLength = source->arrayLength;
|
target->arrayLength = source->arrayLength;
|
||||||
}
|
}
|
||||||
|
if(source->v.intArray != NULL){
|
||||||
for(i = 0; i < source->arrayLength; i++){
|
for(i = 0; i < source->arrayLength; i++){
|
||||||
target->v.intArray[i] = source->v.intArray[i];
|
target->v.intArray[i] = source->v.intArray[i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case HIPFLOATAR:
|
case HIPFLOATAR:
|
||||||
case HIPFLOATVARAR:
|
case HIPFLOATVARAR:
|
||||||
if(target->arrayLength != source->arrayLength){
|
if(target->arrayLength != source->arrayLength || target->v.floatArray == NULL){
|
||||||
if(target->v.floatArray != NULL){
|
if(target->v.floatArray != NULL){
|
||||||
free(target->v.floatArray);
|
free(target->v.floatArray);
|
||||||
}
|
}
|
||||||
@ -769,9 +900,14 @@ int copyHdbValue(hdbValue *source, hdbValue *target){
|
|||||||
memset(target->v.floatArray,0,source->arrayLength * sizeof(double));
|
memset(target->v.floatArray,0,source->arrayLength * sizeof(double));
|
||||||
target->arrayLength = source->arrayLength;
|
target->arrayLength = source->arrayLength;
|
||||||
}
|
}
|
||||||
|
if(source->v.floatArray != NULL){
|
||||||
for(i = 0; i < source->arrayLength; i++){
|
for(i = 0; i < source->arrayLength; i++){
|
||||||
target->v.floatArray[i] = source->v.floatArray[i];
|
target->v.floatArray[i] = source->v.floatArray[i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HIPOBJ:
|
||||||
|
target->v.obj = source->v.obj;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
@ -812,4 +948,149 @@ int GetHipadabaPar(pHdb node, hdbValue *v, void *callData){
|
|||||||
copyHdbValue(&node->value,v);
|
copyHdbValue(&node->value,v);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
static int calcDataLength(pHdb node, int testLength){
|
||||||
|
int length = 0;
|
||||||
|
|
||||||
|
length = getHdbValueLength(node->value);
|
||||||
|
if(node->value.dataType == HIPFLOATVARAR ||
|
||||||
|
node->value.dataType == HIPINTVARAR ||
|
||||||
|
node->value.dataType == HIPTEXT){
|
||||||
|
length = testLength;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
int SetHdbPar(pHdb node, int dataType, void *data, int length,
|
||||||
|
void *callData){
|
||||||
|
int status;
|
||||||
|
hdbValue v;
|
||||||
|
|
||||||
|
if(node->value.dataType == HIPNONE){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dataType != node->value.dataType){
|
||||||
|
return HDBTYPEMISMATCH;
|
||||||
|
}
|
||||||
|
if(length != calcDataLength(node,length)){
|
||||||
|
return HDBLENGTHMISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
v = makeHdbData(dataType, length, data);
|
||||||
|
status = InvokeCallbackChain(node->writeCallbacks, node, callData, v);
|
||||||
|
if(status == 1) {
|
||||||
|
copyHdbValue(&v,&node->value);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
int UpdateHdbPar(pHdb node, int dataType, void *data, int length,
|
||||||
|
void *callData){
|
||||||
|
int status;
|
||||||
|
hdbValue v;
|
||||||
|
|
||||||
|
if(node->value.dataType == HIPNONE){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dataType != node->value.dataType){
|
||||||
|
return HDBTYPEMISMATCH;
|
||||||
|
}
|
||||||
|
if(length != calcDataLength(node,length)){
|
||||||
|
return HDBLENGTHMISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
v = makeHdbData(dataType,length,data);
|
||||||
|
|
||||||
|
status = InvokeCallbackChain(node->updateCallbacks, node, callData, v);
|
||||||
|
if(status == 1) {
|
||||||
|
copyHdbValue(&v,&node->value);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
int GetHdbPar(pHdb node, int dataType, void *data, int length,
|
||||||
|
void *callData){
|
||||||
|
int status, toCopy;
|
||||||
|
hdbValue v;
|
||||||
|
|
||||||
|
if(dataType != node->value.dataType){
|
||||||
|
return HDBTYPEMISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(length != calcDataLength(node,length)){
|
||||||
|
return HDBLENGTHMISMATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = InvokeCallbackChain(node->readCallbacks, node, callData, v);
|
||||||
|
if(status != 1 ){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
switch(dataType){
|
||||||
|
case HIPNONE:
|
||||||
|
break;
|
||||||
|
case HIPINT:
|
||||||
|
memcpy(data,&node->value.v.intValue,sizeof(int));
|
||||||
|
break;
|
||||||
|
case HIPFLOAT:
|
||||||
|
memcpy(data,&node->value.v.doubleValue,sizeof(double));
|
||||||
|
break;
|
||||||
|
case HIPINTAR:
|
||||||
|
case HIPINTVARAR:
|
||||||
|
memcpy(data,node->value.v.intArray,
|
||||||
|
node->value.arrayLength*sizeof(int));
|
||||||
|
break;
|
||||||
|
case HIPTEXT:
|
||||||
|
toCopy = strlen(node->value.v.text);
|
||||||
|
if(toCopy > length){
|
||||||
|
toCopy = length;
|
||||||
|
}
|
||||||
|
memcpy(data,&node->value.v.text, toCopy);
|
||||||
|
break;
|
||||||
|
case HIPFLOATAR:
|
||||||
|
case HIPFLOATVARAR:
|
||||||
|
memcpy(data,node->value.v.floatArray,
|
||||||
|
node->value.arrayLength*sizeof(double));
|
||||||
|
break;
|
||||||
|
case HIPOBJ:
|
||||||
|
memcpy(data,&node->value.v.obj,sizeof(void *));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*============================= Property Functions ==========================*/
|
||||||
|
void SetHdbProperty(pHdb node, char *key, char *value){
|
||||||
|
if(node != NULL && key != NULL && node->properties != NULL){
|
||||||
|
if(StringDictExists(node->properties, key)){
|
||||||
|
StringDictUpdate(node->properties,key,value);
|
||||||
|
} else {
|
||||||
|
StringDictAddPair(node->properties,key,value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int GetHdbProperty(pHdb node, char *key, char *value, int len){
|
||||||
|
if(node != NULL && node->properties != NULL){
|
||||||
|
return StringDictGet(node->properties,key,value,len);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
void InitHdbPropertySearch(pHdb node){
|
||||||
|
if(node != NULL && node->properties != NULL){
|
||||||
|
StringDictKillScan(node->properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
const char *GetNextHdbProperty(pHdb node, char *value ,int len){
|
||||||
|
if(node != NULL && node->properties != NULL) {
|
||||||
|
return StringDictGetNext(node->properties, value, len);
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
117
hipadaba.h
117
hipadaba.h
@ -20,9 +20,14 @@
|
|||||||
* copyright: GPL
|
* copyright: GPL
|
||||||
*
|
*
|
||||||
* Mark Koennecke, June 2006
|
* Mark Koennecke, June 2006
|
||||||
|
*
|
||||||
|
* Added treeChange callback, Mark Koennecke, November 2006
|
||||||
|
*
|
||||||
|
* Added support for properties, Mark Koennecke, January 2007
|
||||||
*/
|
*/
|
||||||
#ifndef HIPADABA
|
#ifndef HIPADABA
|
||||||
#define HIPADABA
|
#define HIPADABA
|
||||||
|
#include <stringdict.h>
|
||||||
|
|
||||||
/*------- datatypes */
|
/*------- datatypes */
|
||||||
#define HIPNONE -1
|
#define HIPNONE -1
|
||||||
@ -33,20 +38,26 @@
|
|||||||
#define HIPFLOATAR 4
|
#define HIPFLOATAR 4
|
||||||
#define HIPINTVARAR 5
|
#define HIPINTVARAR 5
|
||||||
#define HIPFLOATVARAR 6
|
#define HIPFLOATVARAR 6
|
||||||
|
#define HIPOBJ 7
|
||||||
/* -------- callback types */
|
/* -------- callback types */
|
||||||
#define HCBSET 0
|
#define HCBSET 0
|
||||||
#define HCBUPDATE 1
|
#define HCBUPDATE 1
|
||||||
#define HCBREAD 2
|
#define HCBREAD 2
|
||||||
|
#define HCBTREE 3
|
||||||
|
/*--------- error codes */
|
||||||
|
#define HDBTYPEMISMATCH -7701
|
||||||
|
#define HDBLENGTHMISMATCH -7702
|
||||||
/*===================== structure definitions ===================================*/
|
/*===================== structure definitions ===================================*/
|
||||||
typedef struct __hdbValue {
|
typedef struct __hdbValue {
|
||||||
int dataType;
|
int dataType;
|
||||||
int arrayLength;
|
int arrayLength;
|
||||||
union __value {
|
union __value {
|
||||||
long intValue;
|
int intValue;
|
||||||
double doubleValue;
|
double doubleValue;
|
||||||
char *text;
|
char *text;
|
||||||
long *intArray;
|
int *intArray;
|
||||||
double *floatArray;
|
double *floatArray;
|
||||||
|
void *obj;
|
||||||
}v;
|
}v;
|
||||||
}hdbValue;
|
}hdbValue;
|
||||||
/*------------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------------*/
|
||||||
@ -58,8 +69,11 @@ typedef struct __hipadaba {
|
|||||||
struct __hdbcallback *writeCallbacks;
|
struct __hdbcallback *writeCallbacks;
|
||||||
struct __hdbcallback *updateCallbacks;
|
struct __hdbcallback *updateCallbacks;
|
||||||
struct __hdbcallback *readCallbacks;
|
struct __hdbcallback *readCallbacks;
|
||||||
|
struct __hdbcallback *treeChangeCallbacks;
|
||||||
char *name;
|
char *name;
|
||||||
hdbValue value;
|
hdbValue value;
|
||||||
|
int protected;
|
||||||
|
pStringDict properties;
|
||||||
}Hdb, *pHdb;
|
}Hdb, *pHdb;
|
||||||
/*-------------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------------*/
|
||||||
typedef int (*hdbCallbackFunction)(void *userData, void *callData,
|
typedef int (*hdbCallbackFunction)(void *userData, void *callData,
|
||||||
@ -77,6 +91,15 @@ typedef struct __hdbcallback {
|
|||||||
}hdbCallback, *pHdbCallback;
|
}hdbCallback, *pHdbCallback;
|
||||||
/*======================== Function protoypes: hdbData ========================*/
|
/*======================== Function protoypes: hdbData ========================*/
|
||||||
hdbValue makeHdbValue(int datatype, int length);
|
hdbValue makeHdbValue(int datatype, int length);
|
||||||
|
/**
|
||||||
|
* make a hdbValue and initailize it with the data in the void
|
||||||
|
* pointer. Do not initialise when data = NULL.
|
||||||
|
* @param dataType The datatype of the hdbValue
|
||||||
|
* @param The array length of the hdbValue
|
||||||
|
* @param data Initialisation data for hdbValue
|
||||||
|
* @return a suitably defined hdbValue
|
||||||
|
*/
|
||||||
|
hdbValue makeHdbData(int datatype, int length, void *data);
|
||||||
/**
|
/**
|
||||||
* wrap an integer as an hdbValue
|
* wrap an integer as an hdbValue
|
||||||
* @param initValue the initial value of the int
|
* @param initValue the initial value of the int
|
||||||
@ -107,7 +130,7 @@ hdbValue MakeHdbText(char *initText);
|
|||||||
* data points to dynamically allocated memory.
|
* data points to dynamically allocated memory.
|
||||||
* @return: A properly initialized hdbValue structure
|
* @return: A properly initialized hdbValue structure
|
||||||
*/
|
*/
|
||||||
hdbValue MakeHdbIntArray(int length, long *data);
|
hdbValue MakeHdbIntArray(int length, int *data);
|
||||||
/**
|
/**
|
||||||
* wrap a float array as an hdbValue
|
* wrap a float array as an hdbValue
|
||||||
* @param length The length of the int array
|
* @param length The length of the int array
|
||||||
@ -147,6 +170,12 @@ int compareHdbValue(hdbValue v1, hdbValue v2);
|
|||||||
* @return 1 on success, 0 on when out of memory
|
* @return 1 on success, 0 on when out of memory
|
||||||
*/
|
*/
|
||||||
int cloneHdbValue(hdbValue *source, hdbValue *clone);
|
int cloneHdbValue(hdbValue *source, hdbValue *clone);
|
||||||
|
/**
|
||||||
|
* get the length of the hdbValue in bytes.
|
||||||
|
* @param v The hdbValue to calculate the length for
|
||||||
|
* @return the number of data bytes
|
||||||
|
*/
|
||||||
|
int getHdbValueLength(hdbValue v);
|
||||||
/*========================== function protoypes: Nodes =======================*/
|
/*========================== function protoypes: Nodes =======================*/
|
||||||
/**
|
/**
|
||||||
* make a new hipadaba node
|
* make a new hipadaba node
|
||||||
@ -156,16 +185,18 @@ int cloneHdbValue(hdbValue *source, hdbValue *clone);
|
|||||||
*/
|
*/
|
||||||
pHdb MakeHipadabaNode(char *name, int datatype, int length);
|
pHdb MakeHipadabaNode(char *name, int datatype, int length);
|
||||||
/**
|
/**
|
||||||
* add a child to a node
|
* add a child to a node at the end of the child list.
|
||||||
* @param parent The node to which to add the child
|
* @param parent The node to which to add the child
|
||||||
* @param child The node to add
|
* @param child The node to add
|
||||||
|
* @param callData User data for the tree chnage callback. Can be NULL.
|
||||||
*/
|
*/
|
||||||
void AddHipadabaChild(pHdb parent, pHdb child);
|
void AddHipadabaChild(pHdb parent, pHdb child, void *callData);
|
||||||
/**
|
/**
|
||||||
* delete a hipadaba node and all its children
|
* delete a hipadaba node and all its children
|
||||||
* @parma node The node to delete
|
* @parma node The node to delete
|
||||||
|
* @param callData User data for the tree change callback
|
||||||
*/
|
*/
|
||||||
void DeleteHipadabaNode(pHdb node);
|
void DeleteHipadabaNode(pHdb node, void *callData);
|
||||||
/*
|
/*
|
||||||
* checks if a Hdb node is valid
|
* checks if a Hdb node is valid
|
||||||
* @param node The node to check
|
* @param node The node to check
|
||||||
@ -189,8 +220,9 @@ char *GetHipadabaPath(pHdb node);
|
|||||||
/**
|
/**
|
||||||
* removes a node from the parents child list.
|
* removes a node from the parents child list.
|
||||||
* @node the node to remove
|
* @node the node to remove
|
||||||
|
* @param callData User data for the tree change callback
|
||||||
*/
|
*/
|
||||||
void RemoveHdbNodeFromParent(pHdb node);
|
void RemoveHdbNodeFromParent(pHdb node, void *callData);
|
||||||
/**
|
/**
|
||||||
* delete a callback chain
|
* delete a callback chain
|
||||||
* @param root The callback chain to delete
|
* @param root The callback chain to delete
|
||||||
@ -250,8 +282,8 @@ void InternalRemoveHipadabaCallback(pHdb root, int internalID);
|
|||||||
*/
|
*/
|
||||||
int SetHipadabaPar(pHdb node, hdbValue v, void *callData);
|
int SetHipadabaPar(pHdb node, hdbValue v, void *callData);
|
||||||
/**
|
/**
|
||||||
* Update a hipadaba parameter. This is an internal update of a parameter, during
|
* Update a hipadaba parameter. This is an internal update of a parameter,
|
||||||
* driving etc.
|
* during driving etc.
|
||||||
* @param node The node for which to update the parameter
|
* @param node The node for which to update the parameter
|
||||||
* @param v The new value for the node
|
* @param v The new value for the node
|
||||||
* @param callData Additonal context data to be passed to the callback functions
|
* @param callData Additonal context data to be passed to the callback functions
|
||||||
@ -266,5 +298,70 @@ int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData);
|
|||||||
* @return 0 on failure, 1 on success
|
* @return 0 on failure, 1 on success
|
||||||
*/
|
*/
|
||||||
int GetHipadabaPar(pHdb node, hdbValue *v, void *callData);
|
int GetHipadabaPar(pHdb node, hdbValue *v, void *callData);
|
||||||
|
/**
|
||||||
|
* Set a hipadaba parameter. This is an external set for a parameter. It may cause
|
||||||
|
* motors to start driving etc.
|
||||||
|
* @param node The node for which to set the parameter
|
||||||
|
* param dataType The datatype the value ought to have
|
||||||
|
* @param data A pointer to the data to set.
|
||||||
|
* @param length The length of data
|
||||||
|
* @param callData Additonal context data to be passed to the callback functions
|
||||||
|
* @return 0 on failure, a negative error code on failure
|
||||||
|
*/
|
||||||
|
int SetHdbPar(pHdb node, int dataType, void *data, int length,
|
||||||
|
void *callData);
|
||||||
|
/**
|
||||||
|
* Updates a hipadaba parameter. This does not cause an active parameter to
|
||||||
|
* start driving but invokes all notifications which may be registered on
|
||||||
|
* this parameter.
|
||||||
|
* @param node The node for which to set the parameter
|
||||||
|
* param dataType The datatype the value ought to have
|
||||||
|
* @param data A pointer to the data to set.
|
||||||
|
* @param length The length of data
|
||||||
|
* @param callData Additonal context data to be passed to the callback functions
|
||||||
|
* @return 0 on failure, a negative error code on failure
|
||||||
|
*/
|
||||||
|
int UpdateHdbPar(pHdb node, int dataType, void *data, int length,
|
||||||
|
void *callData);
|
||||||
|
/**
|
||||||
|
* Read a hipadaba parameter
|
||||||
|
* @param node The node for which to read the parameter
|
||||||
|
* @param dataType The expected type of the data
|
||||||
|
* @param data A pointer to which data will be copied
|
||||||
|
* @param length The length of data.
|
||||||
|
* @param callData Additonal context data to be passed to the callback functions
|
||||||
|
* @return 0 on failure, a negative error code on failures.
|
||||||
|
*/
|
||||||
|
int GetHdbPar(pHdb node, int dataType, void *data, int length,
|
||||||
|
void *callData);
|
||||||
|
/*================================ Property Interface ==============================================*/
|
||||||
|
/**
|
||||||
|
* set a property
|
||||||
|
* @param node The node to set the property for
|
||||||
|
* @param key The key for the property
|
||||||
|
* @param value The value of the property
|
||||||
|
*/
|
||||||
|
void SetHdbProperty(pHdb node, char *key, char *value);
|
||||||
|
/**
|
||||||
|
* get the value of a property
|
||||||
|
* @param node The node to get the property from
|
||||||
|
* @param key The properties key
|
||||||
|
* @param value The area to which to copy the property
|
||||||
|
* @param len The length of value
|
||||||
|
* @return 0 on failure, 1 on success
|
||||||
|
*/
|
||||||
|
int GetHdbProperty(pHdb node, char *key, char *value, int len);
|
||||||
|
/**
|
||||||
|
* initialize a property scan on this node
|
||||||
|
* @param node The node for which to scan properties
|
||||||
|
*/
|
||||||
|
void InitHdbPropertySearch(pHdb node);
|
||||||
|
/**
|
||||||
|
* get the next property in a search
|
||||||
|
* @param node The node for which to search properties
|
||||||
|
* @param value An area where to copy the value of the property
|
||||||
|
* @param len The length of value
|
||||||
|
* @return The key of the property or NULL when the property list is exhausted
|
||||||
|
*/
|
||||||
|
const char *GetNextHdbProperty(pHdb node, char *value ,int len);
|
||||||
#endif
|
#endif
|
||||||
|
59
histmem.c
59
histmem.c
@ -68,6 +68,10 @@
|
|||||||
/*
|
/*
|
||||||
#define LOADDEBUG 1
|
#define LOADDEBUG 1
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
|
* from histregress.c
|
||||||
|
*/
|
||||||
|
extern pHistDriver CreateRegressHM(pStringDict pOpt);
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
static int HistHalt(void *pData)
|
static int HistHalt(void *pData)
|
||||||
{
|
{
|
||||||
@ -171,6 +175,8 @@
|
|||||||
iRet = self->pDriv->Start(self->pDriv, pCon);
|
iRet = self->pDriv->Start(self->pDriv, pCon);
|
||||||
if(iRet == OKOK)
|
if(iRet == OKOK)
|
||||||
{
|
{
|
||||||
|
/* send a COUNTSTART event */
|
||||||
|
InvokeCallBack(self->pCall,COUNTSTART,pCon);
|
||||||
updateHMData(self->pDriv->data);
|
updateHMData(self->pDriv->data);
|
||||||
return iRet;
|
return iRet;
|
||||||
}
|
}
|
||||||
@ -452,6 +458,10 @@
|
|||||||
{
|
{
|
||||||
pNew->pDriv = NewMcStasHM(pOption);
|
pNew->pDriv = NewMcStasHM(pOption);
|
||||||
}
|
}
|
||||||
|
else if(strcmp(driver,"regress") == 0)
|
||||||
|
{
|
||||||
|
pNew->pDriv = CreateRegressHM(pOption);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
site = getSite();
|
site = getSite();
|
||||||
@ -721,8 +731,6 @@ void HistDirty(pHistMem self)
|
|||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
/* send a COUNTSTART event */
|
|
||||||
InvokeCallBack(self->pCall,COUNTSTART,pCon);
|
|
||||||
|
|
||||||
/* start */
|
/* start */
|
||||||
return StartDevice(GetExecutor(),"HistogramMemory", self->pDes, self,
|
return StartDevice(GetExecutor(),"HistogramMemory", self->pDes, self,
|
||||||
@ -744,9 +752,6 @@ void HistDirty(pHistMem self)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send a COUNTSTART event */
|
|
||||||
InvokeCallBack(self->pCall,COUNTSTART,pCon);
|
|
||||||
|
|
||||||
/* wait till end */
|
/* wait till end */
|
||||||
iRet = Wait4Success(GetExecutor());
|
iRet = Wait4Success(GetExecutor());
|
||||||
if(iRet == DEVINT)
|
if(iRet == DEVINT)
|
||||||
@ -1233,6 +1238,12 @@ static int checkHMEnd(pHistMem self, char *text){
|
|||||||
}
|
}
|
||||||
else if(strcmp(argv[1],"init") == 0)
|
else if(strcmp(argv[1],"init") == 0)
|
||||||
{
|
{
|
||||||
|
if(GetStatus() != eEager)
|
||||||
|
{
|
||||||
|
SCWrite(pCon,"ERROR: cannot initialize HM while running",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if(SCMatchRights(pCon,usMugger))
|
if(SCMatchRights(pCon,usMugger))
|
||||||
{
|
{
|
||||||
iRet = HistConfigure(self,pCon,pSics);
|
iRet = HistConfigure(self,pCon,pSics);
|
||||||
@ -1357,6 +1368,31 @@ static int checkHMEnd(pHistMem self, char *text){
|
|||||||
}
|
}
|
||||||
return iRet;
|
return iRet;
|
||||||
}
|
}
|
||||||
|
else if(strcmp(argv[1],"initfile") == 0) /* initialize from a file */
|
||||||
|
{
|
||||||
|
/* check user rights */
|
||||||
|
if(!SCMatchRights(pCon,self->iAccess))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enough arguments */
|
||||||
|
if(argc < 3)
|
||||||
|
{
|
||||||
|
sprintf(pBueffel,"ERROR: insufficient number of arguments to %s %s",
|
||||||
|
argv[0], argv[1]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
iRet = loadHMData(self->pDriv->data,pCon,argv[2]);
|
||||||
|
self->pDriv->SetHistogram(self->pDriv,pCon,0,0,GetHistLength(self),
|
||||||
|
self->pDriv->data->localBuffer);
|
||||||
|
if(iRet)
|
||||||
|
{
|
||||||
|
SCSendOK(pCon);
|
||||||
|
}
|
||||||
|
return iRet;
|
||||||
|
}
|
||||||
else if(strcmp(argv[1],"get") == 0) /* get a histogram */
|
else if(strcmp(argv[1],"get") == 0) /* get a histogram */
|
||||||
{
|
{
|
||||||
/* check parameters, first required: no of Hist */
|
/* check parameters, first required: no of Hist */
|
||||||
@ -1389,6 +1425,11 @@ static int checkHMEnd(pHistMem self, char *text){
|
|||||||
iEnd = checkHMEnd(self,NULL);
|
iEnd = checkHMEnd(self,NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(iNum != 0 && argc > 4)
|
||||||
|
{
|
||||||
|
iEnd = atoi(argv[4]);
|
||||||
|
}
|
||||||
|
|
||||||
/* allocate data storage and get it */
|
/* allocate data storage and get it */
|
||||||
lData = (HistInt *)malloc(iEnd*sizeof(HistInt));
|
lData = (HistInt *)malloc(iEnd*sizeof(HistInt));
|
||||||
if(!lData)
|
if(!lData)
|
||||||
@ -1397,8 +1438,14 @@ static int checkHMEnd(pHistMem self, char *text){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memset(lData,0,iEnd*sizeof(HistInt));
|
memset(lData,0,iEnd*sizeof(HistInt));
|
||||||
|
if(iNum == 0)
|
||||||
|
{
|
||||||
iRet = GetHistogram(self,pCon,iNum,iStart,iEnd,
|
iRet = GetHistogram(self,pCon,iNum,iStart,iEnd,
|
||||||
lData,iEnd*sizeof(long));
|
lData,iEnd*sizeof(long));
|
||||||
|
} else {
|
||||||
|
iRet = GetHistogramDirect(self,pCon,iNum,iStart, iEnd,
|
||||||
|
lData, iEnd*sizeof(long));
|
||||||
|
}
|
||||||
if(!iRet)
|
if(!iRet)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"ERROR: cannot retrieve histogram %d",iNum);
|
sprintf(pBueffel,"ERROR: cannot retrieve histogram %d",iNum);
|
||||||
@ -1568,7 +1615,7 @@ static int checkHMEnd(pHistMem self, char *text){
|
|||||||
Tcl_DStringAppend(&tResult,"histogram.timebins =",-1);
|
Tcl_DStringAppend(&tResult,"histogram.timebins =",-1);
|
||||||
for(i = 0; i < self->pDriv->data->nTimeChan; i++)
|
for(i = 0; i < self->pDriv->data->nTimeChan; i++)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel," %8.2f", self->pDriv->data->timeBinning[i]);
|
sprintf(pBueffel,"%.2f ", self->pDriv->data->timeBinning[i]);
|
||||||
Tcl_DStringAppend(&tResult,pBueffel,-1);
|
Tcl_DStringAppend(&tResult,pBueffel,-1);
|
||||||
}
|
}
|
||||||
/* Write it */
|
/* Write it */
|
||||||
|
@ -163,6 +163,9 @@ $\langle$HistType {\footnotesize ?}$\rangle\equiv$
|
|||||||
\mbox{}\verb@ SConnection *pCon);@\\
|
\mbox{}\verb@ SConnection *pCon);@\\
|
||||||
\mbox{}\verb@ float (*GetTime)(pHistDriver self,@\\
|
\mbox{}\verb@ float (*GetTime)(pHistDriver self,@\\
|
||||||
\mbox{}\verb@ SConnection *pCon);@\\
|
\mbox{}\verb@ SConnection *pCon);@\\
|
||||||
|
\mbox{}\verb@ HistInt *(*SubSample)(pHistDriver self, @\\
|
||||||
|
\mbox{}\verb@ SConnection *pCon,int bank,@\\
|
||||||
|
\mbox{}\verb@ char *command); @\\
|
||||||
\mbox{}\verb@ int (*Preset)(pHistDriver self,@\\
|
\mbox{}\verb@ int (*Preset)(pHistDriver self,@\\
|
||||||
\mbox{}\verb@ SConnection *pCon,@\\
|
\mbox{}\verb@ SConnection *pCon,@\\
|
||||||
\mbox{}\verb@ HistInt iVal);@\\
|
\mbox{}\verb@ HistInt iVal);@\\
|
||||||
|
@ -130,6 +130,9 @@ definition:
|
|||||||
SConnection *pCon);
|
SConnection *pCon);
|
||||||
float (*GetTime)(pHistDriver self,
|
float (*GetTime)(pHistDriver self,
|
||||||
SConnection *pCon);
|
SConnection *pCon);
|
||||||
|
HistInt *(*SubSample)(pHistDriver self,
|
||||||
|
SConnection *pCon,int bank,
|
||||||
|
char *command);
|
||||||
int (*Preset)(pHistDriver self,
|
int (*Preset)(pHistDriver self,
|
||||||
SConnection *pCon,
|
SConnection *pCon,
|
||||||
HistInt iVal);
|
HistInt iVal);
|
||||||
|
273
histregress.c
Normal file
273
histregress.c
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
/*----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
H I S T S I M
|
||||||
|
|
||||||
|
A simulated histogram memory for regression tests.
|
||||||
|
|
||||||
|
All the counting error stuff is redirected to a regression counter; see
|
||||||
|
documentation there. This just adds data handling.
|
||||||
|
|
||||||
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, October 2006
|
||||||
|
----------------------------------------------------------------------------*/
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "fortify.h"
|
||||||
|
#include "sics.h"
|
||||||
|
#include "countdriv.h"
|
||||||
|
#include "counter.h"
|
||||||
|
#include "stringdict.h"
|
||||||
|
#include "HistMem.h"
|
||||||
|
#include "HistDriv.i"
|
||||||
|
#include "histsim.h"
|
||||||
|
|
||||||
|
static int iSet = 0;
|
||||||
|
static HistInt iSetVal = 0;
|
||||||
|
static HistMode eHistMode;
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int RegressConfig(pHistDriver self, SConnection *pCon,
|
||||||
|
pStringDict pOption, SicsInterp *pSics)
|
||||||
|
{
|
||||||
|
int i, iLength = 1, status;
|
||||||
|
char pData[132];
|
||||||
|
float fFail;
|
||||||
|
pCounterDriver count;
|
||||||
|
|
||||||
|
count = (pCounterDriver)self->pPriv;
|
||||||
|
|
||||||
|
if(eHistMode == eHTOF)
|
||||||
|
{
|
||||||
|
for(i = 0; i < self->data->rank; i++)
|
||||||
|
{
|
||||||
|
iLength *= self->data->iDim[i];
|
||||||
|
}
|
||||||
|
iLength *= self->data->nTimeChan;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
deal with error settings
|
||||||
|
*/
|
||||||
|
status = StringDictGet(pOption,"errortype",pData,131);
|
||||||
|
if(status)
|
||||||
|
{
|
||||||
|
|
||||||
|
fFail = atof(pData);
|
||||||
|
count->Set(count,"errortype",1,fFail);
|
||||||
|
}
|
||||||
|
status = StringDictGet(pOption,"recover",pData,131);
|
||||||
|
if(status)
|
||||||
|
{
|
||||||
|
|
||||||
|
fFail = atof(pData);
|
||||||
|
count->Set(count,"recover",1,fFail);
|
||||||
|
}
|
||||||
|
status = StringDictGet(pOption,"finish",pData,131);
|
||||||
|
if(status)
|
||||||
|
{
|
||||||
|
|
||||||
|
fFail = atof(pData);
|
||||||
|
count->Set(count,"finish",1,fFail);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
configured test value
|
||||||
|
*/
|
||||||
|
status = StringDictGet(pOption,"testval",pData,131);
|
||||||
|
if(status)
|
||||||
|
{
|
||||||
|
iSet = 1;
|
||||||
|
iSetVal = atoi(pData);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int RegressStart(pHistDriver self, SConnection *pCon)
|
||||||
|
{
|
||||||
|
pCounterDriver pDriv;
|
||||||
|
|
||||||
|
pDriv = (pCounterDriver)self->pPriv;
|
||||||
|
pDriv->fPreset = self->fCountPreset;
|
||||||
|
pDriv->eMode = self->eCount;
|
||||||
|
return pDriv->Start(pDriv);
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int RegressPause(pHistDriver self, SConnection *pCon)
|
||||||
|
{
|
||||||
|
pCounterDriver pDriv;
|
||||||
|
|
||||||
|
pDriv = (pCounterDriver)self->pPriv;
|
||||||
|
pDriv->fPreset = self->fCountPreset;
|
||||||
|
pDriv->eMode = self->eCount;
|
||||||
|
return pDriv->Pause(pDriv);
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
static int RegressContinue(pHistDriver self, SConnection *pCon)
|
||||||
|
{
|
||||||
|
pCounterDriver pDriv;
|
||||||
|
|
||||||
|
pDriv = (pCounterDriver)self->pPriv;
|
||||||
|
pDriv->fPreset = self->fCountPreset;
|
||||||
|
pDriv->eMode = self->eCount;
|
||||||
|
return pDriv->Continue(pDriv);
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int RegressHalt(pHistDriver self)
|
||||||
|
{
|
||||||
|
pCounterDriver pDriv;
|
||||||
|
|
||||||
|
pDriv = (pCounterDriver)self->pPriv;
|
||||||
|
return pDriv->Halt(pDriv);
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int RegressGetCountStatus(pHistDriver self, SConnection *pCon)
|
||||||
|
{
|
||||||
|
pCounterDriver pDriv;
|
||||||
|
float fControl;
|
||||||
|
|
||||||
|
pDriv = (pCounterDriver)self->pPriv;
|
||||||
|
return pDriv->GetStatus(pDriv,&fControl);
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int RegressGetError(pHistDriver self, int *iCode, char *pError, int iLen)
|
||||||
|
{
|
||||||
|
pCounterDriver pDriv;
|
||||||
|
|
||||||
|
pDriv = (pCounterDriver)self->pPriv;
|
||||||
|
return pDriv->GetError(pDriv, iCode,pError,iLen);
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int RegressTryAndFixIt(pHistDriver self, int iCode)
|
||||||
|
{
|
||||||
|
pCounterDriver pDriv;
|
||||||
|
|
||||||
|
pDriv = (pCounterDriver)self->pPriv;
|
||||||
|
return pDriv->TryAndFixIt(pDriv, iCode);
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int RegressGetData(pHistDriver self, SConnection *pCon)
|
||||||
|
{
|
||||||
|
pCounterDriver pDriv;
|
||||||
|
|
||||||
|
pDriv = (pCounterDriver)self->pPriv;
|
||||||
|
|
||||||
|
return pDriv->ReadValues(pDriv);
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int RegressGetHistogram(pHistDriver self, SConnection *pCon,
|
||||||
|
int i, int iStart, int iEnd, HistInt *lData)
|
||||||
|
{
|
||||||
|
int ii;
|
||||||
|
|
||||||
|
if(i < 0)
|
||||||
|
{
|
||||||
|
SCWrite(pCon,"ERROR: histogram out of range",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(iSet == 1)
|
||||||
|
{
|
||||||
|
for(ii = iStart; ii < iEnd; ii++)
|
||||||
|
{
|
||||||
|
lData[ii-iStart] = iSetVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(ii = iStart; ii < iEnd; ii++)
|
||||||
|
{
|
||||||
|
lData[ii-iStart] = random();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
static int RegressSetHistogram(pHistDriver self, SConnection *pCon,
|
||||||
|
int i, int iStart, int iEnd, HistInt *lData)
|
||||||
|
{
|
||||||
|
iSet = 1;
|
||||||
|
iSetVal = lData[0];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int RegressPreset(pHistDriver self, SConnection *pCon, HistInt iVal)
|
||||||
|
{
|
||||||
|
iSet = 1;
|
||||||
|
iSetVal = iVal;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
static int RegressFreePrivate(pHistDriver self)
|
||||||
|
{
|
||||||
|
pCounterDriver pDriv;
|
||||||
|
|
||||||
|
pDriv = (pCounterDriver)self->pPriv;
|
||||||
|
DeleteCounterDriver(pDriv);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
static long RegressGetMonitor(pHistDriver self, int i, SConnection *pCon)
|
||||||
|
{
|
||||||
|
pCounterDriver pDriv;
|
||||||
|
long lVal;
|
||||||
|
|
||||||
|
pDriv = (pCounterDriver)self->pPriv;
|
||||||
|
return pDriv->lCounts[i];
|
||||||
|
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
static float RegressGetTime(pHistDriver self, SConnection *pCon)
|
||||||
|
{
|
||||||
|
pCounterDriver pDriv;
|
||||||
|
long lVal;
|
||||||
|
|
||||||
|
pDriv = (pCounterDriver)self->pPriv;
|
||||||
|
return pDriv->fTime;
|
||||||
|
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
pHistDriver CreateRegressHM(pStringDict pOpt)
|
||||||
|
{
|
||||||
|
pHistDriver pNew = NULL;
|
||||||
|
|
||||||
|
/* create the general driver */
|
||||||
|
pNew = CreateHistDriver(pOpt);
|
||||||
|
if(!pNew)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* put a Regresscounter in */
|
||||||
|
pNew->pPriv = (void *)NewRegressCounter("HistoRegress");
|
||||||
|
if(!pNew->pPriv)
|
||||||
|
{
|
||||||
|
DeleteHistDriver(pNew);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* configure all those functions */
|
||||||
|
pNew->Configure = RegressConfig;
|
||||||
|
pNew->Start = RegressStart;
|
||||||
|
pNew->Halt = RegressHalt;
|
||||||
|
pNew->GetCountStatus = RegressGetCountStatus;
|
||||||
|
pNew->GetError = RegressGetError;
|
||||||
|
pNew->TryAndFixIt = RegressTryAndFixIt;
|
||||||
|
pNew->GetData = RegressGetData;
|
||||||
|
pNew->GetHistogram = RegressGetHistogram;
|
||||||
|
pNew->SetHistogram = RegressSetHistogram;
|
||||||
|
pNew->GetMonitor = RegressGetMonitor;
|
||||||
|
pNew->GetTime = RegressGetTime;
|
||||||
|
pNew->Preset = RegressPreset;
|
||||||
|
pNew->FreePrivate = RegressFreePrivate;
|
||||||
|
pNew->Pause = RegressPause;
|
||||||
|
pNew->Continue = RegressContinue;
|
||||||
|
StringDictAddPair(pOpt,"errortype","0");
|
||||||
|
StringDictAddPair(pOpt,"recover","1");
|
||||||
|
StringDictAddPair(pOpt,"testval","0");
|
||||||
|
|
||||||
|
return pNew;
|
||||||
|
}
|
@ -183,6 +183,13 @@
|
|||||||
lData[ii-iStart] = iSetVal;
|
lData[ii-iStart] = iSetVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(iSet == 2)
|
||||||
|
{
|
||||||
|
for(ii = iStart; ii < iEnd; ii++)
|
||||||
|
{
|
||||||
|
lData[ii-iStart] = self->data->localBuffer[ii];
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for(ii = iStart; ii < iEnd; ii++)
|
for(ii = iStart; ii < iEnd; ii++)
|
||||||
@ -196,7 +203,7 @@
|
|||||||
static int SimSetHistogram(pHistDriver self, SConnection *pCon,
|
static int SimSetHistogram(pHistDriver self, SConnection *pCon,
|
||||||
int i, int iStart, int iEnd, HistInt *lData)
|
int i, int iStart, int iEnd, HistInt *lData)
|
||||||
{
|
{
|
||||||
iSet = 1;
|
iSet = 2;
|
||||||
iSetVal = lData[0];
|
iSetVal = lData[0];
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
81
hkl.c
81
hkl.c
@ -61,7 +61,6 @@
|
|||||||
fprintf(fd,"%s hm %d\n",name, self->iHM);
|
fprintf(fd,"%s hm %d\n",name, self->iHM);
|
||||||
fprintf(fd,"%s scantolerance %f\n", name,self->scanTolerance);
|
fprintf(fd,"%s scantolerance %f\n", name,self->scanTolerance);
|
||||||
fprintf(fd,"%s nb %d\n", name, self->iNOR);
|
fprintf(fd,"%s nb %d\n", name, self->iNOR);
|
||||||
fprintf(fd,"%s phiom %d\n", name, self->iOMPHI);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,7 +688,7 @@ int hklInRange(void *data, float fSet[4], int mask[4])
|
|||||||
fSet[0] = dTheta;
|
fSet[0] = dTheta;
|
||||||
|
|
||||||
/* for omega check against the limits +- SCANBORDER in order to allow for
|
/* for omega check against the limits +- SCANBORDER in order to allow for
|
||||||
a omega scan
|
a omega scan.
|
||||||
*/
|
*/
|
||||||
MotorGetPar(self->pOmega,"softlowerlim",&fLimit);
|
MotorGetPar(self->pOmega,"softlowerlim",&fLimit);
|
||||||
if((float)fSet[1] < fLimit + self->scanTolerance){
|
if((float)fSet[1] < fLimit + self->scanTolerance){
|
||||||
@ -721,7 +720,7 @@ static int calculateBisecting(MATRIX z1, pHKL self, SConnection *pCon,
|
|||||||
float fSet[4], double myPsi, int iRetry)
|
float fSet[4], double myPsi, int iRetry)
|
||||||
{
|
{
|
||||||
double stt, om, chi, phi, psi, ompsi, chipsi, phipsi;
|
double stt, om, chi, phi, psi, ompsi, chipsi, phipsi;
|
||||||
int i, test;
|
int i, test, mask[4];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
just the plain angle calculation
|
just the plain angle calculation
|
||||||
@ -731,16 +730,31 @@ static int calculateBisecting(MATRIX z1, pHKL self, SConnection *pCon,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fSet[0] = stt;
|
||||||
|
fSet[1] = om;
|
||||||
|
fSet[2] = chi;
|
||||||
|
fSet[3] = phi;
|
||||||
if(iRetry == 1) {
|
if(iRetry == 1) {
|
||||||
rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi);
|
rotatePsi(om,chi,phi,myPsi,&ompsi,&chipsi,&phipsi);
|
||||||
fSet[1] = ompsi;
|
fSet[1] = ompsi;
|
||||||
fSet[2] = circlify(chipsi);
|
fSet[2] = circlify(chipsi);
|
||||||
fSet[3] = circlify(phipsi);
|
fSet[3] = circlify(phipsi);
|
||||||
return 1;
|
return 1;
|
||||||
|
} else {
|
||||||
|
if(hklInRange(self,fSet, mask) == 1){
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
if(tryOmegaTweak(self,z1, &stt, &om, &chi, &phi) == 1){
|
||||||
|
fSet[0] = stt;
|
||||||
|
fSet[1] = om;
|
||||||
|
fSet[2] = chi;
|
||||||
|
fSet[3] = phi;
|
||||||
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return findAllowedBisecting(self->fLambda, z1, fSet, hklInRange,self);
|
return findAllowedBisecting(self->fLambda, z1, fSet, hklInRange,self);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
static int calculateNormalBeam(MATRIX z1, pHKL self, SConnection *pCon,
|
static int calculateNormalBeam(MATRIX z1, pHKL self, SConnection *pCon,
|
||||||
@ -780,7 +794,7 @@ static int calculateNormalBeam(MATRIX z1, pHKL self, SConnection *pCon,
|
|||||||
|
|
||||||
|
|
||||||
status = z1mToNormalBeam(self->fLambda, z3, &gamma, &omnb, &nu);
|
status = z1mToNormalBeam(self->fLambda, z3, &gamma, &omnb, &nu);
|
||||||
omnb += 180.;
|
/* omnb += 180.; */
|
||||||
mat_free(z3);
|
mat_free(z3);
|
||||||
if(status != 1)
|
if(status != 1)
|
||||||
{
|
{
|
||||||
@ -788,10 +802,14 @@ static int calculateNormalBeam(MATRIX z1, pHKL self, SConnection *pCon,
|
|||||||
}
|
}
|
||||||
if(checkNormalBeam(omnb, &gamma, nu,fSet,pCon,self)){
|
if(checkNormalBeam(omnb, &gamma, nu,fSet,pCon,self)){
|
||||||
return 1;
|
return 1;
|
||||||
|
} else {
|
||||||
|
if(checkNormalBeam(omnb + 360., &gamma, nu, fSet,pCon,self)){
|
||||||
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
|
static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
|
||||||
SConnection *pCon,
|
SConnection *pCon,
|
||||||
@ -903,30 +921,6 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
|
|||||||
if(self->iNOR == 0)
|
if(self->iNOR == 0)
|
||||||
{
|
{
|
||||||
status = calculateBisecting(z1,self,pCon,fSet, myPsi, iRetry);
|
status = calculateBisecting(z1,self,pCon,fSet, myPsi, iRetry);
|
||||||
/*
|
|
||||||
* Betrand mode: wrap phi rotation into omega
|
|
||||||
*/
|
|
||||||
if(self->iOMPHI > 0) {
|
|
||||||
if(ABS(fSet[2] - .0) < .1 || ABS(fSet[2] - 180.) < .1){
|
|
||||||
fSet[1] -= fSet[3];
|
|
||||||
/*
|
|
||||||
fSet[1] = 360. - fSet[3];
|
|
||||||
*/
|
|
||||||
fSet[3] = .0;
|
|
||||||
if(fSet[1] < 0.){
|
|
||||||
fSet[1] += 360.;
|
|
||||||
}
|
|
||||||
if(fSet[1] > 360.0){
|
|
||||||
fSet[1] -= 360.;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
snprintf(pBueffel,511,
|
|
||||||
"ERROR: for omphi mode chi must be 0 or 180, is %f",
|
|
||||||
fSet[2]);
|
|
||||||
SCWrite(pCon,pBueffel,eError);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(self->iNOR == 1)
|
else if(self->iNOR == 1)
|
||||||
{
|
{
|
||||||
@ -1414,8 +1408,8 @@ ente:
|
|||||||
if(strcmp(argv[1],"list") == 0 )
|
if(strcmp(argv[1],"list") == 0 )
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,
|
sprintf(pBueffel,
|
||||||
"lambda = %f Normal Beam = %d PHIOM = %d Quadrant = %d HM = %d",
|
"lambda = %f Normal Beam = %d Quadrant = %d HM = %d",
|
||||||
self->fLambda, self->iNOR, self->iOMPHI,
|
self->fLambda, self->iNOR,
|
||||||
self->iQuad,self->iHM);
|
self->iQuad,self->iHM);
|
||||||
SCWrite(pCon,pBueffel,eValue);
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
sprintf(pBueffel,"UB = { %f %f %f",
|
sprintf(pBueffel,"UB = { %f %f %f",
|
||||||
@ -1654,29 +1648,6 @@ ente:
|
|||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*------------- phi omega mode (to be removed) */
|
|
||||||
else if(strcmp(argv[1],"phiom") == 0)
|
|
||||||
{
|
|
||||||
if(argc < 3)
|
|
||||||
{
|
|
||||||
snprintf(pBueffel,511,"%s.phiom = %d",argv[0],self->iOMPHI);
|
|
||||||
SCWrite(pCon,pBueffel,eValue);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if(!SCMatchRights(pCon,usUser))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(!isNumeric(argv[2]))
|
|
||||||
{
|
|
||||||
sprintf(pBueffel,"ERROR: %s was not recognized as a number", argv[2]);
|
|
||||||
SCWrite(pCon,pBueffel,eError);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
self->iOMPHI = atoi(argv[2]);
|
|
||||||
SCSendOK(pCon);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/*------------- quadrant */
|
/*------------- quadrant */
|
||||||
else if(strcmp(argv[1],"quadrant") == 0)
|
else if(strcmp(argv[1],"quadrant") == 0)
|
||||||
{
|
{
|
||||||
|
1
hkl.i
1
hkl.i
@ -15,7 +15,6 @@
|
|||||||
int iManual;
|
int iManual;
|
||||||
double fLastHKL[5];
|
double fLastHKL[5];
|
||||||
int iNOR;
|
int iNOR;
|
||||||
int iOMPHI;
|
|
||||||
int iQuad;
|
int iQuad;
|
||||||
int iHM;
|
int iHM;
|
||||||
pMotor pTheta;
|
pMotor pTheta;
|
||||||
|
1
hkl.tex
1
hkl.tex
@ -26,7 +26,6 @@ $\langle$hkldat {\footnotesize ?}$\rangle\equiv$
|
|||||||
\mbox{}\verb@ int iManual;@\\
|
\mbox{}\verb@ int iManual;@\\
|
||||||
\mbox{}\verb@ double fLastHKL[5];@\\
|
\mbox{}\verb@ double fLastHKL[5];@\\
|
||||||
\mbox{}\verb@ int iNOR;@\\
|
\mbox{}\verb@ int iNOR;@\\
|
||||||
\mbox{}\verb@ int iOMPHI;@\\
|
|
||||||
\mbox{}\verb@ int iQuad;@\\
|
\mbox{}\verb@ int iQuad;@\\
|
||||||
\mbox{}\verb@ int iHM;@\\
|
\mbox{}\verb@ int iHM;@\\
|
||||||
\mbox{}\verb@ pMotor pTheta;@\\
|
\mbox{}\verb@ pMotor pTheta;@\\
|
||||||
|
1
hkl.w
1
hkl.w
@ -21,7 +21,6 @@ The object uses the following object data structure:
|
|||||||
int iManual;
|
int iManual;
|
||||||
double fLastHKL[5];
|
double fLastHKL[5];
|
||||||
int iNOR;
|
int iNOR;
|
||||||
int iOMPHI;
|
|
||||||
int iQuad;
|
int iQuad;
|
||||||
int iHM;
|
int iHM;
|
||||||
pMotor pTheta;
|
pMotor pTheta;
|
||||||
|
@ -310,7 +310,7 @@ int HMControlAction(SConnection *pCon, SicsInterp *pSics,
|
|||||||
assert(self);
|
assert(self);
|
||||||
if(argc < 4)
|
if(argc < 4)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"ERROR: Usage %s start preset mode", argv[0]);
|
snprintf(pBueffel,131,"ERROR: Usage %s start preset mode", argv[0]);
|
||||||
SCWrite(pCon,pBueffel,eError);
|
SCWrite(pCon,pBueffel,eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
110
hmdata.c
110
hmdata.c
@ -5,11 +5,15 @@
|
|||||||
copyright: see file COPYRIGHT
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
Mark Koennecke, January 2003
|
Mark Koennecke, January 2003
|
||||||
|
|
||||||
|
Added loading HM data from file, Mark Koennecke, November 2006
|
||||||
-------------------------------------------------------------------------*/
|
-------------------------------------------------------------------------*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include "splitter.h"
|
||||||
#include "fortify.h"
|
#include "fortify.h"
|
||||||
#include "hmdata.h"
|
#include "hmdata.h"
|
||||||
#include "HistMem.h"
|
#include "HistMem.h"
|
||||||
@ -46,7 +50,7 @@ void clearHMData(pHMdata self){
|
|||||||
size *= self->iDim[i];
|
size *= self->iDim[i];
|
||||||
}
|
}
|
||||||
if(self->tofMode){
|
if(self->tofMode){
|
||||||
size *= self->nTimeChan;
|
size *= getNoOfTimebins(self);
|
||||||
}
|
}
|
||||||
memset(self->localBuffer,0,size*sizeof(HistInt));
|
memset(self->localBuffer,0,size*sizeof(HistInt));
|
||||||
}
|
}
|
||||||
@ -60,7 +64,7 @@ static int resizeBuffer(pHMdata self){
|
|||||||
size *= self->iDim[i];
|
size *= self->iDim[i];
|
||||||
}
|
}
|
||||||
if(self->tofMode){
|
if(self->tofMode){
|
||||||
size *= self->nTimeChan;
|
size *= getNoOfTimebins(self);
|
||||||
}
|
}
|
||||||
if(self->localBuffer != NULL){
|
if(self->localBuffer != NULL){
|
||||||
free(self->localBuffer);
|
free(self->localBuffer);
|
||||||
@ -80,6 +84,7 @@ int configureHMdata(pHMdata self, pStringDict pOpt,
|
|||||||
int status, i;
|
int status, i;
|
||||||
float fVal;
|
float fVal;
|
||||||
char pValue[80];
|
char pValue[80];
|
||||||
|
pHistMem master = NULL;
|
||||||
|
|
||||||
if(self->nTimeChan > 2) {
|
if(self->nTimeChan > 2) {
|
||||||
self->tofMode = 1;
|
self->tofMode = 1;
|
||||||
@ -111,6 +116,18 @@ int configureHMdata(pHMdata self, pStringDict pOpt,
|
|||||||
self->updateIntervall = (int)rint(fVal);
|
self->updateIntervall = (int)rint(fVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = StringDictGet(pOpt,"timeslave",pValue, 79);
|
||||||
|
if(status == 1) {
|
||||||
|
master = (pHistMem)FindCommandData(pServ->pSics,pValue,"HistMem");
|
||||||
|
if(master == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: timeslave requested, but master HM not found",
|
||||||
|
eError);
|
||||||
|
} else {
|
||||||
|
self->timeslave = master->pDriv->data;
|
||||||
|
self->tofMode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
invalidate buffer
|
invalidate buffer
|
||||||
*/
|
*/
|
||||||
@ -138,7 +155,7 @@ int configureHMdata(pHMdata self, pStringDict pOpt,
|
|||||||
int genTimeBinning(pHMdata self, float start, float step, int noSteps){
|
int genTimeBinning(pHMdata self, float start, float step, int noSteps){
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(noSteps >= MAXCHAN){
|
if(noSteps >= MAXCHAN || self->timeslave != NULL){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for(i = 0; i < noSteps; i++){
|
for(i = 0; i < noSteps; i++){
|
||||||
@ -150,6 +167,10 @@ int genTimeBinning(pHMdata self, float start, float step, int noSteps){
|
|||||||
}
|
}
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
int setTimeBin(pHMdata self, int index, float value){
|
int setTimeBin(pHMdata self, int index, float value){
|
||||||
|
if(self->timeslave != NULL){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(index >= 0 && index < MAXCHAN){
|
if(index >= 0 && index < MAXCHAN){
|
||||||
self->timeBinning[index] = value;
|
self->timeBinning[index] = value;
|
||||||
} else {
|
} else {
|
||||||
@ -157,7 +178,7 @@ int setTimeBin(pHMdata self, int index, float value){
|
|||||||
}
|
}
|
||||||
self->tofMode = 1;
|
self->tofMode = 1;
|
||||||
if(index > self->nTimeChan){
|
if(index > self->nTimeChan){
|
||||||
self->nTimeChan = index;
|
self->nTimeChan = index+1;
|
||||||
return resizeBuffer(self);
|
return resizeBuffer(self);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -168,18 +189,28 @@ int isInTOFMode(pHMdata self){
|
|||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
int getNoOfTimebins(pHMdata self){
|
int getNoOfTimebins(pHMdata self){
|
||||||
|
if(self->timeslave != NULL){
|
||||||
|
return getNoOfTimebins(self->timeslave);
|
||||||
|
} else {
|
||||||
return self->nTimeChan;
|
return self->nTimeChan;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
float *getTimeBinning(pHMdata self){
|
float *getTimeBinning(pHMdata self){
|
||||||
|
if(self->timeslave != NULL){
|
||||||
|
return getTimeBinning(self->timeslave);
|
||||||
|
} else {
|
||||||
return self->timeBinning;
|
return self->timeBinning;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/*-------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------*/
|
||||||
void clearTimeBinning(pHMdata self){
|
void clearTimeBinning(pHMdata self){
|
||||||
|
if(self->timeslave == NULL){
|
||||||
self->nTimeChan = 1;
|
self->nTimeChan = 1;
|
||||||
self->tofMode = 0;
|
self->tofMode = 0;
|
||||||
resizeBuffer(self);
|
resizeBuffer(self);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
void getHMDataDim(pHMdata self, int iDim[MAXDIM], int *rank){
|
void getHMDataDim(pHMdata self, int iDim[MAXDIM], int *rank){
|
||||||
memcpy(iDim,self->iDim,self->rank*sizeof(int));
|
memcpy(iDim,self->iDim,self->rank*sizeof(int));
|
||||||
@ -193,7 +224,7 @@ long getHMDataLength(pHMdata self){
|
|||||||
length *= self->iDim[i];
|
length *= self->iDim[i];
|
||||||
}
|
}
|
||||||
if(self->tofMode){
|
if(self->tofMode){
|
||||||
length *= self->nTimeChan;
|
length *= getNoOfTimebins(self);
|
||||||
}
|
}
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
@ -227,6 +258,10 @@ static int updateHMbuffer(pHistMem hist, int bank, SConnection *pCon){
|
|||||||
|
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
|
if(self->timeslave != NULL){
|
||||||
|
resizeBuffer(self);
|
||||||
|
}
|
||||||
|
|
||||||
for(i = 0; i < 3; i++){
|
for(i = 0; i < 3; i++){
|
||||||
status = hist->pDriv->GetHistogram(hist->pDriv,pCon,
|
status = hist->pDriv->GetHistogram(hist->pDriv,pCon,
|
||||||
bank,0,getHMDataLength(self),
|
bank,0,getHMDataLength(self),
|
||||||
@ -292,7 +327,7 @@ HistInt *getHMDataBufferPointer(pHistMem hist,SConnection *pCon){
|
|||||||
|
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
if(self->localBuffer == NULL){
|
if(self->localBuffer == NULL || self->timeslave != NULL){
|
||||||
resizeBuffer(self);
|
resizeBuffer(self);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -327,7 +362,7 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
|||||||
int iStart[MAXDIM], int iEnd[MAXDIM]) {
|
int iStart[MAXDIM], int iEnd[MAXDIM]) {
|
||||||
HistInt *iData;
|
HistInt *iData;
|
||||||
pHMdata self = hist->pDriv->data;
|
pHMdata self = hist->pDriv->data;
|
||||||
int i, iHistLength, status, iIndex;
|
int i, iHistLength, status, iIndex, myrank;
|
||||||
char pBueffel[256];
|
char pBueffel[256];
|
||||||
unsigned long lSum, lRowSum;
|
unsigned long lSum, lRowSum;
|
||||||
|
|
||||||
@ -336,7 +371,12 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
|||||||
/*
|
/*
|
||||||
error checking
|
error checking
|
||||||
*/
|
*/
|
||||||
for(i = 0; i < self->rank; i++){
|
myrank = self->rank;
|
||||||
|
if(isInTOFMode(self)){
|
||||||
|
self->iDim[self->rank] = getNoOfTimebins(self);
|
||||||
|
myrank++;
|
||||||
|
}
|
||||||
|
for(i = 0; i < myrank; i++){
|
||||||
if( (iStart[i] < 0) || (iStart[i] > self->iDim[i]) ) {
|
if( (iStart[i] < 0) || (iStart[i] > self->iDim[i]) ) {
|
||||||
sprintf(pBueffel,"ERROR: %d is out of data dimension range",
|
sprintf(pBueffel,"ERROR: %d is out of data dimension range",
|
||||||
iStart[i]);
|
iStart[i]);
|
||||||
@ -367,13 +407,14 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
|||||||
|
|
||||||
iHistLength = getHMDataLength(self);
|
iHistLength = getHMDataLength(self);
|
||||||
/* actually sum */
|
/* actually sum */
|
||||||
switch(self->rank)
|
switch(myrank)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
lSum = SumRow(self->localBuffer, iHistLength,
|
lSum = SumRow(self->localBuffer, iHistLength,
|
||||||
iStart[0], iEnd[0]);
|
iStart[0], iEnd[0]);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
|
if(isInTOFMode(self)){
|
||||||
lSum = 0;
|
lSum = 0;
|
||||||
for(i = iStart[0]; i < iEnd[0]; i++){
|
for(i = iStart[0]; i < iEnd[0]; i++){
|
||||||
iIndex = i*self->iDim[1];
|
iIndex = i*self->iDim[1];
|
||||||
@ -381,11 +422,20 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
|||||||
iIndex+iStart[1], iIndex+iEnd[1]);
|
iIndex+iStart[1], iIndex+iEnd[1]);
|
||||||
lSum += lRowSum;
|
lSum += lRowSum;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
lSum = 0;
|
||||||
|
for(i = iStart[1]; i < iEnd[1]; i++){
|
||||||
|
iIndex = i*self->iDim[0];
|
||||||
|
lRowSum = SumRow(self->localBuffer,iHistLength,
|
||||||
|
iIndex+iStart[0], iIndex+iEnd[0]);
|
||||||
|
lSum += lRowSum;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sprintf(pBueffel,
|
sprintf(pBueffel,
|
||||||
"ERROR: summing in %d dimensions not yet implemented",
|
"ERROR: summing in %d dimensions not yet implemented",
|
||||||
self->rank);
|
myrank);
|
||||||
SCWrite(pCon,pBueffel,eError);
|
SCWrite(pCon,pBueffel,eError);
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
@ -395,3 +445,43 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
|||||||
}
|
}
|
||||||
return lSum;
|
return lSum;
|
||||||
}
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
int loadHMData(pHMdata self, SConnection *pCon, char *filename){
|
||||||
|
FILE *fd = NULL;
|
||||||
|
char buffer[1024], pNumber[80], *pPtr;
|
||||||
|
long i = 0, length;
|
||||||
|
HistInt *data = NULL;
|
||||||
|
|
||||||
|
fd = fopen(filename,"r");
|
||||||
|
if(fd == NULL){
|
||||||
|
snprintf(buffer,1023,"ERROR: failed to open file %s", filename);
|
||||||
|
SCWrite(pCon,buffer,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
length = getHMDataLength(self);
|
||||||
|
if(self->localBuffer == NULL || self->timeslave != NULL){
|
||||||
|
resizeBuffer(self);
|
||||||
|
}
|
||||||
|
data = self->localBuffer;
|
||||||
|
if(data == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: failed to allocate HM", eError);
|
||||||
|
fclose(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
while(i < length && fgets(buffer,1024,fd) != NULL){
|
||||||
|
pPtr = buffer;
|
||||||
|
while(pPtr != NULL){
|
||||||
|
pPtr = sicsNextNumber(pPtr,pNumber);
|
||||||
|
if(pPtr != NULL){
|
||||||
|
data[i] = atoi(pNumber);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i < length-1){
|
||||||
|
SCWrite(pCon,"WARNING: not enough data in file to fill HM",eWarning);
|
||||||
|
}
|
||||||
|
fclose(fd);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
4
hmdata.h
4
hmdata.h
@ -16,7 +16,7 @@
|
|||||||
#define MAXDIM 3
|
#define MAXDIM 3
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct __hmdata{
|
||||||
int rank;
|
int rank;
|
||||||
int iDim[MAXDIM];
|
int iDim[MAXDIM];
|
||||||
int nTimeChan;
|
int nTimeChan;
|
||||||
@ -26,6 +26,7 @@
|
|||||||
int updateIntervall;
|
int updateIntervall;
|
||||||
int updateFlag;
|
int updateFlag;
|
||||||
HistInt *localBuffer;
|
HistInt *localBuffer;
|
||||||
|
struct __hmdata *timeslave;
|
||||||
} HMdata, *pHMdata;
|
} HMdata, *pHMdata;
|
||||||
|
|
||||||
|
|
||||||
@ -56,6 +57,7 @@
|
|||||||
|
|
||||||
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
|
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
|
||||||
int start[MAXDIM], int end[MAXDIM]);
|
int start[MAXDIM], int end[MAXDIM]);
|
||||||
|
int loadHMData(pHMdata self, SConnection *pCon, char *filename);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
6
hmdata.w
6
hmdata.w
@ -11,7 +11,7 @@ display clients gone mad. This task is also handled through this class.
|
|||||||
|
|
||||||
In order to do this, the following data structure is needed:
|
In order to do this, the following data structure is needed:
|
||||||
@d hmdatadat @{
|
@d hmdatadat @{
|
||||||
typedef struct {
|
typedef struct __hmdata{
|
||||||
int rank;
|
int rank;
|
||||||
int iDim[MAXDIM];
|
int iDim[MAXDIM];
|
||||||
int nTimeChan;
|
int nTimeChan;
|
||||||
@ -21,6 +21,7 @@ In order to do this, the following data structure is needed:
|
|||||||
int updateIntervall;
|
int updateIntervall;
|
||||||
int updateFlag;
|
int updateFlag;
|
||||||
HistInt *localBuffer;
|
HistInt *localBuffer;
|
||||||
|
struct __hmdata *timeslave;
|
||||||
} HMdata, *pHMdata;
|
} HMdata, *pHMdata;
|
||||||
@}
|
@}
|
||||||
|
|
||||||
@ -52,6 +53,7 @@ The following functions work on this data structure:
|
|||||||
|
|
||||||
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
|
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
|
||||||
int start[MAXDIM], int end[MAXDIM]);
|
int start[MAXDIM], int end[MAXDIM]);
|
||||||
|
int loadHMData(pHMdata self, SConnection *pCon, char *filename);
|
||||||
@}
|
@}
|
||||||
|
|
||||||
\begin{description}
|
\begin{description}
|
||||||
@ -83,6 +85,8 @@ the histogram memory and not from the buffer the next time round.
|
|||||||
pointer of HMdata. Use with extra care!
|
pointer of HMdata. Use with extra care!
|
||||||
\item[sumHMDataRectangle] sums a rectangular box delimted by start and end
|
\item[sumHMDataRectangle] sums a rectangular box delimted by start and end
|
||||||
from the histogram memory.
|
from the histogram memory.
|
||||||
|
\item[loadHMData] loads histogram memory data from a file. This is for
|
||||||
|
debugging purposes. The file must contain enough numbers to fill the HM.
|
||||||
\end{description}
|
\end{description}
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,8 +12,9 @@ Markus Zolliker, March 2005
|
|||||||
|
|
||||||
typedef struct Item {
|
typedef struct Item {
|
||||||
struct Item *next;
|
struct Item *next;
|
||||||
const char *type;
|
char *type;
|
||||||
const char *name;
|
char *name;
|
||||||
|
char *desc;
|
||||||
Initializer maker;
|
Initializer maker;
|
||||||
int startupOnly;
|
int startupOnly;
|
||||||
} Item;
|
} Item;
|
||||||
@ -21,15 +22,17 @@ typedef struct Item {
|
|||||||
static Item *list = NULL;
|
static Item *list = NULL;
|
||||||
static int startup = 1;
|
static int startup = 1;
|
||||||
|
|
||||||
void MakeInitializer(const char *type, const char *name, Initializer maker, int startupOnly) {
|
void MakeInitializer(const char *type, const char *name, Initializer maker,
|
||||||
|
int startupOnly, const char *desc) {
|
||||||
Item *item;
|
Item *item;
|
||||||
|
|
||||||
item = calloc(1, sizeof *item);
|
item = calloc(1, sizeof *item);
|
||||||
assert(item);
|
assert(item);
|
||||||
item->maker = maker;
|
item->maker = maker;
|
||||||
item->next = list;
|
item->next = list;
|
||||||
item->type = type;
|
item->type = strdup(type);
|
||||||
item->name = name;
|
item->name = strdup(name);
|
||||||
|
item->desc = strdup(desc);
|
||||||
item->startupOnly = startupOnly;
|
item->startupOnly = startupOnly;
|
||||||
list = item;
|
list = item;
|
||||||
}
|
}
|
||||||
@ -84,6 +87,40 @@ static int MakeObject(SConnection *con, SicsInterp *sics,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int DriverList(SConnection *con, SicsInterp *sics,
|
||||||
|
void *data, int argc, char *argv[]) {
|
||||||
|
Item *p;
|
||||||
|
char *name, *type;
|
||||||
|
|
||||||
|
if (argc < 2 || strcasecmp(argv[1], "list") == 0) {
|
||||||
|
for (p = list; p != NULL; p = p->next) {
|
||||||
|
if (argc < 3) {
|
||||||
|
SCPrintf(con, eStatus, "%s %s %s", p->type, p->name, p->desc);
|
||||||
|
} else if (strcasecmp(argv[2], p->type) == 0) {
|
||||||
|
SCPrintf(con, eStatus, "%s %s", p->name, p->desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (argc == 2) {
|
||||||
|
name = argv[1];
|
||||||
|
type = "Object";
|
||||||
|
} else {
|
||||||
|
name = argv[2];
|
||||||
|
type = argv[1];
|
||||||
|
}
|
||||||
|
p = list;
|
||||||
|
while (p != NULL && (strcasecmp(p->type, type) != 0 || strcasecmp(p->name, name) != 0)) {
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
if (p) {
|
||||||
|
SCPrintf(con, eValue, "%s", p->desc);
|
||||||
|
} else {
|
||||||
|
SCPrintf(con, eValue, "notfound");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int RemoveObject(SConnection *con, SicsInterp *sics,
|
static int RemoveObject(SConnection *con, SicsInterp *sics,
|
||||||
void *data, int argc, char *argv[]) {
|
void *data, int argc, char *argv[]) {
|
||||||
CmdInitializer cmdin;
|
CmdInitializer cmdin;
|
||||||
@ -91,7 +128,7 @@ static int RemoveObject(SConnection *con, SicsInterp *sics,
|
|||||||
char *className;
|
char *className;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
SCPrintf(con, eError, "%s has 1 argument", argv[0]);
|
SCPrintf(con, eError, "%s needs 1 argument", argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,16 +161,20 @@ static void KillInitializers(void *data) {
|
|||||||
item = list;
|
item = list;
|
||||||
while (item) {
|
while (item) {
|
||||||
next = item->next;
|
next = item->next;
|
||||||
|
if (item->name) free(item->name);
|
||||||
|
if (item->type) free(item->type);
|
||||||
|
if (item->desc) free(item->desc);
|
||||||
free(item);
|
free(item);
|
||||||
item = next;
|
item = next;
|
||||||
}
|
}
|
||||||
list = NULL;
|
list = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MakeDriver(const char *driver, CmdInitializer maker, int startupOnly) {
|
void MakeDriver(const char *driver, CmdInitializer maker, int startupOnly, const char *desc) {
|
||||||
if (! FindCommand(pServ->pSics, "MakeObject")) {
|
if (! FindCommand(pServ->pSics, "MakeObject")) {
|
||||||
AddCommandWithFlag(pServ->pSics, "MakeObject", MakeObject, KillInitializers, NULL, 0);
|
AddCommandWithFlag(pServ->pSics, "MakeObject", MakeObject, KillInitializers, NULL, 0);
|
||||||
AddCommandWithFlag(pServ->pSics, "RemoveObject", RemoveObject, NULL, NULL, 0);
|
AddCommandWithFlag(pServ->pSics, "RemoveObject", RemoveObject, NULL, NULL, 0);
|
||||||
|
AddCommandWithFlag(pServ->pSics, "DriverList", DriverList, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
MakeInitializer("Object", driver, (Initializer)maker, startupOnly);
|
MakeInitializer("Object", driver, (Initializer)maker, startupOnly, desc);
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,8 @@ Markus Zolliker, March 2005
|
|||||||
|
|
||||||
typedef void (*Initializer)(void);
|
typedef void (*Initializer)(void);
|
||||||
|
|
||||||
void MakeInitializer(const char *type, const char *name, Initializer maker, int startupOnly);
|
void MakeInitializer(const char *type, const char *name, Initializer maker, int startupOnly,
|
||||||
|
const char *desc);
|
||||||
/*
|
/*
|
||||||
install an initializer
|
install an initializer
|
||||||
|
|
||||||
@ -54,7 +55,8 @@ typedef int (*CmdInitializer) (SConnection *pCon, int argc, char *argv[], int dy
|
|||||||
- dynamic: the initializer was called _after_ startup
|
- dynamic: the initializer was called _after_ startup
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void MakeDriver(const char *driver, CmdInitializer maker, int startupOnly);
|
void MakeDriver(const char *driver, CmdInitializer maker, int startupOnly,
|
||||||
|
const char *desc);
|
||||||
/*
|
/*
|
||||||
Install a driver of type "Object" with the initializer function maker.
|
Install a driver of type "Object" with the initializer function maker.
|
||||||
- startupOnly: the driver creation should only be possible at startup
|
- startupOnly: the driver creation should only be possible at startup
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
/*-------------------------- conversion routines -------------------------*/
|
/*-------------------------- conversion routines -------------------------*/
|
||||||
static float ang2x(pLin2Ang self, float fAngle)
|
static float ang2x(pLin2Ang self, float fAngle)
|
||||||
{
|
{
|
||||||
return self->length*sin((fAngle+self->zero)/RD);
|
return self->length*tan((fAngle+self->zero)/RD);
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
static float x2ang(pLin2Ang self, float fX)
|
static float x2ang(pLin2Ang self, float fX)
|
||||||
@ -44,7 +44,7 @@
|
|||||||
assert(self->length > 0.);
|
assert(self->length > 0.);
|
||||||
|
|
||||||
dt = fX/self->length;
|
dt = fX/self->length;
|
||||||
return RD*asin(dt) - self->zero;
|
return RD*atan(dt) - self->zero;
|
||||||
}
|
}
|
||||||
/*============== functions in the interface ============================*/
|
/*============== functions in the interface ============================*/
|
||||||
static void *Lin2AngGetInterface(void *pData, int iID)
|
static void *Lin2AngGetInterface(void *pData, int iID)
|
||||||
|
@ -9,4 +9,4 @@
|
|||||||
|
|
||||||
MFLAGS=-f makefile_linux$(DUMMY)
|
MFLAGS=-f makefile_linux$(DUMMY)
|
||||||
|
|
||||||
HDFROOT=/afs/psi.ch/project/sinq/sl-linux
|
HDFROOT=/usr/local
|
||||||
|
132
macro.c
132
macro.c
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
All you need to evaluate macros with SICS
|
All you need to evaluate macros with SICS
|
||||||
|
|
||||||
The implmentation for the macro stuff is complex and non intuitive.
|
The implementation for the macro stuff is complex and non intuitive.
|
||||||
This is the price to pay for adding the extremly powerful and
|
This is the price to pay for adding the extremly powerful and
|
||||||
strong Tcl-interpreter to SICS. The problem is that Tcl does not
|
strong Tcl-interpreter to SICS. The problem is that Tcl does not
|
||||||
know anything about connections and our error handling. We have
|
know anything about connections and our error handling. We have
|
||||||
@ -770,6 +770,127 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
int GumPut(SConnection *pCon, SicsInterp *pInter, void *pData,
|
||||||
|
int argc, char *argv[])
|
||||||
|
{
|
||||||
|
OutCode eOut = eWarning;
|
||||||
|
int i = 0, iCode, iLen;
|
||||||
|
int iMacro;
|
||||||
|
char *ppCode;
|
||||||
|
char *pMessage = NULL;
|
||||||
|
commandContext cc;
|
||||||
|
|
||||||
|
assert(pCon);
|
||||||
|
assert(pInter);
|
||||||
|
|
||||||
|
if(argc < 2)
|
||||||
|
{
|
||||||
|
SCWrite(pCon,"Insufficient arguments to ClientPut",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* handle optional I/O codes */
|
||||||
|
if(argc > 2)
|
||||||
|
{
|
||||||
|
/* the last one must be the code */
|
||||||
|
iCode = argc - 1;
|
||||||
|
ppCode = strdup(argv[iCode]);
|
||||||
|
strtolower(ppCode);
|
||||||
|
while(pCode[i] != NULL)
|
||||||
|
{
|
||||||
|
if(strcmp(pCode[i],ppCode) == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if(ppCode)
|
||||||
|
{
|
||||||
|
free(ppCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = 10;
|
||||||
|
iCode = argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(i)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
eOut = eInternal;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
eOut = eCommand;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
eOut = eHWError;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
eOut = eInError;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
eOut = eStatus;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
eOut = eValue;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
eOut = eWarning;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
eOut = eFinish;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
eOut = eEvent;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
eOut = eWarning;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
eOut = eError;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
eOut = eWarning;
|
||||||
|
iCode = argc;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* recombine the message */
|
||||||
|
/* find length */
|
||||||
|
iLen = 0;
|
||||||
|
for(i = 1; i < iCode; i++)
|
||||||
|
{
|
||||||
|
iLen += strlen(argv[i]);
|
||||||
|
}
|
||||||
|
pMessage = (char *)malloc((iLen+100)*sizeof(char));
|
||||||
|
if(!pMessage)
|
||||||
|
{
|
||||||
|
SCWrite(pCon,"ERROR: out of memory in clientput",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memset(pMessage,0,(iLen+100)*sizeof(char));
|
||||||
|
Arg2Text(iCode-1,&argv[1],pMessage,(iLen+100)*sizeof(char));
|
||||||
|
|
||||||
|
/* now write, thereby tunneling macro flag in order to get proper
|
||||||
|
write to client and not into interpreter. We also make sure that the device
|
||||||
|
is gumput
|
||||||
|
*/
|
||||||
|
iMacro = SCinMacro(pCon);
|
||||||
|
SCsetMacro(pCon,0);
|
||||||
|
cc = SCGetContext(pCon);
|
||||||
|
strcpy(cc.deviceID,"gumput");
|
||||||
|
SCPushContext2(pCon,cc);
|
||||||
|
SCWrite(pCon,pMessage,eOut);
|
||||||
|
SCPopContext(pCon);
|
||||||
|
SCsetMacro(pCon,iMacro);
|
||||||
|
if(pMessage)
|
||||||
|
{
|
||||||
|
free(pMessage);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
int Broadcast(SConnection *pCon, SicsInterp *pInter, void *pData,
|
int Broadcast(SConnection *pCon, SicsInterp *pInter, void *pData,
|
||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
@ -891,14 +1012,9 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
|||||||
if (pCommand != pBueffel) free(pCommand);
|
if (pCommand != pBueffel) free(pCommand);
|
||||||
if(iRet == TCL_OK)
|
if(iRet == TCL_OK)
|
||||||
{
|
{
|
||||||
/* we do not now why, but at some time it was found that
|
if(strlen(pTcl->result) > 0){
|
||||||
we need a copy, and can not use pTcl->result directly
|
|
||||||
|
|
||||||
SCWrite(pCon,pTcl->result,eStatus);
|
|
||||||
|
|
||||||
let us use SCPrintf, which maked always a copy
|
|
||||||
*/
|
|
||||||
SCPrintf(pCon, eStatus, "%s", pTcl->result);
|
SCPrintf(pCon, eStatus, "%s", pTcl->result);
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
3
macro.h
3
macro.h
@ -14,6 +14,7 @@
|
|||||||
#ifndef SICSMACRO
|
#ifndef SICSMACRO
|
||||||
#define SICSMACRO
|
#define SICSMACRO
|
||||||
#include <tcl.h>
|
#include <tcl.h>
|
||||||
|
#include "sics.h"
|
||||||
#include "SCinter.h"
|
#include "SCinter.h"
|
||||||
|
|
||||||
Tcl_Interp *MacroInit(SicsInterp *pInter);
|
Tcl_Interp *MacroInit(SicsInterp *pInter);
|
||||||
@ -30,6 +31,8 @@
|
|||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
int ClientPut(SConnection *pCon, SicsInterp *pInter, void *pData,
|
int ClientPut(SConnection *pCon, SicsInterp *pInter, void *pData,
|
||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
|
int GumPut(SConnection *pCon, SicsInterp *pInter, void *pData,
|
||||||
|
int argc, char *argv[]);
|
||||||
int Broadcast(SConnection *pCon, SicsInterp *pInter, void *pData,
|
int Broadcast(SConnection *pCon, SicsInterp *pInter, void *pData,
|
||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
int TransactAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
int TransactAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
12
make_gen
12
make_gen
@ -30,14 +30,22 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
|||||||
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) mcreader.o mccontrol.o\
|
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) mcreader.o mccontrol.o\
|
||||||
hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \
|
hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \
|
||||||
mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \
|
mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \
|
||||||
sinfox.o sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.o
|
sinfox.o sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.o \
|
||||||
|
moregress.o hdbcommand.o multicounter.o regresscter.o histregress.o \
|
||||||
|
sicshdbadapter.o polldriv.o sicspoll.o statemon.o
|
||||||
|
|
||||||
MOTOROBJ = motor.o simdriv.o
|
MOTOROBJ = motor.o simdriv.o
|
||||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||||
VELOOBJ = velo.o velosim.o
|
VELOOBJ = velo.o velosim.o
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.SUFFIXES: .tcl .htm .c .o
|
.SUFFIXES: .tcl .htm .c .o .tc
|
||||||
|
|
||||||
|
.tc.c:
|
||||||
|
tjxp $*.tc $*.c
|
||||||
|
|
||||||
|
#--- 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 libtecsl libpsi SICServer
|
||||||
|
|
||||||
|
@ -6,11 +6,11 @@
|
|||||||
# Markus Zolliker, March 2003
|
# Markus Zolliker, March 2003
|
||||||
#==========================================================================
|
#==========================================================================
|
||||||
# assign if the National Instrument GPIB driver is available
|
# assign if the National Instrument GPIB driver is available
|
||||||
SINQDIR=/afs/psi.ch/project/sinq
|
SINQDIR=/usr/local
|
||||||
NI=
|
#NI=
|
||||||
#NI= -DHAVENI
|
NI= -DHAVENI
|
||||||
#NIOBJ= nigpib.o
|
NIOBJ= nigpib.o
|
||||||
#NILIB=$(SINQDIR)/linux/lib/cib.o
|
NILIB=$(SINQDIR)/lib/cib.o
|
||||||
|
|
||||||
include linux_def
|
include linux_def
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \
|
|||||||
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\
|
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\
|
||||||
-ltcl8.4 -lmxml $(HDFROOT)/lib/libhdf5.a \
|
-ltcl8.4 -lmxml $(HDFROOT)/lib/libhdf5.a \
|
||||||
$(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \
|
$(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \
|
||||||
-ljpeg -ldl -lz -lm -lc
|
-lmxml -lghttp -ljpeg -ljson -ldl -lz -lsz -lm -lc
|
||||||
|
|
||||||
include make_gen
|
include make_gen
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \
|
|||||||
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\
|
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\
|
||||||
-ltcl8.3 $(HDFROOT)/lib/libhdf5.a \
|
-ltcl8.3 $(HDFROOT)/lib/libhdf5.a \
|
||||||
$(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \
|
$(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \
|
||||||
$(HDFROOT)/lib/libjpeg.a -lsz -ldl -lz -lmxml -lghttp -lm -lc
|
$(HDFROOT)/lib/libjpeg.a -lsz -ljson -ldl -lz -lmxml -lghttp -lm -lc
|
||||||
|
|
||||||
include make_gen
|
include make_gen
|
||||||
|
|
||||||
|
102
maximize.c
102
maximize.c
@ -47,6 +47,7 @@
|
|||||||
#include "counter.h"
|
#include "counter.h"
|
||||||
#include "drive.h"
|
#include "drive.h"
|
||||||
#include "maximize.h"
|
#include "maximize.h"
|
||||||
|
#include "motor.h"
|
||||||
|
|
||||||
#define MAXPTS 100
|
#define MAXPTS 100
|
||||||
#define DEBUG 1
|
#define DEBUG 1
|
||||||
@ -55,6 +56,7 @@
|
|||||||
pObjectDescriptor pDes;
|
pObjectDescriptor pDes;
|
||||||
pCounter pCount;
|
pCounter pCount;
|
||||||
int i360;
|
int i360;
|
||||||
|
int maxpts;
|
||||||
}Maxxii;
|
}Maxxii;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------
|
/*-----------------------------------------------------------------------
|
||||||
@ -134,7 +136,25 @@
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
static float readMPDrivable(void *pVar, SConnection *pCon)
|
||||||
|
{
|
||||||
|
float value = -999.99;
|
||||||
|
pIDrivable pDriv = NULL;
|
||||||
|
pDummy pDum = (pDummy)pVar;
|
||||||
|
|
||||||
|
pDriv = GetDrivableInterface(pVar);
|
||||||
|
assert(pDriv != NULL);
|
||||||
|
if(strcmp(pDum->pDescriptor->name,"Motor") == 0)
|
||||||
|
{
|
||||||
|
MotorGetSoftPosition((pMotor)pVar,pCon,&value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = pDriv->GetValue(pVar,pCon);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
int MaximizePeak(pMax self, void *pVar, char *pVarName,
|
int MaximizePeak(pMax self, void *pVar, char *pVarName,
|
||||||
float fStep, CounterMode eMode,
|
float fStep, CounterMode eMode,
|
||||||
@ -159,7 +179,7 @@
|
|||||||
start:
|
start:
|
||||||
lMax = 0;
|
lMax = 0;
|
||||||
lMin = 0x7fffffff;
|
lMin = 0x7fffffff;
|
||||||
fStart = pDriv->GetValue(pVar,pCon);
|
fStart = readMPDrivable(pVar,pCon);
|
||||||
if(fStart < -999999.)
|
if(fStart < -999999.)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -167,16 +187,16 @@
|
|||||||
|
|
||||||
/* search to the left until out of space or lCts < lMax/2. */
|
/* search to the left until out of space or lCts < lMax/2. */
|
||||||
SCWrite(pCon,"Searching for low angle boundary..",eWarning);
|
SCWrite(pCon,"Searching for low angle boundary..",eWarning);
|
||||||
for(i = MAXPTS/2; i >= 0; i--)
|
for(i = self->maxpts/2; i >= 0; i--)
|
||||||
{
|
{
|
||||||
/* drive motor */
|
/* drive motor */
|
||||||
fPos = fStart - (MAXPTS/2 - i)*fStep;
|
fPos = fStart - (self->maxpts/2 - i)*fStep;
|
||||||
fPos = in360(self,fPos);
|
fPos = in360(self,fPos);
|
||||||
if(maxDrive(pVar,pVarName,fPos,pCon) != 1)
|
if(maxDrive(pVar,pVarName,fPos,pCon) != 1)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
x[i] = pDriv->GetValue(pVar,pCon);
|
x[i] = readMPDrivable(pVar,pCon);
|
||||||
/* count */
|
/* count */
|
||||||
if(maxCount(self->pCount,eMode,fPreset, &lCts,pCon) != 1)
|
if(maxCount(self->pCount,eMode,fPreset, &lCts,pCon) != 1)
|
||||||
{
|
{
|
||||||
@ -218,7 +238,7 @@
|
|||||||
goto start;
|
goto start;
|
||||||
}
|
}
|
||||||
/* no peak found or normal peak: continue at other side */
|
/* no peak found or normal peak: continue at other side */
|
||||||
if( (i < 1) || (y[MAXPTS/2] > lMax/2) )
|
if( (i < 1) || (y[self->maxpts/2] > lMax/2) )
|
||||||
{
|
{
|
||||||
iSkip = 0;
|
iSkip = 0;
|
||||||
}
|
}
|
||||||
@ -227,7 +247,7 @@
|
|||||||
/* next case: all of the peak in measured half:
|
/* next case: all of the peak in measured half:
|
||||||
find max value and skip the right half
|
find max value and skip the right half
|
||||||
*/
|
*/
|
||||||
for(i = MAXPTS/2; i > 0; i--)
|
for(i = self->maxpts/2; i > 0; i--)
|
||||||
{
|
{
|
||||||
if(y[i] > lMax/2)
|
if(y[i] > lMax/2)
|
||||||
{
|
{
|
||||||
@ -246,16 +266,16 @@
|
|||||||
lMin = 100000;
|
lMin = 100000;
|
||||||
lMax = -100000;
|
lMax = -100000;
|
||||||
SCWrite(pCon,"Searching for high angle boundary..",eWarning);
|
SCWrite(pCon,"Searching for high angle boundary..",eWarning);
|
||||||
for(i = MAXPTS/2; i < MAXPTS; i++)
|
for(i = self->maxpts/2; i < self->maxpts; i++)
|
||||||
{
|
{
|
||||||
/* drive motor */
|
/* drive motor */
|
||||||
fPos = fStart + (i - MAXPTS/2) * fStep;
|
fPos = fStart + (i - self->maxpts/2) * fStep;
|
||||||
fPos = in360(self,fPos);
|
fPos = in360(self,fPos);
|
||||||
if(maxDrive(pVar,pVarName,fPos,pCon) != 1)
|
if(maxDrive(pVar,pVarName,fPos,pCon) != 1)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
x[i] = pDriv->GetValue(pVar,pCon);
|
x[i] = readMPDrivable(pVar,pCon);
|
||||||
/* count */
|
/* count */
|
||||||
if(maxCount(self->pCount,eMode,fPreset, &lCts,pCon) != 1)
|
if(maxCount(self->pCount,eMode,fPreset, &lCts,pCon) != 1)
|
||||||
{
|
{
|
||||||
@ -292,18 +312,18 @@
|
|||||||
iTop = i;
|
iTop = i;
|
||||||
iTop++;
|
iTop++;
|
||||||
/* first case: peak is at high angle side */
|
/* first case: peak is at high angle side */
|
||||||
if( (i > MAXPTS-2) && (lMax*0.5 > lMin) )
|
if( (i > self->maxpts-2) && (lMax*0.5 > lMin) )
|
||||||
{
|
{
|
||||||
goto start;
|
goto start;
|
||||||
}
|
}
|
||||||
/* second case: no peak */
|
/* second case: no peak */
|
||||||
if( (iTop > MAXPTS-2) )
|
if( (iTop > self->maxpts-2) )
|
||||||
{
|
{
|
||||||
SCWrite(pCon,"ERROR: no peak found!",eError);
|
SCWrite(pCon,"ERROR: no peak found!",eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* third case: normal peak */
|
/* third case: normal peak */
|
||||||
if(y[MAXPTS/2] >= 0.5*lMax)
|
if(y[self->maxpts/2] >= 0.5*lMax)
|
||||||
{
|
{
|
||||||
iTop--;
|
iTop--;
|
||||||
}
|
}
|
||||||
@ -313,7 +333,7 @@
|
|||||||
*/
|
*/
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for(i = MAXPTS/2; i < MAXPTS; i++)
|
for(i = self->maxpts/2; i < self->maxpts; i++)
|
||||||
{
|
{
|
||||||
if(y[i] > lMax/2)
|
if(y[i] > lMax/2)
|
||||||
{
|
{
|
||||||
@ -325,7 +345,7 @@
|
|||||||
}
|
}
|
||||||
} /* end of iSkip */
|
} /* end of iSkip */
|
||||||
|
|
||||||
if( (iBot < 2) || (iTop > MAXPTS-2) || (lMax < lMin*2) )
|
if( (iBot < 2) || (iTop > self->maxpts-2) || (lMax < lMin*2) )
|
||||||
{
|
{
|
||||||
SCWrite(pCon,"ERROR: no peak found!",eError);
|
SCWrite(pCon,"ERROR: no peak found!",eError);
|
||||||
return 0;
|
return 0;
|
||||||
@ -420,11 +440,14 @@
|
|||||||
pNew->pDes = CreateDescriptor("Maximizer");
|
pNew->pDes = CreateDescriptor("Maximizer");
|
||||||
pNew->pCount = pCom->pData;
|
pNew->pCount = pCom->pData;
|
||||||
pNew->i360 = 0;
|
pNew->i360 = 0;
|
||||||
|
pNew->maxpts = 100;
|
||||||
|
|
||||||
AddCommand(pSics,"max",MaximizeAction,MaxKill,pNew);
|
AddCommand(pSics,"max",MaximizeAction,MaxKill,pNew);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*------------------------------------------------------------------*/
|
/*------------------------------------------------------------------
|
||||||
|
* max motor step preset mode
|
||||||
|
* ---------------------------------------------------------------------*/
|
||||||
int MaximizeAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
int MaximizeAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -434,7 +457,7 @@
|
|||||||
double dVal;
|
double dVal;
|
||||||
float fStep, fPreset;
|
float fStep, fPreset;
|
||||||
CounterMode eCount;
|
CounterMode eCount;
|
||||||
int iRet;
|
int iRet, iVal;
|
||||||
|
|
||||||
self = (pMax)pData;
|
self = (pMax)pData;
|
||||||
assert(self);
|
assert(self);
|
||||||
@ -446,9 +469,56 @@
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* enough arguments ?*/
|
/* enough arguments ?*/
|
||||||
if(argc < 5)
|
if(argc < 5)
|
||||||
{
|
{
|
||||||
|
if(argc > 1)
|
||||||
|
{
|
||||||
|
strtolower(argv[1]);
|
||||||
|
if(strcmp(argv[1],"in360") == 0)
|
||||||
|
{
|
||||||
|
if(argc > 2)
|
||||||
|
{
|
||||||
|
iVal = atoi(argv[2]);
|
||||||
|
if(iVal != 0 && iVal != 1) {
|
||||||
|
SCWrite(pCon,"ERROR: only 0, 1 allowed for in360",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->i360 = iVal;
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(pBueffel,255,"max.in360 = %d", self->i360);
|
||||||
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(strcmp(argv[1],"maxpts") == 0)
|
||||||
|
{
|
||||||
|
if(argc > 2)
|
||||||
|
{
|
||||||
|
iVal = atoi(argv[2]);
|
||||||
|
if(iVal < 10 || iVal > 100) {
|
||||||
|
SCWrite(pCon,"ERROR: maxpst must be between 10 and 100",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->maxpts = iVal;
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(pBueffel,255,"max.maxpts = %d", self->maxpts);
|
||||||
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
SCWrite(pCon,"ERROR: Insufficient number of arguments to max",
|
SCWrite(pCon,"ERROR: Insufficient number of arguments to max",
|
||||||
eError);
|
eError);
|
||||||
return 0;
|
return 0;
|
||||||
|
36
mcstas/dmc/README
Normal file
36
mcstas/dmc/README
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
VIRTUAL DMC
|
||||||
|
|
||||||
|
This is the SICS-McStas virtual instrument DMC modelled after the real
|
||||||
|
powder diffcractometer DMC at SINQ:
|
||||||
|
|
||||||
|
http://sinq.web.psi.ch/sinq/instr/dmc/dmc.html
|
||||||
|
|
||||||
|
The McStas simulation used for this system has been verified against
|
||||||
|
the real instrument. The basic usage is to start the SICServer with:
|
||||||
|
|
||||||
|
./SICServer vdmc.tcl
|
||||||
|
|
||||||
|
in this directory. Then you can connect to SICS at localhost/2911
|
||||||
|
with any SICS client and start issuing commands.
|
||||||
|
|
||||||
|
In order to save simulation time, the simulation works with
|
||||||
|
neutron data files presimulated for four wavelength up to the sample.
|
||||||
|
This is why you get your wavelength coerced to the nearest
|
||||||
|
precalculated value.
|
||||||
|
|
||||||
|
If you desire to "measure" your own sample on virtual DMC, you first
|
||||||
|
have to create a LazyPulverix output file. You then can proceed to
|
||||||
|
load the sample into SICS with the SICS command:
|
||||||
|
|
||||||
|
sample load path-to-lazy-pulverix-outputfile
|
||||||
|
|
||||||
|
The command:
|
||||||
|
|
||||||
|
sample list
|
||||||
|
|
||||||
|
tells you which samples virtual DMC already knows about.
|
||||||
|
|
||||||
|
Questions and comments to: Mark.Koennecke@psi.ch
|
||||||
|
|
||||||
|
|
8454
mcstas/dmc/dmcafter.c
Normal file
8454
mcstas/dmc/dmcafter.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@
|
|||||||
# This is the scripted version using nxscript
|
# This is the scripted version using nxscript
|
||||||
#
|
#
|
||||||
# Mark Koennecke, May 2004
|
# Mark Koennecke, May 2004
|
||||||
|
# This is a special version for virtual DMC on lns00
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
proc storeMonochromator {} {
|
proc storeMonochromator {} {
|
||||||
@ -75,14 +76,34 @@ proc makeLinks {} {
|
|||||||
nxscript makelink dana dtnstep
|
nxscript makelink dana dtnstep
|
||||||
nxscript makelink dana mlambda
|
nxscript makelink dana mlambda
|
||||||
}
|
}
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
proc makeSimFileName args {
|
||||||
|
global datahome
|
||||||
|
sicsdatanumber incr
|
||||||
|
set num [SplitReply [sicsdatanumber]]
|
||||||
|
return [makeSimForNum $num]
|
||||||
|
}
|
||||||
|
#------------------------------------------------------------------------
|
||||||
|
proc makeSimForNum {num} {
|
||||||
|
global datahome
|
||||||
|
set pre [string trim [SplitReply [sicsdataprefix]]]
|
||||||
|
set po [string trim [SplitReply [sicsdatapostfix]]]
|
||||||
|
return [format "%s/%s2006n%6.6d%s" $datahome $pre $num $po]
|
||||||
|
}
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# store DMC data
|
# store DMC data
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
proc storedata {} {
|
proc storedata {} {
|
||||||
global home
|
global home wwwMode
|
||||||
|
|
||||||
|
if {$wwwMode == 1} {
|
||||||
|
set fil [makeSimFileName]
|
||||||
|
} else {
|
||||||
set fil [newFileName]
|
set fil [newFileName]
|
||||||
|
}
|
||||||
|
lastdatafile $fil
|
||||||
clientput "Opening $fil for writing"
|
clientput "Opening $fil for writing"
|
||||||
nxscript create4 $fil $home/dmc.dic
|
nxscript createxml $fil $home/dmc.dic
|
||||||
|
|
||||||
writeStandardAttributes $fil
|
writeStandardAttributes $fil
|
||||||
writeTextVar etitle title
|
writeTextVar etitle title
|
||||||
|
@ -5,9 +5,15 @@
|
|||||||
# Dr. Mark Koennecke, June 2005
|
# Dr. Mark Koennecke, June 2005
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# O P T I O N S
|
# O P T I O N S
|
||||||
|
# wwwMode = 1 when running for the WWW-VDMC application
|
||||||
|
set wwwMode 0
|
||||||
|
|
||||||
set home $env(HOME)/src/workspace/sics/mcstas/dmc
|
if {$wwwMode == 1} {
|
||||||
|
set home /home/lnswww/vinstrument/mcstas/dmc
|
||||||
|
set datahome /home/lnswww/www/vinstrument
|
||||||
|
} else {
|
||||||
|
set home $env(HOME)/psi/workspace/sics/mcstas/dmc
|
||||||
|
}
|
||||||
#--------------------------------- first all the server options are set
|
#--------------------------------- first all the server options are set
|
||||||
#ServerOption RedirectFile $home/stdcdmc
|
#ServerOption RedirectFile $home/stdcdmc
|
||||||
ServerOption ReadTimeOut 10
|
ServerOption ReadTimeOut 10
|
||||||
@ -120,18 +126,20 @@ SicsDataPrefix vdmc
|
|||||||
#--------- make data number
|
#--------- make data number
|
||||||
MakeDataNumber SicsDataNumber $home/DataNumber
|
MakeDataNumber SicsDataNumber $home/DataNumber
|
||||||
VarMake SicsDataPostFix Text Internal
|
VarMake SicsDataPostFix Text Internal
|
||||||
SicsDataPostFix ".hdf"
|
SicsDataPostFix ".xml"
|
||||||
VarMake Adress Text User
|
VarMake Adress Text User
|
||||||
VarMake phone Text User
|
VarMake phone Text User
|
||||||
VarMake fax Text User
|
VarMake fax Text User
|
||||||
VarMake email Text User
|
VarMake email Text User
|
||||||
VarMake sample_mur Float User
|
VarMake sample_mur Float User
|
||||||
|
VarMake lastdatafile Text User
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
# P R O C E D U R E S
|
# P R O C E D U R E S
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
MakeDrive
|
MakeDrive
|
||||||
MakeBatchManager
|
MakeBatchManager
|
||||||
MakeNXScript
|
MakeNXScript
|
||||||
|
MakeRuenBuffer
|
||||||
#-------------------- initialize scripted commands
|
#-------------------- initialize scripted commands
|
||||||
source $home/vdmccom.tcl
|
source $home/vdmccom.tcl
|
||||||
#-------------------- configure commandlog
|
#-------------------- configure commandlog
|
||||||
@ -139,7 +147,6 @@ commandlog auto
|
|||||||
commandlog intervall 5
|
commandlog intervall 5
|
||||||
|
|
||||||
#----------- enable sycamore
|
#----------- enable sycamore
|
||||||
#InstallProtocolHandler
|
|
||||||
#InstallSinfox
|
#InstallSinfox
|
||||||
#source sycFormat.tcl
|
#source sycFormat.tcl
|
||||||
#source /usr/lib/tcllib1.6.1/stooop/stooop.tcl
|
#source /usr/lib/tcllib1.6.1/stooop/stooop.tcl
|
||||||
@ -147,3 +154,95 @@ commandlog intervall 5
|
|||||||
#source sinfo.tcl
|
#source sinfo.tcl
|
||||||
#source sycamore.tcl
|
#source sycamore.tcl
|
||||||
#Publish sinfo Spy
|
#Publish sinfo Spy
|
||||||
|
|
||||||
|
#==================== install Hipadaba
|
||||||
|
proc hdbReadOnly {} {
|
||||||
|
error "Parameter is READ ONLY"
|
||||||
|
}
|
||||||
|
#------------------------------------
|
||||||
|
proc maketwotheta {} {
|
||||||
|
set txt [TwoThetaD]
|
||||||
|
set l [split $txt =]
|
||||||
|
set start [string trim [lindex $l 1]]
|
||||||
|
for {set i 0} {$i < 400} {incr i } {
|
||||||
|
append result [expr $start + $i * .2] " "
|
||||||
|
}
|
||||||
|
return $result
|
||||||
|
}
|
||||||
|
#-------------------------------------
|
||||||
|
InstallProtocolHandler
|
||||||
|
InstallHdb
|
||||||
|
MakeStateMon
|
||||||
|
hmake /dmc spy none
|
||||||
|
hsetprop /dmc type instrument
|
||||||
|
#-------- experiment
|
||||||
|
hmake /dmc/experiment spy none
|
||||||
|
hattach /dmc/experiment title title
|
||||||
|
hattach /dmc/experiment user user
|
||||||
|
hattach /dmc/experiment starttime starttime
|
||||||
|
hattach /dmc/experiment user user
|
||||||
|
hattach /dmc/experiment/user adress address
|
||||||
|
hattach /dmc/experiment/user phone phone
|
||||||
|
hattach /dmc/experiment/user email email
|
||||||
|
hattach /dmc/experiment comment1 comment1
|
||||||
|
hattach /dmc/experiment comment2 comment2
|
||||||
|
hattach /dmc/experiment comment3 comment3
|
||||||
|
#------- SINQ
|
||||||
|
hmake /dmc/sinq spy none
|
||||||
|
hmakescript /dmc/sinq/proton_monitor "counter getmonitor 4" hdbReadOnly int
|
||||||
|
sicspoll /dmc/sinq/proton_monitor hdb 10
|
||||||
|
#-------- monochromator
|
||||||
|
hmake /dmc/monochromator spy none
|
||||||
|
hattach /dmc/monochromator lambda wavelength
|
||||||
|
hattach /dmc/monochromator OmegaM theta
|
||||||
|
hattach /dmc/monochromator TwoThetaM two_theta
|
||||||
|
hattach /dmc/monochromator MonoX x_translation
|
||||||
|
hattach /dmc/monochromator MonoY y_translation
|
||||||
|
hattach /dmc/monochromator MonoChi chi
|
||||||
|
hattach /dmc/monochromator MonoPhi phi
|
||||||
|
hattach /dmc/monochromator CurveM vertical_focusing
|
||||||
|
hmakescript /dmc/monochromator/d_value "mono dd" "mono dd" float
|
||||||
|
hsetprop /dmc/monochromator/d_value priv manager
|
||||||
|
hmakescript /dmc/monochromator/scattering_sense "mono ss" "mono ss" int
|
||||||
|
hsetprop /dmc/monochromator/scattering_sense priv manager
|
||||||
|
|
||||||
|
#----------- sample
|
||||||
|
hmake /dmc/sample spy none
|
||||||
|
hmakescript /dmc/sample/name sample sample Text
|
||||||
|
hattach /dmc/sample Table rotation
|
||||||
|
hmakescript /dmc/sample/monitor "counter getmonitor 1" hdbReadOnly int
|
||||||
|
hsetprop /dmc/sample/monitor priv internal
|
||||||
|
#---------- detector
|
||||||
|
hmake /dmc/detector spy none
|
||||||
|
hattach /dmc/detector TwoThetaD two_theta
|
||||||
|
hmakescript /dmc/detector/preset "counter getpreset" hdbReadOnly float
|
||||||
|
hsetprop /dmc/detector/preset priv internal
|
||||||
|
hmakescript /dmc/detector/countmode "counter getmode" hdbReadOnly text
|
||||||
|
hsetprop /dmc/detector/countmode priv internal
|
||||||
|
sicspoll add /dmc/detector/preset hdb 30
|
||||||
|
sicspoll add /dmc/detector/countmode hdb 30
|
||||||
|
#------------ commands
|
||||||
|
hmake /commands spy none
|
||||||
|
hcommand /commands/count count
|
||||||
|
hsetprop /commands/count type command
|
||||||
|
hmake /commands/count/mode user text
|
||||||
|
hmake /commands/count/preset user float
|
||||||
|
hset /commands/count/preset 5
|
||||||
|
hset /commands/count/mode timer
|
||||||
|
#---------------- graphics
|
||||||
|
hmake /Graphics spy none
|
||||||
|
hmake /Graphics/powder_diagram spy none
|
||||||
|
hsetprop /Graphics/powder_diagram type graphdata
|
||||||
|
hsetprop /Graphics/powder_diagram viewer default
|
||||||
|
hmake /Graphics/powder_diagram/rank internal int
|
||||||
|
hset /Graphics/powder_diagram/rank 1
|
||||||
|
hmake /Graphics/powder_diagram/dim internal intar 1
|
||||||
|
hset /Graphics/powder_diagram/dim 400
|
||||||
|
hmakescript /Graphics/powder_diagram/two_theta maketwotheta hdbReadOnly floatar 400
|
||||||
|
sicspoll add /Graphics/powder_diagram/two_theta hdb 30
|
||||||
|
hsetprop /Graphics/powder_diagram/two_theta type axis
|
||||||
|
hsetprop /Graphics/powder_diagram/two_theta dim 0
|
||||||
|
hattach /Graphics/powder_diagram banana counts
|
||||||
|
hsetprop /Graphics/powder_diagram/counts type data
|
||||||
|
hsetprop /Graphics/powder_diagram/counts priv internal
|
||||||
|
sicspoll add /Graphics/powder_diagram/counts hdb 60
|
||||||
|
@ -15,7 +15,9 @@ if { [info exists vdmcinit] == 0 } {
|
|||||||
Publish copydmcdata User
|
Publish copydmcdata User
|
||||||
Publish sample User
|
Publish sample User
|
||||||
Publish wwwsics Spy
|
Publish wwwsics Spy
|
||||||
|
Publish wwwfilefornumber Spy
|
||||||
mcinstall
|
mcinstall
|
||||||
|
Publish gethm Spy
|
||||||
}
|
}
|
||||||
source $home/log.tcl
|
source $home/log.tcl
|
||||||
source $home/nxsupport.tcl
|
source $home/nxsupport.tcl
|
||||||
@ -38,12 +40,19 @@ proc washlazy {name} {
|
|||||||
if { [string first "H K L THETA 2THETA D VALUE" $line] > 0} {
|
if { [string first "H K L THETA 2THETA D VALUE" $line] > 0} {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
#-------- A second version to treat the messed up lazy pulverix files
|
||||||
|
# uploaded through the WWW-interface
|
||||||
|
if { [string first "H K L THETA" $line] >= 0} {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#------- process data lines
|
#------- process data lines
|
||||||
puts $out "// mult Q(hkl) F2 DW w"
|
puts $out "// mult Q(hkl) F2 DW w"
|
||||||
|
clientput "HKL found at: $line"
|
||||||
while { [gets $in line] >= 0} {
|
while { [gets $in line] >= 0} {
|
||||||
set num [scan $line "%d %d %d %f %f %f %f %f %d %d %d %f %f %f %f %f %d"\
|
set num [scan $line "%d %d %d %f %f %f %f %f %d %d %d %f %f %f %f %f %d"\
|
||||||
h k l th th2 d di sin h2 k2 l2 I F A B ang mul]
|
h k l th th2 d di sin h2 k2 l2 I F A B ang mul]
|
||||||
|
clientput "Line = $num, $line"
|
||||||
if { $num == 17} {
|
if { $num == 17} {
|
||||||
set q [expr (2.*3.14159265358979323846)/$d]
|
set q [expr (2.*3.14159265358979323846)/$d]
|
||||||
set f2 [expr $F * $F]
|
set f2 [expr $F * $F]
|
||||||
@ -155,6 +164,7 @@ proc rundmcoptsim {mode preset } {
|
|||||||
} else {
|
} else {
|
||||||
return $msg
|
return $msg
|
||||||
}
|
}
|
||||||
|
wait 5
|
||||||
}
|
}
|
||||||
#------------------------------------------------------------------------
|
#------------------------------------------------------------------------
|
||||||
proc copydmcdataold { } {
|
proc copydmcdataold { } {
|
||||||
@ -363,7 +373,7 @@ proc wwwpar {type mot} {
|
|||||||
}
|
}
|
||||||
#------------- wwwuser formats user information into a html table
|
#------------- wwwuser formats user information into a html table
|
||||||
proc wwwuser {} {
|
proc wwwuser {} {
|
||||||
lappend list title sample user email phone adress
|
lappend list title user email phone adress
|
||||||
append txt "<table>"
|
append txt "<table>"
|
||||||
foreach e $list {
|
foreach e $list {
|
||||||
set ret [catch {$e} msg]
|
set ret [catch {$e} msg]
|
||||||
@ -376,6 +386,14 @@ proc wwwuser {} {
|
|||||||
}
|
}
|
||||||
return $txt
|
return $txt
|
||||||
}
|
}
|
||||||
|
#------------- wwwfilefornumber returns the path to a data file for a
|
||||||
|
# number
|
||||||
|
proc wwwfilefornumber {num} {
|
||||||
|
return [makeSimForNum $num]
|
||||||
|
}
|
||||||
|
#-------------------------------------------------------------------
|
||||||
|
proc gethm {} {
|
||||||
|
banana uuget 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
62
mesure.c
62
mesure.c
@ -33,6 +33,7 @@
|
|||||||
#include "fourtable.h"
|
#include "fourtable.h"
|
||||||
#include "lld.h"
|
#include "lld.h"
|
||||||
#include "stdscan.h"
|
#include "stdscan.h"
|
||||||
|
#include "exeman.h"
|
||||||
|
|
||||||
extern void SNXFormatTime(char *pBueffel, int iLen);
|
extern void SNXFormatTime(char *pBueffel, int iLen);
|
||||||
extern float nintf(float f);
|
extern float nintf(float f);
|
||||||
@ -445,7 +446,9 @@ static int MesureCalculateSettings(pMesure self, float fHKL[3], float fSet[4],
|
|||||||
float fPsi, SConnection *pCon)
|
float fPsi, SConnection *pCon)
|
||||||
{
|
{
|
||||||
int status, np;
|
int status, np;
|
||||||
float step, tolerance;
|
float step, tolerance, fHard;
|
||||||
|
char *scanvar = NULL;
|
||||||
|
char buffer[256];
|
||||||
|
|
||||||
SetHKLScanTolerance(self->pCryst,.0);
|
SetHKLScanTolerance(self->pCryst,.0);
|
||||||
status = CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon);
|
status = CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon);
|
||||||
@ -460,7 +463,26 @@ static int MesureCalculateSettings(pMesure self, float fHKL[3], float fSet[4],
|
|||||||
np = getMesureNP(self,(double)fSet[0]);
|
np = getMesureNP(self,(double)fSet[0]);
|
||||||
tolerance = (step * (float)np)/2. + .2;
|
tolerance = (step * (float)np)/2. + .2;
|
||||||
SetHKLScanTolerance(self->pCryst,tolerance);
|
SetHKLScanTolerance(self->pCryst,tolerance);
|
||||||
return CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon);
|
status = CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon);
|
||||||
|
if(status != 1){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
scanvar = GetFourCircleScanVar(self->stepTable,fSet[0]);
|
||||||
|
if(scanvar != NULL && strcmp(scanvar,"om") != 0){
|
||||||
|
tolerance *= 2.;
|
||||||
|
strcpy(buffer,"ERROR: 2theta limit problem:");
|
||||||
|
if(!MotorCheckBoundary(self->p2Theta,fSet[0]-tolerance,&fHard,
|
||||||
|
buffer,256-strlen(buffer))){
|
||||||
|
SCWrite(pCon,buffer,eWarning);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!MotorCheckBoundary(self->p2Theta,fSet[0]+tolerance,&fHard,
|
||||||
|
buffer,256-strlen(buffer))){
|
||||||
|
SCWrite(pCon,buffer,eWarning);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
int MesureReflection(pMesure self, float fHKL[3], float fPsi,
|
int MesureReflection(pMesure self, float fHKL[3], float fPsi,
|
||||||
@ -973,6 +995,8 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
|||||||
int iRet, i,ii, iLF, iNP;
|
int iRet, i,ii, iLF, iNP;
|
||||||
char pBueffel[512], pNum[10], pTime[132];
|
char pBueffel[512], pNum[10], pTime[132];
|
||||||
pEVControl pEva = NULL;
|
pEVControl pEva = NULL;
|
||||||
|
pDummy pPtr = NULL;
|
||||||
|
pIDrivable pDriv = NULL;
|
||||||
|
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(pCon);
|
assert(pCon);
|
||||||
@ -1058,7 +1082,20 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
|||||||
fTemp = -777.77;
|
fTemp = -777.77;
|
||||||
pEva = (pEVControl)FindCommandData(pServ->pSics,"temperature",
|
pEva = (pEVControl)FindCommandData(pServ->pSics,"temperature",
|
||||||
"Environment Controller");
|
"Environment Controller");
|
||||||
if(pEva)
|
if(pEva == NULL)
|
||||||
|
{
|
||||||
|
pPtr = (pDummy)FindCommandData(pServ->pSics,"temperature",
|
||||||
|
"RemObject");
|
||||||
|
if(pPtr != NULL)
|
||||||
|
{
|
||||||
|
pDriv = pPtr->pDescriptor->GetInterface(pPtr,DRIVEID);
|
||||||
|
if(pDriv != NULL)
|
||||||
|
{
|
||||||
|
fTemp = pDriv->GetValue(pPtr,pCon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
iRet = EVCGetPos(pEva, pCon,&fTemp);
|
iRet = EVCGetPos(pEva, pCon,&fTemp);
|
||||||
}
|
}
|
||||||
@ -1120,6 +1157,19 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static FILE *openListFile(char *pName){
|
||||||
|
FILE *fd = NULL;
|
||||||
|
pDynString filename = NULL;
|
||||||
|
filename = findBatchFile(pServ->pSics,pName);
|
||||||
|
if(filename != NULL){
|
||||||
|
fd = fopen(GetCharArray(filename),"r");
|
||||||
|
DeleteDynString(filename);
|
||||||
|
} else {
|
||||||
|
fd = fopen(pName,"r");
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
int MesureFile(pMesure self, char *pFile, int iSkip, SConnection *pCon)
|
int MesureFile(pMesure self, char *pFile, int iSkip, SConnection *pCon)
|
||||||
{
|
{
|
||||||
@ -1132,7 +1182,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
|||||||
assert(pCon);
|
assert(pCon);
|
||||||
|
|
||||||
/* well before doing a thing, open the list file */
|
/* well before doing a thing, open the list file */
|
||||||
fd = fopen(pFile,"r");
|
fd = openListFile(pFile);
|
||||||
if(!fd)
|
if(!fd)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
|
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
|
||||||
@ -1221,7 +1271,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
|||||||
assert(pCon);
|
assert(pCon);
|
||||||
|
|
||||||
/* well before doing a thing, open the list file */
|
/* well before doing a thing, open the list file */
|
||||||
fd = fopen(pFile,"r");
|
fd = openListFile(pFile);
|
||||||
if(!fd)
|
if(!fd)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
|
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
|
||||||
@ -1280,7 +1330,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
|||||||
assert(pCon);
|
assert(pCon);
|
||||||
|
|
||||||
/* well before doing a thing, open the list file */
|
/* well before doing a thing, open the list file */
|
||||||
fd = fopen(pFile,"r");
|
fd = openListFile(pFile);
|
||||||
if(!fd)
|
if(!fd)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
|
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
|
||||||
|
1
modriv.h
1
modriv.h
@ -73,5 +73,6 @@
|
|||||||
/* ----------------------- Simulation -----------------------------------*/
|
/* ----------------------- Simulation -----------------------------------*/
|
||||||
MotorDriver *CreateSIM(SConnection *pCon, int argc, char *argv[]);
|
MotorDriver *CreateSIM(SConnection *pCon, int argc, char *argv[]);
|
||||||
void KillSIM(void *pData);
|
void KillSIM(void *pData);
|
||||||
|
MotorDriver *RGMakeMotorDriver(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
258
moregress.c
Normal file
258
moregress.c
Normal file
@ -0,0 +1,258 @@
|
|||||||
|
/**
|
||||||
|
* This is a regression testing motor driver for SICS.
|
||||||
|
* A parameter can be set which makes this driver cause
|
||||||
|
* various error conditions. This can then be used to
|
||||||
|
* verify and debug the working of upper level code
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke, July 2007
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sics.h>
|
||||||
|
#include <modriv.h>
|
||||||
|
|
||||||
|
/*===================== supported errors ======================*/
|
||||||
|
#define NONE 0
|
||||||
|
#define STARTFAIL 1
|
||||||
|
#define BADPOS 2 /* positioning problem */
|
||||||
|
#define FAIL 3 /* failure */
|
||||||
|
#define OFFPOS 4 /* off pos by .2 */
|
||||||
|
#define READFAIL 5
|
||||||
|
#define RUN 6 /* keep running; for interrupt testing */
|
||||||
|
/*=============================================================*/
|
||||||
|
typedef struct __RGMoDriv{
|
||||||
|
/* 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 */
|
||||||
|
float target;
|
||||||
|
int errorType;
|
||||||
|
int recover;
|
||||||
|
int counter;
|
||||||
|
} RGMotorDriver;
|
||||||
|
|
||||||
|
/*================================================================
|
||||||
|
GetPos returns OKOK on success, HWFault on failure
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static int RGGetPos(void *data, float *fPos){
|
||||||
|
RGMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (RGMotorDriver *)data;
|
||||||
|
if(self->errorType == READFAIL){
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
if(self->errorType > 1 && self->errorType < 6){
|
||||||
|
*fPos = self->target - .2;
|
||||||
|
} else {
|
||||||
|
*fPos = self->target;
|
||||||
|
}
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------
|
||||||
|
RunTo starts the motor running. Returns OKOK on success, HWfault
|
||||||
|
on Errors
|
||||||
|
------------------------------------------------------------------*/
|
||||||
|
static int RGRunTo(void *data, float newValue){
|
||||||
|
RGMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (RGMotorDriver *)data;
|
||||||
|
self->target = newValue;
|
||||||
|
if(self->errorType == STARTFAIL){
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
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 RGCheckStatus(void *data){
|
||||||
|
RGMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (RGMotorDriver *)data;
|
||||||
|
switch(self->errorType){
|
||||||
|
case BADPOS:
|
||||||
|
return HWPosFault;
|
||||||
|
break;
|
||||||
|
case FAIL:
|
||||||
|
return HWFault;
|
||||||
|
break;
|
||||||
|
case RUN:
|
||||||
|
return HWBusy;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return HWIdle;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
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 RGGetError(void *data, int *iCode, char *buffer,
|
||||||
|
int iBufLen){
|
||||||
|
RGMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (RGMotorDriver *)data;
|
||||||
|
*iCode = self->errorType;
|
||||||
|
switch(self->errorType){
|
||||||
|
case NONE:
|
||||||
|
strncpy(buffer,"No error found",iBufLen);
|
||||||
|
break;
|
||||||
|
case BADPOS:
|
||||||
|
strncpy(buffer,"Position not reached",iBufLen);
|
||||||
|
break;
|
||||||
|
case FAIL:
|
||||||
|
strncpy(buffer,"Hardware is mad",iBufLen);
|
||||||
|
break;
|
||||||
|
case STARTFAIL:
|
||||||
|
strncpy(buffer,"Failed to start motor",iBufLen);
|
||||||
|
break;
|
||||||
|
case READFAIL:
|
||||||
|
strncpy(buffer,"Failed to read motor",iBufLen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------
|
||||||
|
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 RGFixIt(void *data, int iError, float newValue){
|
||||||
|
RGMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (RGMotorDriver *)data;
|
||||||
|
if(self->recover == 1){
|
||||||
|
self->errorType = NONE;
|
||||||
|
return MOTREDO;
|
||||||
|
}
|
||||||
|
return MOTFAIL;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------
|
||||||
|
Halt tries to stop the motor. Halt errors are ignored
|
||||||
|
---------------------------------------------------------------------*/
|
||||||
|
static int RGHalt(void *data){
|
||||||
|
RGMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (RGMotorDriver *)data;
|
||||||
|
self->errorType = NONE;
|
||||||
|
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 RGGetDriverPar(void *data, char *name, float *value){
|
||||||
|
RGMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (RGMotorDriver *)data;
|
||||||
|
if(strcmp(name,"errortype") == 0){
|
||||||
|
*value = (float)self->errorType;
|
||||||
|
return 1;
|
||||||
|
} else if (strcmp(name,"recover") == 0){
|
||||||
|
*value = self->recover;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 RGSetDriverPar(void *data, SConnection *pCon,
|
||||||
|
char *name, float value){
|
||||||
|
RGMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (RGMotorDriver *)data;
|
||||||
|
if(strcmp(name,"errortype") == 0){
|
||||||
|
self->errorType = (int)value;
|
||||||
|
return 1;
|
||||||
|
} else if (strcmp(name,"recover") == 0){
|
||||||
|
self->recover = (int)value;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
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 RGListDriverPar(void *data, char *motorname,
|
||||||
|
SConnection *pCon){
|
||||||
|
RGMotorDriver *self = NULL;
|
||||||
|
char buffer[256];
|
||||||
|
|
||||||
|
self = (RGMotorDriver *)data;
|
||||||
|
snprintf(buffer,255,"%s errortype = %d", motorname,
|
||||||
|
self->errorType);
|
||||||
|
SCWrite(pCon,buffer,eValue);
|
||||||
|
|
||||||
|
snprintf(buffer,255,"%s recover = %d", motorname,
|
||||||
|
self->recover);
|
||||||
|
SCWrite(pCon,buffer,eValue);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------
|
||||||
|
KillPrivate has the task to delete possibly dynamically allocated
|
||||||
|
memory in the private part of the driver structure
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
static void RGKillPrivate(void *data){
|
||||||
|
RGMotorDriver *self = NULL;
|
||||||
|
|
||||||
|
self = (RGMotorDriver *)data;
|
||||||
|
}
|
||||||
|
/*=======================================================================*/
|
||||||
|
MotorDriver *RGMakeMotorDriver(void) {
|
||||||
|
RGMotorDriver *pNew = NULL;
|
||||||
|
|
||||||
|
pNew = malloc(sizeof(RGMotorDriver));
|
||||||
|
if(pNew == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(pNew,0,sizeof(RGMotorDriver));
|
||||||
|
|
||||||
|
pNew->GetPosition = RGGetPos;
|
||||||
|
pNew->RunTo = RGRunTo;
|
||||||
|
pNew->GetStatus = RGCheckStatus;
|
||||||
|
pNew->GetError = RGGetError;
|
||||||
|
pNew->TryAndFixIt = RGFixIt;
|
||||||
|
pNew->Halt = RGHalt;
|
||||||
|
pNew->GetDriverPar = RGGetDriverPar;
|
||||||
|
pNew->SetDriverPar = RGSetDriverPar;
|
||||||
|
pNew->ListDriverPar = RGListDriverPar;
|
||||||
|
pNew->KillPrivate = RGKillPrivate;
|
||||||
|
pNew->fLower = -180.;
|
||||||
|
pNew->fUpper = 180.;
|
||||||
|
|
||||||
|
return (MotorDriver *)pNew;
|
||||||
|
}
|
||||||
|
|
34
motor.c
34
motor.c
@ -76,13 +76,6 @@
|
|||||||
#define IGNOREFAULT 10
|
#define IGNOREFAULT 10
|
||||||
#define MOVECOUNT 11
|
#define MOVECOUNT 11
|
||||||
|
|
||||||
/*------------------------------------------------------------------------
|
|
||||||
a tiny structure used in CallBack work
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
float fVal;
|
|
||||||
char *pName;
|
|
||||||
} MotCallback;
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
static void *MotorGetInterface(void *pData, int iID)
|
static void *MotorGetInterface(void *pData, int iID)
|
||||||
@ -416,7 +409,7 @@ static void handleMoveCallback(pMotor self, SConnection *pCon)
|
|||||||
|
|
||||||
|
|
||||||
/* create and initialize parameters */
|
/* create and initialize parameters */
|
||||||
pM->ParArray = ObParCreate(12);
|
pM->ParArray = ObParCreate(MOTOBPARLENGTH);
|
||||||
if(!pM->ParArray)
|
if(!pM->ParArray)
|
||||||
{
|
{
|
||||||
free(pM);
|
free(pM);
|
||||||
@ -606,6 +599,7 @@ extern void KillPiPiezo(void *pData);
|
|||||||
if(iRet == 1)
|
if(iRet == 1)
|
||||||
{
|
{
|
||||||
SCparChange(pCon);
|
SCparChange(pCon);
|
||||||
|
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||||
return iRet;
|
return iRet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -631,6 +625,7 @@ extern void KillPiPiezo(void *pData);
|
|||||||
fLimit -= fChange;
|
fLimit -= fChange;
|
||||||
ObParSet(self->ParArray,self->name,"softlowerlim",fLimit,pCon);
|
ObParSet(self->ParArray,self->name,"softlowerlim",fLimit,pCon);
|
||||||
SCparChange(pCon);
|
SCparChange(pCon);
|
||||||
|
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -652,6 +647,7 @@ extern void KillPiPiezo(void *pData);
|
|||||||
ObParInit(self->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser);
|
ObParInit(self->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||||
SCparChange(pCon);
|
SCparChange(pCon);
|
||||||
|
|
||||||
return iRet;
|
return iRet;
|
||||||
@ -747,10 +743,11 @@ extern void KillPiPiezo(void *pData);
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check boundaries first */
|
/* check boundaries first */
|
||||||
iRet = MotorCheckBoundary(self,fNew,&fHard,pBueffel,511);
|
iRet = MotorCheckBoundary(self,fNew,&fHard,pError,131);
|
||||||
if(!iRet)
|
if(!iRet)
|
||||||
{
|
{
|
||||||
SCWrite(pCon,pBueffel,eStatus);
|
snprintf(pBueffel,511,"ERROR: %s",pError);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
SCSetInterrupt(pCon,eAbortOperation);
|
SCSetInterrupt(pCon,eAbortOperation);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -784,6 +781,7 @@ extern void KillPiPiezo(void *pData);
|
|||||||
self->retryCount = 0;
|
self->retryCount = 0;
|
||||||
self->stopped = 0;
|
self->stopped = 0;
|
||||||
self->fTarget = fHard;
|
self->fTarget = fHard;
|
||||||
|
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||||
self->posCount = 0;
|
self->posCount = 0;
|
||||||
iRet = self->pDriver->RunTo(self->pDriver,fHard);
|
iRet = self->pDriver->RunTo(self->pDriver,fHard);
|
||||||
if(iRet != OKOK)
|
if(iRet != OKOK)
|
||||||
@ -1024,6 +1022,21 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
|||||||
SCWrite(pCon,pBueffel,eError);
|
SCWrite(pCon,pBueffel,eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
} else if(strcmp(argv[2],"regress") == 0)
|
||||||
|
{
|
||||||
|
pDriver = RGMakeMotorDriver();
|
||||||
|
if(!pDriver)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* create the motor */
|
||||||
|
pNew = MotorInit("regress",argv[1],pDriver);
|
||||||
|
if(!pNew)
|
||||||
|
{
|
||||||
|
sprintf(pBueffel,"Failure to create motor %s",argv[1]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1085,7 +1098,6 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
|||||||
{
|
{
|
||||||
self->pDriver->ListDriverPar(self->pDriver,self->name, pCon);
|
self->pDriver->ListDriverPar(self->pDriver,self->name, pCon);
|
||||||
}
|
}
|
||||||
SCWrite(pCon,"ENDLIST",eFinish);
|
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
void MotorReset(pMotor pM)
|
void MotorReset(pMotor pM)
|
||||||
|
8
motor.h
8
motor.h
@ -14,6 +14,7 @@
|
|||||||
#include "obdes.h"
|
#include "obdes.h"
|
||||||
#include "interface.h"
|
#include "interface.h"
|
||||||
|
|
||||||
|
#define MOTOBPARLENGTH 12
|
||||||
typedef struct __Motor {
|
typedef struct __Motor {
|
||||||
pObjectDescriptor pDescriptor;
|
pObjectDescriptor pDescriptor;
|
||||||
ObPar *ParArray;
|
ObPar *ParArray;
|
||||||
@ -32,6 +33,13 @@
|
|||||||
int stopped;
|
int stopped;
|
||||||
} Motor;
|
} Motor;
|
||||||
typedef Motor *pMotor;
|
typedef Motor *pMotor;
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
a tiny structure used in CallBack work
|
||||||
|
--------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
float fVal;
|
||||||
|
char *pName;
|
||||||
|
} MotCallback;
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/* parameter management */
|
/* parameter management */
|
||||||
|
429
multicounter.c
Normal file
429
multicounter.c
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
/**
|
||||||
|
* The MultiCounter is another counter which coordinates multiple
|
||||||
|
* counting objects, counters and histogram memories. It also calls a
|
||||||
|
* script function after TransferData which collects counters and monitors.
|
||||||
|
* The purpose is to have a flexible counter abstraction for upper level
|
||||||
|
* code such as maximizers and scan functions. The script can deal with
|
||||||
|
* counting on monitors or on sums of histogram memories.
|
||||||
|
*
|
||||||
|
* This is a bit unclean. The counter driver is of no use, therefore its
|
||||||
|
* private data structure is used to hold the other counters and the name
|
||||||
|
* of the script. It would have been better to inherit from counter but
|
||||||
|
* that would have required lost of type casts. I am to lazy for this.
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke, September 2006
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <tcl.h>
|
||||||
|
#include "multicounter.h"
|
||||||
|
#include "counter.h"
|
||||||
|
#include "HistMem.h"
|
||||||
|
#include "macro.h"
|
||||||
|
#include "splitter.h"
|
||||||
|
|
||||||
|
#define MAXSLAVE 16
|
||||||
|
#define NOCOUNTERS -2727
|
||||||
|
/*=============== code for the driver ======================================*/
|
||||||
|
typedef struct {
|
||||||
|
void *slaveData[MAXSLAVE];
|
||||||
|
pICountable slaves[MAXSLAVE];
|
||||||
|
char *transferScript;
|
||||||
|
int nSlaves;
|
||||||
|
}MultiCounter, *pMultiCounter;
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static void KillMultiDriver(struct __COUNTER *data){
|
||||||
|
pMultiCounter self = (pMultiCounter)data->pData;
|
||||||
|
if(self == NULL){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(self->transferScript != NULL){
|
||||||
|
free(self->transferScript);
|
||||||
|
}
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
/*============== countable interface functions ============================*/
|
||||||
|
static int MMCCHalt(void *pData){
|
||||||
|
int i, retVal = OKOK, status;
|
||||||
|
pCounter pCount = NULL;
|
||||||
|
pMultiCounter self = NULL;
|
||||||
|
|
||||||
|
pCount = (pCounter)pData;
|
||||||
|
if(pCount != NULL){
|
||||||
|
self = (pMultiCounter)pCount->pDriv->pData;
|
||||||
|
}
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
for(i = 0; i < self->nSlaves; i++){
|
||||||
|
status = self->slaves[i]->Halt(self->slaveData[i]);
|
||||||
|
if(status != OKOK)
|
||||||
|
retVal = status;
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int MMCCStart(void *pData, SConnection *pCon)
|
||||||
|
{
|
||||||
|
int i, status;
|
||||||
|
pCounter pCount = NULL;
|
||||||
|
pMultiCounter self = NULL;
|
||||||
|
|
||||||
|
pCount = (pCounter)pData;
|
||||||
|
if(pCount != NULL){
|
||||||
|
self = (pMultiCounter)pCount->pDriv->pData;
|
||||||
|
}
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
for(i = 0; i < self->nSlaves; 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);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pCount->isUpToDate = 0;
|
||||||
|
pCount->tStart = time(NULL);
|
||||||
|
InvokeCallBack(pCount->pCall,COUNTSTART,pCon);
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int MMCCStatus(void *pData, SConnection *pCon){
|
||||||
|
int status,i;
|
||||||
|
pCounter pCount = NULL;
|
||||||
|
pMultiCounter self = NULL;
|
||||||
|
pDummy pDum = NULL;
|
||||||
|
|
||||||
|
pCount = (pCounter)pData;
|
||||||
|
if(pCount != NULL){
|
||||||
|
self = (pMultiCounter)pCount->pDriv->pData;
|
||||||
|
}
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
if(self->nSlaves == 0) {
|
||||||
|
pCount->pDriv->iErrorCode = NOCOUNTERS;
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int MMCCPause(void *pData, SConnection *pCon){
|
||||||
|
int i, status;
|
||||||
|
pCounter pCount = NULL;
|
||||||
|
pMultiCounter self = NULL;
|
||||||
|
|
||||||
|
pCount = (pCounter)pData;
|
||||||
|
if(pCount != NULL){
|
||||||
|
self = (pMultiCounter)pCount->pDriv->pData;
|
||||||
|
}
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
for(i = 0; i < self->nSlaves; i++){
|
||||||
|
status = self->slaves[i]->Pause(self->slaveData[i],pCon);
|
||||||
|
if(status != OKOK){
|
||||||
|
MMCCHalt(pCount);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int MMCCContinue(void *pData, SConnection *pCon){
|
||||||
|
int i, status;
|
||||||
|
pCounter pCount = NULL;
|
||||||
|
pMultiCounter self = NULL;
|
||||||
|
|
||||||
|
pCount = (pCounter)pData;
|
||||||
|
if(pCount != NULL){
|
||||||
|
self = (pMultiCounter)pCount->pDriv->pData;
|
||||||
|
}
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
for(i = 0; i < self->nSlaves; i++){
|
||||||
|
status = self->slaves[i]->Continue(self->slaveData[i],pCon);
|
||||||
|
if(status != OKOK){
|
||||||
|
MMCCHalt(pCount);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
static char *getNextMMCCNumber(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;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static void loadCountData(pCounter pCount, const char *data){
|
||||||
|
char *pPtr = NULL;
|
||||||
|
char pNumber[80];
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
pPtr = (char *)data;
|
||||||
|
pPtr = getNextMMCCNumber(pPtr,pNumber);
|
||||||
|
pCount->pDriv->fTime = atof(pNumber);
|
||||||
|
while(pPtr != NULL && i < MAXCOUNT){
|
||||||
|
pPtr = getNextMMCCNumber(pPtr,pNumber);
|
||||||
|
pCount->pDriv->lCounts[i] = atoi(pNumber);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int MMCCTransfer(void *pData, SConnection *pCon){
|
||||||
|
int i, retVal = OKOK, status;
|
||||||
|
char pBueffel[132];
|
||||||
|
pCounter pCount = NULL;
|
||||||
|
pMultiCounter self = NULL;
|
||||||
|
int tclStatus;
|
||||||
|
|
||||||
|
pCount = (pCounter)pData;
|
||||||
|
if(pCount != NULL){
|
||||||
|
self = (pMultiCounter)pCount->pDriv->pData;
|
||||||
|
}
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
for(i = 0; i < self->nSlaves; i++){
|
||||||
|
status = self->slaves[i]->TransferData(self->slaveData[i], pCon);
|
||||||
|
if(status != OKOK){
|
||||||
|
retVal = status;
|
||||||
|
sprintf(pBueffel,"WARNING: slave histogram %d failed to transfer data",
|
||||||
|
i);
|
||||||
|
SCWrite(pCon,pBueffel,eWarning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(self->transferScript != NULL){
|
||||||
|
MacroPush(pCon);
|
||||||
|
tclStatus = Tcl_Eval(InterpGetTcl(pServ->pSics), self->transferScript);
|
||||||
|
if(tclStatus != TCL_OK){
|
||||||
|
snprintf(pBueffel,131,"ERROR: TransferScript returned: %s",
|
||||||
|
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
MacroPop();
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
MacroPop();
|
||||||
|
loadCountData(pCount,Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static void MMCCParameter(void *pData, float fPreset, CounterMode eMode ){
|
||||||
|
int i;
|
||||||
|
pCounter pCount = NULL;
|
||||||
|
pMultiCounter self = NULL;
|
||||||
|
|
||||||
|
pCount = (pCounter)pData;
|
||||||
|
if(pCount != NULL){
|
||||||
|
self = (pMultiCounter)pCount->pDriv->pData;
|
||||||
|
}
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
for(i = 0; i < self->nSlaves; i++){
|
||||||
|
self->slaves[i]->SetCountParameters(self->slaveData[i], fPreset,
|
||||||
|
eMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*======================= Driver Interface ==============================*/
|
||||||
|
static int MultiCounterSet(struct __COUNTER *self, char *name,
|
||||||
|
int iCter, float fVal){
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static int MultiCounterGet(struct __COUNTER *self, char *name,
|
||||||
|
int iCter, float *fVal){
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static int MultiCounterSend(struct __COUNTER *self, char *pText,
|
||||||
|
char *reply, int replylen){
|
||||||
|
|
||||||
|
strncpy(reply,"NOT Implemented",replylen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static int MultiCounterError(struct __COUNTER *pData, int *iCode,
|
||||||
|
char *error, int errlen){
|
||||||
|
pCounter pCount = NULL;
|
||||||
|
|
||||||
|
pCount = (pCounter)pData;
|
||||||
|
|
||||||
|
if(pCount->pDriv->iErrorCode == NOCOUNTERS){
|
||||||
|
strncpy(error,"NO counters configured!",errlen);
|
||||||
|
} else {
|
||||||
|
strncpy(error,"Not Implemented", errlen);
|
||||||
|
}
|
||||||
|
return COTERM;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
static int MultiCounterFix(struct __COUNTER *self, int iCode){
|
||||||
|
return COTERM;
|
||||||
|
}
|
||||||
|
/*=============== Interpreter Interface ================================ */
|
||||||
|
int MultiCounterAction(SConnection *pCon, SicsInterp *pSics,
|
||||||
|
void *pData, int argc, char *argv[]){
|
||||||
|
pMultiCounter self = NULL;
|
||||||
|
pCounter pCount = NULL;
|
||||||
|
char buffer[256];
|
||||||
|
|
||||||
|
if(argc > 1){
|
||||||
|
strtolower(argv[1]);
|
||||||
|
if(strcmp(argv[1],"transferscript") == 0){
|
||||||
|
pCount = (pCounter)pData;
|
||||||
|
self = (pMultiCounter)pCount->pDriv->pData;
|
||||||
|
if(argc < 3){
|
||||||
|
SCPrintf(pCon,eValue,"%s.transferscript = %s",
|
||||||
|
argv[0],self->transferScript);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
if(!SCMatchRights(pCon,usUser)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(self->transferScript != NULL){
|
||||||
|
free(self->transferScript);
|
||||||
|
}
|
||||||
|
Arg2Text(argc-2,&argv[2],buffer,255);
|
||||||
|
self->transferScript = strdup(buffer);
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CountAction(pCon,pSics,pData,argc,argv);
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
int MakeMultiCounter(SConnection *pCon, SicsInterp *pSics,
|
||||||
|
void *pData, int argc, char *argv[]){
|
||||||
|
int i, status;
|
||||||
|
pCounter pNew = NULL;
|
||||||
|
char pBueffel[132];
|
||||||
|
CommandList *pCom;
|
||||||
|
pICountable pCount;
|
||||||
|
pMultiCounter self = NULL;
|
||||||
|
pCounterDriver pDriv = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
need at least two parameters
|
||||||
|
*/
|
||||||
|
if(argc < 3){
|
||||||
|
SCWrite(pCon,"ERROR: insufficient number of arguments to MakeMultiCounter",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
allocate our data structure
|
||||||
|
*/
|
||||||
|
self = malloc(sizeof(MultiCounter));
|
||||||
|
pDriv = malloc(sizeof(CounterDriver));
|
||||||
|
if(self == NULL || pDriv == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounter",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memset(self,0,sizeof(MultiCounter));
|
||||||
|
memset(pDriv,0,sizeof(CounterDriver));
|
||||||
|
pDriv->pData = self;
|
||||||
|
pDriv->KillPrivate = KillMultiDriver;
|
||||||
|
pDriv->iNoOfMonitors = MAXCOUNT;
|
||||||
|
pNew = CreateCounter(argv[1],pDriv);
|
||||||
|
if(pNew == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: out of memory in MakeMultiCounter",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pDriv->Get = MultiCounterGet;
|
||||||
|
pDriv->GetError = MultiCounterError;
|
||||||
|
pDriv->TryAndFixIt = MultiCounterFix;
|
||||||
|
pDriv->Set = MultiCounterSet;
|
||||||
|
pDriv->Send
|
||||||
|
= MultiCounterSend;
|
||||||
|
|
||||||
|
/*
|
||||||
|
assign interface functions
|
||||||
|
*/
|
||||||
|
pNew->pCountInt->Halt = MMCCHalt;
|
||||||
|
pNew->pCountInt->StartCount = MMCCStart;
|
||||||
|
pNew->pCountInt->CheckCountStatus = MMCCStatus;
|
||||||
|
pNew->pCountInt->Pause = MMCCPause;
|
||||||
|
pNew->pCountInt->Continue = MMCCContinue;
|
||||||
|
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){
|
||||||
|
sprintf(pBueffel,"ERROR: object %s not found in MakeMultiCounter",
|
||||||
|
argv[i]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pCount = GetCountableInterface(pCom->pData);
|
||||||
|
if(!pCount){
|
||||||
|
sprintf(pBueffel,"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
|
||||||
|
*/
|
||||||
|
status = AddCommand(pSics,argv[1],MultiCounterAction,DeleteCounter,
|
||||||
|
pNew);
|
||||||
|
if(!status){
|
||||||
|
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
|
||||||
|
SCWrite(pCon,pBueffel,eError);
|
||||||
|
DeleteCounter(pNew);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
19
multicounter.h
Normal file
19
multicounter.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* The MultiCounter is another counter which coordinates multiple
|
||||||
|
* counting objects, counters and histogram memories. It also calls a
|
||||||
|
* script function after TransferData which collects counters and monitors.
|
||||||
|
* The purpose is to have a flexible counter abstraction for upper level
|
||||||
|
* code such as maximizers and scan functions. The script can deal with
|
||||||
|
* counting on monitors or on sums of histogram memories.
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke, September 2006
|
||||||
|
*/
|
||||||
|
#ifndef MULTICOUNTER_H_
|
||||||
|
#define MULTICOUNTER_H_
|
||||||
|
#include <sics.h>
|
||||||
|
|
||||||
|
int MakeMultiCounter(SConnection *pCon, SicsInterp *pSics,
|
||||||
|
void *pData, int argc, char *argv[]);
|
||||||
|
#endif /*MULTICOUNTER_H_*/
|
@ -315,6 +315,7 @@
|
|||||||
char pError[132];
|
char pError[132];
|
||||||
int i, iToken, iRet;
|
int i, iToken, iRet;
|
||||||
sParser PP;
|
sParser PP;
|
||||||
|
CommandList *pCom = NULL;
|
||||||
|
|
||||||
assert(pCon);
|
assert(pCon);
|
||||||
assert(pSics);
|
assert(pSics);
|
||||||
@ -345,9 +346,10 @@
|
|||||||
break;
|
break;
|
||||||
case ENDCONFIG:
|
case ENDCONFIG:
|
||||||
/* reconfigure command to final state */
|
/* reconfigure command to final state */
|
||||||
RemoveCommand(pSics,argv[0]);
|
pCom = FindCommand(pSics,argv[0]);
|
||||||
AddCommand(pSics,argv[0],MultiWrapper,KillMultiMotor,
|
assert(pCom != NULL);
|
||||||
self);
|
pCom->OFunc = MultiWrapper;
|
||||||
|
pCom->KFunc = KillMultiMotor;
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
case ALIAS:
|
case ALIAS:
|
||||||
|
10
network.c
10
network.c
@ -424,9 +424,14 @@ CreateSocketAdress(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the we can write to the socket first....
|
||||||
|
* Well, this how it should be. However, on linux I observe that
|
||||||
|
* there is a problem with Java clients not reliably receiving data when
|
||||||
|
* this is active.
|
||||||
|
*/
|
||||||
#ifndef CYGNUS
|
#ifndef CYGNUS
|
||||||
/* setup for select first */
|
tmo.tv_usec = 10;
|
||||||
tmo.tv_usec = 100;
|
|
||||||
FD_ZERO(&lMask);
|
FD_ZERO(&lMask);
|
||||||
FD_SET(self->sockid,&lMask);
|
FD_SET(self->sockid,&lMask);
|
||||||
if((self->sockid >= FD_SETSIZE) || (self->sockid < 0) )
|
if((self->sockid >= FD_SETSIZE) || (self->sockid < 0) )
|
||||||
@ -446,6 +451,7 @@ CreateSocketAdress(
|
|||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
iRet = send(self->sockid,buffer,lLen,0);
|
iRet = send(self->sockid,buffer,lLen,0);
|
||||||
if(iRet != lLen)
|
if(iRet != lLen)
|
||||||
{
|
{
|
||||||
|
7
nread.c
7
nread.c
@ -686,6 +686,9 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
|||||||
int iRet, iStatus;
|
int iRet, iStatus;
|
||||||
int iCount;
|
int iCount;
|
||||||
NetItem NItem;
|
NetItem NItem;
|
||||||
|
int conCount = 0;
|
||||||
|
char num[50];
|
||||||
|
IPair *options = NULL;
|
||||||
|
|
||||||
self = (pNetRead)pData;
|
self = (pNetRead)pData;
|
||||||
assert(self);
|
assert(self);
|
||||||
@ -716,9 +719,13 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
|||||||
{
|
{
|
||||||
iCount = NItem.pSock->sockid;
|
iCount = NItem.pSock->sockid;
|
||||||
}
|
}
|
||||||
|
conCount++;
|
||||||
iRet = LLDnodePtr2Next(self->iList);
|
iRet = LLDnodePtr2Next(self->iList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
snprintf(num,50,"%d", conCount);
|
||||||
|
IFSetOption(pSICSOptions,"ConnectionCount",num);
|
||||||
|
|
||||||
/* the select itself */
|
/* the select itself */
|
||||||
tmo.tv_usec = self->iReadTimeout;
|
tmo.tv_usec = self->iReadTimeout;
|
||||||
iCount++;
|
iCount++;
|
||||||
|
@ -109,6 +109,8 @@
|
|||||||
/* initialise tasker */
|
/* initialise tasker */
|
||||||
assert(TaskerInit(&self->pTasker));
|
assert(TaskerInit(&self->pTasker));
|
||||||
|
|
||||||
|
pSICSOptions = IFAddOption(pSICSOptions, "ConnectionCount","0");
|
||||||
|
|
||||||
/* initialise the server from script */
|
/* initialise the server from script */
|
||||||
if(file == NULL)
|
if(file == NULL)
|
||||||
{
|
{
|
||||||
@ -397,13 +399,13 @@
|
|||||||
*/
|
*/
|
||||||
killTclDrivable();
|
killTclDrivable();
|
||||||
|
|
||||||
/* close the List system */
|
|
||||||
LLDsystemClose();
|
|
||||||
|
|
||||||
KillFreeConnections();
|
KillFreeConnections();
|
||||||
|
|
||||||
killSICSHipadaba();
|
killSICSHipadaba();
|
||||||
|
|
||||||
|
/* close the List system */
|
||||||
|
LLDsystemClose();
|
||||||
|
|
||||||
/* make fortify print his findings */
|
/* make fortify print his findings */
|
||||||
Fortify_DumpAllMemory(iFortifyScope);
|
Fortify_DumpAllMemory(iFortifyScope);
|
||||||
Fortify_LeaveScope();
|
Fortify_LeaveScope();
|
||||||
|
65
nxscript.c
65
nxscript.c
@ -373,6 +373,31 @@ static void putSicsData(SConnection *pCon, SicsInterp *pSics,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*----------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------*/
|
||||||
|
static void putAttribute(SConnection *pCon, SicsInterp *pSics,
|
||||||
|
pNXScript self, int argc, char *argv[]){
|
||||||
|
int status, type = NX_CHAR;
|
||||||
|
char buffer[256];
|
||||||
|
|
||||||
|
if(argc < 5){
|
||||||
|
SCWrite(pCon,"ERROR: insufficient number of arguments to putAttribute",
|
||||||
|
eError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = NXDopenalias(self->fileHandle,self->dictHandle,argv[2]);
|
||||||
|
if(status != NX_OK){
|
||||||
|
sprintf(buffer,"ERROR: failed to open alias %s", argv[2]);
|
||||||
|
SCWrite(pCon,buffer,eError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
status = NXputattr(self->fileHandle,argv[3],(void *)argv[4],
|
||||||
|
strlen(argv[4])+1, type);
|
||||||
|
if(status != NX_OK){
|
||||||
|
sprintf(buffer,"ERROR: failed to write attribute %s", argv[3]);
|
||||||
|
SCWrite(pCon,buffer,eError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
static void updateHMDim(NXScript *self, pHistMem mem){
|
static void updateHMDim(NXScript *self, pHistMem mem){
|
||||||
int iDim[MAXDIM];
|
int iDim[MAXDIM];
|
||||||
int i, rank, timeLength, status;
|
int i, rank, timeLength, status;
|
||||||
@ -412,7 +437,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
|||||||
pNXScript self,
|
pNXScript self,
|
||||||
int argc, char *argv[]){
|
int argc, char *argv[]){
|
||||||
pHistMem mem = NULL;
|
pHistMem mem = NULL;
|
||||||
int status, start, length, i, subset = 0;
|
int status, start, length, i, subset = 0, bank = 0;
|
||||||
HistInt *iData = NULL;
|
HistInt *iData = NULL;
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
|
|
||||||
@ -461,6 +486,19 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* check for additional bank number
|
||||||
|
*/
|
||||||
|
if(argc > 6){
|
||||||
|
status = Tcl_GetInt(InterpGetTcl(pSics),argv[6],&bank);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
sprintf(buffer,"ERROR: failed to convert %s to integer",
|
||||||
|
argv[6]);
|
||||||
|
SCWrite(pCon,buffer,eError);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
read HM
|
read HM
|
||||||
*/
|
*/
|
||||||
@ -472,7 +510,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memset(iData,0,length*sizeof(HistInt));
|
memset(iData,0,length*sizeof(HistInt));
|
||||||
status = GetHistogramDirect(mem,pCon,0,start,start+length,iData,
|
status = GetHistogramDirect(mem,pCon,bank,start,start+length,iData,
|
||||||
length*sizeof(HistInt));
|
length*sizeof(HistInt));
|
||||||
}else{
|
}else{
|
||||||
/*
|
/*
|
||||||
@ -712,7 +750,10 @@ static void putArray(SConnection *pCon, SicsInterp *pSics,
|
|||||||
data = (float *)malloc(length*sizeof(float));
|
data = (float *)malloc(length*sizeof(float));
|
||||||
}
|
}
|
||||||
if(data == NULL){
|
if(data == NULL){
|
||||||
SCWrite(pCon,"ERROR: out of memory or invalid length",eError);
|
snprintf(buffer,255,
|
||||||
|
"ERROR: out of memory or invalid length at %s, length = %s",
|
||||||
|
argv[2],argv[4]);
|
||||||
|
SCWrite(pCon,buffer,eError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memset(data,0,length*sizeof(float));
|
memset(data,0,length*sizeof(float));
|
||||||
@ -980,6 +1021,9 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
|||||||
}else if(strcmp(argv[1],"putsicsdata") == 0){
|
}else if(strcmp(argv[1],"putsicsdata") == 0){
|
||||||
/*===============*/
|
/*===============*/
|
||||||
putSicsData(pCon,pSics,self,argc,argv);
|
putSicsData(pCon,pSics,self,argc,argv);
|
||||||
|
}else if(strcmp(argv[1],"putattribute") == 0){
|
||||||
|
/*===============*/
|
||||||
|
putAttribute(pCon,pSics,self,argc,argv);
|
||||||
} else {
|
} else {
|
||||||
SCWrite(pCon,"ERROR: put command not recognised",eError);
|
SCWrite(pCon,"ERROR: put command not recognised",eError);
|
||||||
}
|
}
|
||||||
@ -1032,6 +1076,7 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
pNXScript self = (pNXScript)pData;
|
pNXScript self = (pNXScript)pData;
|
||||||
char *pFile = NULL;
|
char *pFile = NULL;
|
||||||
int status;
|
int status;
|
||||||
|
char buffer[132];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
preliminary checks
|
preliminary checks
|
||||||
@ -1095,6 +1140,20 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(strcmp(argv[1],"isalias") == 0) {
|
||||||
|
if(argc < 3) {
|
||||||
|
SCWrite(pCon,"ERROR: need alias to test",eError);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(NXDget(self->dictHandle,argv[2],buffer,131) == NX_OK){
|
||||||
|
snprintf(buffer,131,"%s = 1", argv[2]);
|
||||||
|
} else {
|
||||||
|
snprintf(buffer,131,"%s = 0", argv[2]);
|
||||||
|
}
|
||||||
|
SCWrite(pCon,buffer,eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if(strcmp(argv[1],"makelink") == 0){
|
if(strcmp(argv[1],"makelink") == 0){
|
||||||
makeLink(pCon,pSics,self,argc,argv);
|
makeLink(pCon,pSics,self,argc,argv);
|
||||||
return 1;
|
return 1;
|
||||||
|
15
nxutil.c
15
nxutil.c
@ -28,8 +28,9 @@
|
|||||||
int iRet;
|
int iRet;
|
||||||
|
|
||||||
/* Find the motor */
|
/* Find the motor */
|
||||||
strtolower(pName);
|
strncpy(pBueffel,pName,511);
|
||||||
pMot = FindMotor(pSics,pName);
|
strtolower(pBueffel);
|
||||||
|
pMot = FindMotor(pSics,pBueffel);
|
||||||
if(!pMot)
|
if(!pMot)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"WARNING: cannot find motor %s",pName);
|
sprintf(pBueffel,"WARNING: cannot find motor %s",pName);
|
||||||
@ -58,8 +59,9 @@
|
|||||||
int iRet;
|
int iRet;
|
||||||
|
|
||||||
/* Find the motor */
|
/* Find the motor */
|
||||||
strtolower(pName);
|
strncpy(pBueffel,pName,511);
|
||||||
pMot = FindMotor(pSics,pName);
|
strtolower(pBueffel);
|
||||||
|
pMot = FindMotor(pSics,pBueffel);
|
||||||
if(!pMot)
|
if(!pMot)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"WARNING: cannot find motor %s",pName);
|
sprintf(pBueffel,"WARNING: cannot find motor %s",pName);
|
||||||
@ -95,8 +97,9 @@
|
|||||||
char *pText = NULL;
|
char *pText = NULL;
|
||||||
|
|
||||||
/* find it */
|
/* find it */
|
||||||
strtolower(pName);
|
strncpy(pBueffel,pName,511);
|
||||||
pVar = FindVariable(pSics,pName);
|
strtolower(pBueffel);
|
||||||
|
pVar = FindVariable(pSics,pBueffel);
|
||||||
if(!pVar)
|
if(!pVar)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"WARNING: cannot find variable %s",pName);
|
sprintf(pBueffel,"WARNING: cannot find variable %s",pName);
|
||||||
|
2
obdes.c
2
obdes.c
@ -84,7 +84,7 @@
|
|||||||
*/
|
*/
|
||||||
if(self->parNode != NULL){
|
if(self->parNode != NULL){
|
||||||
if(self->parNode->mama == NULL){
|
if(self->parNode->mama == NULL){
|
||||||
DeleteHipadabaNode(self->parNode);
|
DeleteHipadabaNode(self->parNode,NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(self);
|
free(self);
|
||||||
|
13
ofac.c
13
ofac.c
@ -119,6 +119,9 @@
|
|||||||
#include "sicslist.h"
|
#include "sicslist.h"
|
||||||
#include "cone.h"
|
#include "cone.h"
|
||||||
#include "sicshipadaba.h"
|
#include "sicshipadaba.h"
|
||||||
|
#include "multicounter.h"
|
||||||
|
#include "sicspoll.h"
|
||||||
|
#include "statemon.h"
|
||||||
/*----------------------- Server options creation -------------------------*/
|
/*----------------------- Server options creation -------------------------*/
|
||||||
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
|
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
@ -214,6 +217,7 @@
|
|||||||
AddCommand(pInter,"FileWhere",MacroWhere,WhereKill,NULL);
|
AddCommand(pInter,"FileWhere",MacroWhere,WhereKill,NULL);
|
||||||
*/
|
*/
|
||||||
AddCommand(pInter,"ClientPut",ClientPut,NULL,NULL);
|
AddCommand(pInter,"ClientPut",ClientPut,NULL,NULL);
|
||||||
|
AddCommand(pInter,"GumPut",GumPut,NULL,NULL);
|
||||||
AddCommand(pInter,"broadcast",Broadcast,NULL,NULL);
|
AddCommand(pInter,"broadcast",Broadcast,NULL,NULL);
|
||||||
AddCommand(pInter,"transact",TransactAction,NULL,NULL);
|
AddCommand(pInter,"transact",TransactAction,NULL,NULL);
|
||||||
AddCommand(pInter,"fulltransact",TransactAction,NULL,NULL);
|
AddCommand(pInter,"fulltransact",TransactAction,NULL,NULL);
|
||||||
@ -274,6 +278,7 @@
|
|||||||
AddCommand(pInter,"MakeCounter",MakeCounter,NULL,NULL);
|
AddCommand(pInter,"MakeCounter",MakeCounter,NULL,NULL);
|
||||||
AddCommand(pInter,"MakeO2T",CreateO2T,NULL,NULL);
|
AddCommand(pInter,"MakeO2T",CreateO2T,NULL,NULL);
|
||||||
AddCommand(pInter,"SicsAlias",SicsAlias,NULL,NULL);
|
AddCommand(pInter,"SicsAlias",SicsAlias,NULL,NULL);
|
||||||
|
AddCommand(pInter,"SicsAlias",DefineAlias,NULL,NULL);
|
||||||
AddCommand(pInter,"DefineAlias",DefineAlias,NULL,NULL); /* M.Z. */
|
AddCommand(pInter,"DefineAlias",DefineAlias,NULL,NULL); /* M.Z. */
|
||||||
AddCommand(pInter,"MakeHM",MakeHistMemory,NULL,NULL);
|
AddCommand(pInter,"MakeHM",MakeHistMemory,NULL,NULL);
|
||||||
AddCommand(pInter,"VelocitySelector",VelSelFactory,NULL,NULL);
|
AddCommand(pInter,"VelocitySelector",VelSelFactory,NULL,NULL);
|
||||||
@ -328,6 +333,12 @@
|
|||||||
InstallSinfox,NULL,NULL);
|
InstallSinfox,NULL,NULL);
|
||||||
AddCommand(pInter,"MakeCone",
|
AddCommand(pInter,"MakeCone",
|
||||||
MakeCone,NULL,NULL);
|
MakeCone,NULL,NULL);
|
||||||
|
AddCommand(pInter,"MakeMultiCounter",
|
||||||
|
MakeMultiCounter,NULL,NULL);
|
||||||
|
AddCommand(pInter,"MakeSicsPoll",
|
||||||
|
InstallSICSPoll,NULL,NULL);
|
||||||
|
AddCommand(pInter,"MakeStateMon",
|
||||||
|
StateMonFactory,NULL,NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
install site specific commands
|
install site specific commands
|
||||||
@ -396,6 +407,8 @@
|
|||||||
RemoveCommand(pSics,"InstallProtocolHandler");
|
RemoveCommand(pSics,"InstallProtocolHandler");
|
||||||
RemoveCommand(pSics,"InstallSinfox");
|
RemoveCommand(pSics,"InstallSinfox");
|
||||||
RemoveCommand(pSics,"MakeCone");
|
RemoveCommand(pSics,"MakeCone");
|
||||||
|
RemoveCommand(pSics,"MakeMultiCounter");
|
||||||
|
RemoveCommand(pSics,"MakeStateMon");
|
||||||
/*
|
/*
|
||||||
remove site specific installation commands
|
remove site specific installation commands
|
||||||
*/
|
*/
|
||||||
|
76
optimise.c
76
optimise.c
@ -519,38 +519,13 @@ static int ClimbDrive(SConnection *pCon,char *name, float value)
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
static int ClimbVariable(pOptimise self, SConnection *pCon, int i)
|
static int findDirection(pOptimise self, pOVarEntry pOvar, SConnection *pCon)
|
||||||
{
|
{
|
||||||
pOVarEntry pOvar;
|
int status, direction;
|
||||||
void *pData;
|
float varValue;
|
||||||
int status, direction = 1;
|
long oneCount, twoCount;
|
||||||
long oneCount, twoCount, lastCount, currentCount;
|
|
||||||
float varValue, startValue;
|
|
||||||
char buffer[256];
|
|
||||||
int (*CollectFunc)(pScanData self, int iPoint) = NULL;
|
|
||||||
|
|
||||||
assert(self);
|
|
||||||
assert( (i >= 0) && (i < self->iVar));
|
|
||||||
assert(pCon);
|
|
||||||
|
|
||||||
/* get variable data */
|
|
||||||
DynarGet(self->pVariables,i,&pData);
|
|
||||||
pOvar = (pOVarEntry)pData;
|
|
||||||
startValue = pOvar->fCenter;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* prepare scan object
|
|
||||||
*/
|
|
||||||
self->pScanner->pCon = pCon;
|
|
||||||
self->pScanner->pSics = pServ->pSics;
|
|
||||||
self->pScanner->iNP = 1;
|
|
||||||
self->pScanner->iMode = self->eCount;
|
|
||||||
self->pScanner->fPreset = self->fPreset;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* test for upwards direction
|
|
||||||
*/
|
|
||||||
varValue = pOvar->fCenter + pOvar->fStep;
|
varValue = pOvar->fCenter + pOvar->fStep;
|
||||||
status = ClimbDrive(pCon,pOvar->pName,varValue);
|
status = ClimbDrive(pCon,pOvar->pName,varValue);
|
||||||
if(!status)
|
if(!status)
|
||||||
@ -584,14 +559,46 @@ static int ClimbDrive(SConnection *pCon,char *name, float value)
|
|||||||
if(oneCount > twoCount)
|
if(oneCount > twoCount)
|
||||||
{
|
{
|
||||||
direction = 1;
|
direction = 1;
|
||||||
lastCount = oneCount;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
direction = -1;
|
direction = -1;
|
||||||
lastCount = twoCount;
|
|
||||||
}
|
}
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int ClimbVariable(pOptimise self, SConnection *pCon, int i)
|
||||||
|
{
|
||||||
|
pOVarEntry pOvar;
|
||||||
|
void *pData;
|
||||||
|
int status, direction = 1;
|
||||||
|
long oneCount, twoCount, lastCount, currentCount;
|
||||||
|
float varValue, startValue;
|
||||||
|
char buffer[256];
|
||||||
|
int (*CollectFunc)(pScanData self, int iPoint) = NULL;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
assert( (i >= 0) && (i < self->iVar));
|
||||||
|
assert(pCon);
|
||||||
|
|
||||||
|
/* get variable data */
|
||||||
|
DynarGet(self->pVariables,i,&pData);
|
||||||
|
pOvar = (pOVarEntry)pData;
|
||||||
|
startValue = pOvar->fCenter;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* prepare scan object
|
||||||
|
*/
|
||||||
|
self->pScanner->pCon = pCon;
|
||||||
|
self->pScanner->pSics = pServ->pSics;
|
||||||
|
self->pScanner->iNP = 1;
|
||||||
|
self->pScanner->iMode = self->eCount;
|
||||||
|
self->pScanner->fPreset = self->fPreset;
|
||||||
|
|
||||||
|
direction = findDirection(self,pOvar, pCon);
|
||||||
|
if(direction < -1){
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* drive to the last best position
|
* drive to the last best position
|
||||||
*/
|
*/
|
||||||
@ -601,6 +608,11 @@ static int ClimbDrive(SConnection *pCon,char *name, float value)
|
|||||||
{
|
{
|
||||||
return DRIVEERROR;
|
return DRIVEERROR;
|
||||||
}
|
}
|
||||||
|
lastCount = ClimbCount(self,pCon);
|
||||||
|
if(lastCount < 0)
|
||||||
|
{
|
||||||
|
return SCANERROR;
|
||||||
|
}
|
||||||
currentCount = lastCount;
|
currentCount = lastCount;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
"warning",
|
"warning",
|
||||||
"error",
|
"error",
|
||||||
"hdb",
|
"hdb",
|
||||||
|
"hdbEvent",
|
||||||
NULL };
|
NULL };
|
||||||
static int iNoCodes = 11;
|
static int iNoCodes = 13;
|
||||||
#endif
|
#endif
|
||||||
|
97
polldriv.c
Normal file
97
polldriv.c
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
* This is the sister module to sicspoll which defines the drivers for the
|
||||||
|
* various modes of polling SICS objects.
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke, November-December 2006
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sics.h>
|
||||||
|
#include <splitter.h>
|
||||||
|
|
||||||
|
#include "polldriv.h"
|
||||||
|
#include "splitter.h"
|
||||||
|
#include "sicshipadaba.h"
|
||||||
|
/*================ actual driver implementation =========================*/
|
||||||
|
static int timeDue(struct __POLLDRIV *self, time_t now, SConnection *pCon){
|
||||||
|
if(now > self->nextPoll){
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*------------------ HDB Driver -----------------------------------------*/
|
||||||
|
static int pollHdb(struct __POLLDRIV *self, SConnection *pCon){
|
||||||
|
hdbValue old, newVal;
|
||||||
|
pHdb node = NULL;
|
||||||
|
|
||||||
|
memset(&old,0,sizeof(hdbValue));
|
||||||
|
memset(&newVal,0,sizeof(hdbValue));
|
||||||
|
node = (pHdb)self->objPointer;
|
||||||
|
assert(node != NULL);
|
||||||
|
old = node->value;
|
||||||
|
self->nextPoll = time(NULL) + self->pollIntervall;
|
||||||
|
if(GetHipadabaPar(node, &newVal, pCon) == 1){
|
||||||
|
if(!compareHdbValue(old,newVal)){
|
||||||
|
UpdateHipadabaPar(node,newVal,pCon);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static pPollDriv makeHdbDriver(SConnection *pCon, char *objectIdentifier,
|
||||||
|
int argc, char *argv[]){
|
||||||
|
pHdb root = NULL, node = NULL;
|
||||||
|
pPollDriv pNew = NULL;
|
||||||
|
|
||||||
|
root = GetHipadabaRoot();
|
||||||
|
assert(root != NULL);
|
||||||
|
node = GetHipadabaNode(root,objectIdentifier);
|
||||||
|
if(node == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: object to poll not found",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pNew = malloc(sizeof(PollDriv));
|
||||||
|
if(pNew == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(pNew,0,sizeof(PollDriv));
|
||||||
|
|
||||||
|
|
||||||
|
pNew->objectIdentifier = strdup(objectIdentifier);
|
||||||
|
pNew->objPointer = node;
|
||||||
|
pNew->isDue = timeDue;
|
||||||
|
pNew->poll = pollHdb;
|
||||||
|
|
||||||
|
if(argc > 0){
|
||||||
|
pNew->pollIntervall = atoi(argv[0]);
|
||||||
|
} else {
|
||||||
|
pNew->pollIntervall = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pNew;
|
||||||
|
}
|
||||||
|
/*================ external interface ====================================*/
|
||||||
|
pPollDriv makePollDriver(SConnection *pCon, char *driver,
|
||||||
|
char *objectIdentifier, int argc, char *argv[]){
|
||||||
|
|
||||||
|
strtolower(driver);
|
||||||
|
if(strcmp(driver,"hdb") == 0) {
|
||||||
|
return makeHdbDriver(pCon,objectIdentifier, argc, argv);
|
||||||
|
} else {
|
||||||
|
SCWrite(pCon,"ERROR: polling driver type unknown",eError);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
void deletePollDriv(pPollDriv self){
|
||||||
|
if(self->objectIdentifier != NULL){
|
||||||
|
free(self->objectIdentifier);
|
||||||
|
}
|
||||||
|
free(self);
|
||||||
|
}
|
42
polldriv.h
Normal file
42
polldriv.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* This is the sister module to sicspoll which defines the drivers for the
|
||||||
|
* various modes of polling SICS objects.
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke, November-December 2006
|
||||||
|
*/
|
||||||
|
#ifndef POLLDRIV_H_
|
||||||
|
#define POLLDRIV_H_
|
||||||
|
#include <time.h>
|
||||||
|
#include <sics.h>
|
||||||
|
/*==================== a data structure ===================================*/
|
||||||
|
typedef struct __POLLDRIV{
|
||||||
|
char *objectIdentifier; /* the object identifier */
|
||||||
|
void *objPointer; /* a pointer to the object */
|
||||||
|
time_t nextPoll; /* next polling time */
|
||||||
|
int pollIntervall; /* poll intervall */
|
||||||
|
int (*isDue)(struct __POLLDRIV *self, time_t now, SConnection *pCon);
|
||||||
|
/* function called to determine if this object must be polled */
|
||||||
|
int (*poll)(struct __POLLDRIV *self, SConnection *pCon);
|
||||||
|
/* the actual polling function */
|
||||||
|
}PollDriv, *pPollDriv;
|
||||||
|
/*==================== the interface =====================================*/
|
||||||
|
/*
|
||||||
|
* make a poll driver
|
||||||
|
* @param pCon A connection to report errors too
|
||||||
|
* @param driver the driver type to generate
|
||||||
|
* @param objectIdentifier An identifer for the object to poll
|
||||||
|
* @param argc number of additional parameter
|
||||||
|
* @param *argv[] Additional parameters.
|
||||||
|
* @return NULL on failure or a PollDriv strucure else.
|
||||||
|
*/
|
||||||
|
pPollDriv makePollDriver(SConnection *pCon, char *driver,
|
||||||
|
char *objectIdentifier, int argc, char *argv[]);
|
||||||
|
/**
|
||||||
|
* free all memory associated with this poll driver
|
||||||
|
* @param self The structure to delete
|
||||||
|
*/
|
||||||
|
void deletePollDriv(pPollDriv self);
|
||||||
|
|
||||||
|
#endif /*POLLDRIV_H_*/
|
88
polldriv.tc
Normal file
88
polldriv.tc
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/**
|
||||||
|
* This is the sister module to sicspoll which defines the drivers for the
|
||||||
|
* various modes of polling SICS objects.
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke, November-December 2006
|
||||||
|
*/
|
||||||
|
<%! source sicstemplates.tcl %>
|
||||||
|
<% stdIncludes %>
|
||||||
|
#include "polldriv.h"
|
||||||
|
#include "splitter.h"
|
||||||
|
#include "sicshipadaba.h"
|
||||||
|
/*================ actual driver implementation =========================*/
|
||||||
|
static int timeDue(struct __POLLDRIV *self, time_t now, SConnection *pCon){
|
||||||
|
if(now > self->nextPoll){
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*------------------ HDB Driver -----------------------------------------*/
|
||||||
|
static int pollHdb(struct __POLLDRIV *self, SConnection *pCon){
|
||||||
|
hdbValue old, newVal;
|
||||||
|
pHdb node = NULL;
|
||||||
|
|
||||||
|
memset(&old,0,sizeof(hdbValue));
|
||||||
|
memset(&newVal,0,sizeof(hdbValue));
|
||||||
|
node = (pHdb)self->objPointer;
|
||||||
|
assert(node != NULL);
|
||||||
|
old = node->value;
|
||||||
|
self->nextPoll = time(NULL) + self->pollIntervall;
|
||||||
|
if(GetHipadabaPar(node, &newVal, pCon) == 1){
|
||||||
|
if(!compareHdbValue(old,newVal)){
|
||||||
|
UpdateHipadabaPar(node,newVal,pCon);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static pPollDriv makeHdbDriver(SConnection *pCon, char *objectIdentifier,
|
||||||
|
int argc, char *argv[]){
|
||||||
|
pHdb root = NULL, node = NULL;
|
||||||
|
pPollDriv pNew = NULL;
|
||||||
|
|
||||||
|
root = GetHipadabaRoot();
|
||||||
|
assert(root != NULL);
|
||||||
|
node = GetHipadabaNode(root,objectIdentifier);
|
||||||
|
if(node == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: object to poll not found",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
<%newStruc PollDriv 5 %>
|
||||||
|
|
||||||
|
pNew->objectIdentifier = strdup(objectIdentifier);
|
||||||
|
pNew->objPointer = node;
|
||||||
|
pNew->isDue = timeDue;
|
||||||
|
pNew->poll = pollHdb;
|
||||||
|
|
||||||
|
if(argc > 0){
|
||||||
|
pNew->pollIntervall = atoi(argv[0]);
|
||||||
|
} else {
|
||||||
|
pNew->pollIntervall = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pNew;
|
||||||
|
}
|
||||||
|
/*================ external interface ====================================*/
|
||||||
|
pPollDriv makePollDriver(SConnection *pCon, char *driver,
|
||||||
|
char *objectIdentifier, int argc, char *argv[]){
|
||||||
|
|
||||||
|
strtolower(driver);
|
||||||
|
if(strcmp(driver,"hdb") == 0) {
|
||||||
|
return makeHdbDriver(pCon,objectIdentifier, argc, argv);
|
||||||
|
} else {
|
||||||
|
SCWrite(pCon,"ERROR: polling driver type unknown",eError);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
void deletePollDriv(pPollDriv self){
|
||||||
|
if(self->objectIdentifier != NULL){
|
||||||
|
free(self->objectIdentifier);
|
||||||
|
}
|
||||||
|
free(self);
|
||||||
|
}
|
77
protocol.c
77
protocol.c
@ -16,7 +16,7 @@
|
|||||||
#include <dynstring.h>
|
#include <dynstring.h>
|
||||||
#include "commandlog.h"
|
#include "commandlog.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "json.h"
|
#include <json/json.h>
|
||||||
|
|
||||||
#define MAXMSG 1024
|
#define MAXMSG 1024
|
||||||
#define INIT_STR_SIZE 256
|
#define INIT_STR_SIZE 256
|
||||||
@ -87,8 +87,6 @@ pProtocol CreateProtocol(void);
|
|||||||
static int ProtocolOptions(SConnection* pCon, pProtocol pPro);
|
static int ProtocolOptions(SConnection* pCon, pProtocol pPro);
|
||||||
static int ProtocolHelp(SConnection* pCon, Protocol* pPro);
|
static int ProtocolHelp(SConnection* pCon, Protocol* pPro);
|
||||||
static int ProtocolSet(SConnection* pCon, Protocol* pPro, char *pProName);
|
static int ProtocolSet(SConnection* pCon, Protocol* pPro, char *pProName);
|
||||||
static int ProtocolGet(SConnection* pCon, Protocol* pPro, char *pProName,
|
|
||||||
int *pIndex);
|
|
||||||
static int ProtocolList(SConnection* pCon, Protocol* pPro);
|
static int ProtocolList(SConnection* pCon, Protocol* pPro);
|
||||||
int ProtocolAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
int ProtocolAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
@ -294,9 +292,10 @@ static int ProtocolSet(SConnection* pCon, Protocol* pPro, char *pProName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
static int ProtocolGet(SConnection* pCon, Protocol* pPro, char *pProName,
|
int ProtocolGet(SConnection* pCon, void* pData, char *pProName, int len)
|
||||||
int *pIndex)
|
|
||||||
{
|
{
|
||||||
|
int Index;
|
||||||
|
Protocol *pPro = (Protocol *)pData;
|
||||||
if(!SCVerifyConnection(pCon))
|
if(!SCVerifyConnection(pCon))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -309,24 +308,27 @@ static int ProtocolGet(SConnection* pCon, Protocol* pPro, char *pProName,
|
|||||||
pPro->isDefaultSet = 1;
|
pPro->isDefaultSet = 1;
|
||||||
pCon->iProtocolID = 0;
|
pCon->iProtocolID = 0;
|
||||||
}
|
}
|
||||||
|
strncpy(pProName, pPro->pProList[pCon->iProtocolID], len);
|
||||||
*pIndex = (int)malloc(sizeof(int));
|
return 1;
|
||||||
*pIndex = pCon->iProtocolID;
|
#if 0
|
||||||
|
Index = pCon->iProtocolID;
|
||||||
|
|
||||||
/* check list of protocols for valid name */
|
/* check list of protocols for valid name */
|
||||||
switch(*pIndex)
|
switch(Index)
|
||||||
{
|
{
|
||||||
case 0: /* default = psi_sics */
|
case 0: /* default = psi_sics */
|
||||||
case 1: /* normal (connection start default) */
|
case 1: /* normal (connection start default) */
|
||||||
case 2: /* outcodes */
|
case 2: /* outcodes */
|
||||||
case 3: /* sycamore */
|
case 3: /* sycamore */
|
||||||
pProName = strdup(pPro->pProList[*pIndex]);
|
case 4: /* json */
|
||||||
|
pProName = pPro->pProList[Index];
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
@ -632,42 +634,43 @@ struct json_object *mkJSON_Object(SConnection *pCon, char *pBuffer, int iOut)
|
|||||||
json_object_object_add(msg_json, "flag", json_object_new_string(pCode[iOut]));
|
json_object_object_add(msg_json, "flag", json_object_new_string(pCode[iOut]));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (iOut == eHdb) {
|
if (iOut == eHdbValue || iOut == eHdbEvent) {
|
||||||
tmp_json = json_tokener_parse(pBuffer);
|
tmp_json = json_tokener_parse(pBuffer);
|
||||||
if (is_error(msg_json)) { linenum = __LINE__; goto reporterr; }
|
if (is_error(tmp_json)) { linenum = __LINE__; goto reporterr; }
|
||||||
} else {
|
} else {
|
||||||
/* Strip \r and \n */
|
/* Strip \r and \n */
|
||||||
for (pBufferFrom=pBufferTo=pBuffer; ; pBufferFrom++) {
|
for (pBufferFrom=pBufferTo=pBuffer; ; pBufferFrom++) {
|
||||||
if (*pBufferFrom == '\r' || *pBufferFrom == '\n')
|
if (*pBufferFrom == '\r' || *pBufferFrom == '\n')
|
||||||
continue;
|
continue;
|
||||||
*pBufferTo = *pBufferFrom;
|
pBufferTo = pBufferFrom;
|
||||||
if (*pBufferTo == '\0')
|
if (*pBufferTo == '\0')
|
||||||
break;
|
break;
|
||||||
pBufferTo++;
|
pBufferTo++;
|
||||||
}
|
}
|
||||||
tmp_json = json_object_new_string(pBuffer);
|
tmp_json = json_object_new_string(pBuffer);
|
||||||
if (is_error(msg_json)) { linenum = __LINE__; goto reporterr; }
|
if (is_error(tmp_json)) { linenum = __LINE__; goto reporterr; }
|
||||||
}
|
}
|
||||||
json_object_object_add(msg_json, "data", tmp_json);
|
json_object_object_add(msg_json, "data", tmp_json);
|
||||||
return msg_json;
|
return msg_json;
|
||||||
|
|
||||||
reporterr:
|
reporterr:
|
||||||
SCSetWriteFunc(pCon,SCNormalWrite);
|
SCSetWriteFunc(pCon,SCNormalWrite);
|
||||||
snprintf(pError, 256,"%s:%d Error making json object", __FILE__, linenum);
|
snprintf(pError, 256,"{\"ERROR\": \"%s:%d Error making json object\"}", __FILE__, linenum);
|
||||||
SCWrite(pCon,pError,eError);
|
SCWrite(pCon,pError,eError);
|
||||||
|
SCSetWriteFunc(pCon,SCWriteJSON_String);
|
||||||
cleanup:
|
cleanup:
|
||||||
if (tmp_json != NULL)
|
if (tmp_json != NULL && !is_error(tmp_json))
|
||||||
json_object_put(tmp_json);
|
json_object_put(tmp_json);
|
||||||
if (msg_json != NULL)
|
if (msg_json != NULL && !is_error(msg_json))
|
||||||
json_object_put(msg_json);
|
json_object_put(msg_json);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SCWriteJSON_String(SConnection *pCon, char *pBuffer, int iOut)
|
int SCWriteJSON_String(SConnection *pCon, char *pBuffer, int iOut)
|
||||||
{
|
{
|
||||||
struct json_object *my_object=NULL;
|
struct json_object *my_object=NULL, *tmp_json=NULL;
|
||||||
char pBueffel[MAXMSG];
|
char pBueffel[MAXMSG], errBuff[MAXMSG];
|
||||||
int iRet;
|
int iRet, errLen = MAXMSG;
|
||||||
|
|
||||||
if (strlen(pBuffer) == 0)
|
if (strlen(pBuffer) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
@ -687,22 +690,49 @@ int SCWriteJSON_String(SConnection *pCon, char *pBuffer, int iOut)
|
|||||||
|
|
||||||
/* write to commandlog if user or manager privilege */
|
/* write to commandlog if user or manager privilege */
|
||||||
if(SCGetRights(pCon) <= usUser)
|
if(SCGetRights(pCon) <= usUser)
|
||||||
|
{
|
||||||
|
if(pCon->iMacro != 1)
|
||||||
{
|
{
|
||||||
sprintf(pBueffel,"To sock %d :",iRet);
|
sprintf(pBueffel,"To sock %d :",iRet);
|
||||||
WriteToCommandLog(pBueffel,pBuffer);
|
WriteToCommandLog(pBueffel,pBuffer);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(iOut == eError || iOut == eWarning)
|
||||||
|
{
|
||||||
|
sprintf(pBueffel,"To sock %d :",iRet);
|
||||||
|
WriteToCommandLog(pBueffel,pBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(SCinMacro(pCon))
|
if(SCinMacro(pCon))
|
||||||
{
|
{
|
||||||
InterpWrite(pServ->pSics,pBuffer);
|
InterpWrite(pServ->pSics,pBuffer);
|
||||||
|
/* print it to client if error message */
|
||||||
|
if((iOut== eError) || (iOut == eWarning) )
|
||||||
|
{
|
||||||
|
tmp_json = json_object_new_string(pBuffer);
|
||||||
|
iRet = SCDoSockWrite(pCon,json_object_to_json_string(tmp_json));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((my_object = mkJSON_Object(pCon, pBuffer, iOut)) == NULL) {
|
||||||
|
snprintf(errBuff, errLen, "failed to make JSON object from, %s", pBuffer);
|
||||||
|
tmp_json = json_object_new_string(errBuff);
|
||||||
|
my_object = json_object_new_object();
|
||||||
|
json_object_object_add(my_object, "ERROR", tmp_json);
|
||||||
|
SCDoSockWrite(pCon,json_object_to_json_string(my_object));
|
||||||
|
iRet = 0;
|
||||||
} else {
|
} else {
|
||||||
my_object = mkJSON_Object(pCon, pBuffer, iOut);
|
|
||||||
iRet = SCDoSockWrite(pCon,json_object_to_json_string(my_object));
|
iRet = SCDoSockWrite(pCon,json_object_to_json_string(my_object));
|
||||||
SCWriteToLogFiles(pCon,pBuffer);
|
SCWriteToLogFiles(pCon,pBuffer);
|
||||||
}
|
}
|
||||||
if (my_object != NULL)
|
}
|
||||||
|
if (tmp_json != NULL && !is_error(tmp_json))
|
||||||
|
json_object_put(tmp_json);
|
||||||
|
if (my_object != NULL && !is_error(my_object))
|
||||||
json_object_put(my_object);
|
json_object_put(my_object);
|
||||||
return 1;
|
return iRet;
|
||||||
}
|
}
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Protocol API */
|
/* Protocol API */
|
||||||
@ -731,6 +761,7 @@ char * GetProtocolName(SConnection* pCon)
|
|||||||
case 1: /* normal (connection start default) */
|
case 1: /* normal (connection start default) */
|
||||||
case 2: /* outcodes */
|
case 2: /* outcodes */
|
||||||
case 3: /* sycamore */
|
case 3: /* sycamore */
|
||||||
|
case 4: /* json */
|
||||||
return strdup(pPro->pProList[pCon->iProtocolID]);
|
return strdup(pPro->pProList[pCon->iProtocolID]);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -30,5 +30,6 @@ int SCWriteSycamore(SConnection *pCon, char *pBuffer, int iOut);
|
|||||||
/*--------------------- implement protocol API -----------------------*/
|
/*--------------------- implement protocol API -----------------------*/
|
||||||
char * GetProtocolName(SConnection *pCon);
|
char * GetProtocolName(SConnection *pCon);
|
||||||
int GetProtocolID(SConnection *pCon);
|
int GetProtocolID(SConnection *pCon);
|
||||||
|
int ProtocolGet(SConnection* pCon, void* pData, char *pProName, int len);
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
#endif
|
#endif
|
||||||
|
262
regresscter.c
Normal file
262
regresscter.c
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
/*--------------------------------------------------------------------------
|
||||||
|
This is a counter for use in automated regression tests.
|
||||||
|
|
||||||
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, September 2006
|
||||||
|
----------------------------------------------------------------------------*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include "fortify.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "sics.h"
|
||||||
|
#include "countdriv.h"
|
||||||
|
/*---------------------------------- possible error types ------------------*/
|
||||||
|
#define NONE 0
|
||||||
|
#define STARTFAIL 1
|
||||||
|
#define STATUSFAIL 2
|
||||||
|
#define PAUSEFAIL 3
|
||||||
|
#define CONTFAIL 4
|
||||||
|
#define READFAIL 5
|
||||||
|
|
||||||
|
#define STATEIDLE 0
|
||||||
|
#define STATERUN 1
|
||||||
|
#define STATEPAU 2
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
typedef struct {
|
||||||
|
int errType;
|
||||||
|
int recover;
|
||||||
|
int state;
|
||||||
|
time_t endTime;
|
||||||
|
} RegressSt;
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int RegressGetStatus(struct __COUNTER *self, float *fControl){
|
||||||
|
RegressSt *pSim = NULL;
|
||||||
|
time_t tD, tDe;
|
||||||
|
int iRun;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
pSim = (RegressSt *) self->pData;
|
||||||
|
assert(pSim);
|
||||||
|
|
||||||
|
if(pSim->errType == STATUSFAIL){
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
if(time(NULL) > pSim->endTime){
|
||||||
|
pSim->state = STATEIDLE;
|
||||||
|
}
|
||||||
|
switch(pSim->state){
|
||||||
|
case STATEIDLE:
|
||||||
|
return HWIdle;
|
||||||
|
break;
|
||||||
|
case STATERUN:
|
||||||
|
return HWBusy;
|
||||||
|
break;
|
||||||
|
case STATEPAU:
|
||||||
|
return HWPause;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert(0);
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int RegressStart(struct __COUNTER *self){
|
||||||
|
RegressSt *pSim = NULL;
|
||||||
|
time_t tD;
|
||||||
|
int iRun;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
pSim = (RegressSt *) self->pData;
|
||||||
|
assert(pSim);
|
||||||
|
|
||||||
|
if(pSim->errType == STARTFAIL){
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
pSim->state = STATERUN;
|
||||||
|
if(self->eMode == eTimer){
|
||||||
|
pSim->endTime = time(NULL) + (int)self->fPreset;
|
||||||
|
} else {
|
||||||
|
pSim->endTime = time(NULL) + 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int RegressPause(struct __COUNTER *self){
|
||||||
|
RegressSt *pSim = NULL;
|
||||||
|
time_t tD;
|
||||||
|
int iRun;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
pSim = (RegressSt *) self->pData;
|
||||||
|
assert(pSim);
|
||||||
|
|
||||||
|
if(pSim->errType == PAUSEFAIL){
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
|
||||||
|
pSim->state = STATEPAU;
|
||||||
|
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int RegressContinue(struct __COUNTER *self){
|
||||||
|
RegressSt *pSim = NULL;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
pSim = (RegressSt *) self->pData;
|
||||||
|
assert(pSim);
|
||||||
|
|
||||||
|
if(pSim->errType == CONTFAIL){
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
|
||||||
|
pSim->state = STATERUN;
|
||||||
|
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int RegressHalt(struct __COUNTER *self){
|
||||||
|
RegressSt *pSim = NULL;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
pSim = (RegressSt *) self->pData;
|
||||||
|
assert(pSim);
|
||||||
|
|
||||||
|
pSim->state = STATEIDLE;
|
||||||
|
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int RegressReadValues(struct __COUNTER *self){
|
||||||
|
RegressSt *pSim = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
pSim = (RegressSt *) self->pData;
|
||||||
|
assert(pSim);
|
||||||
|
|
||||||
|
if(pSim->errType == READFAIL){
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < MAXCOUNT; i++) {
|
||||||
|
self->lCounts[i] = i*10+5;
|
||||||
|
}
|
||||||
|
self->lCounts[1] = self->fPreset;
|
||||||
|
self->fTime = self->fPreset;
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
static int RegressGetError(struct __COUNTER *self, int *iCode, char *error,
|
||||||
|
int iErrLen){
|
||||||
|
strncpy(error, "Regression counter error", iErrLen);
|
||||||
|
*iCode = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int RegressTryAndFixIt(struct __COUNTER *self, int iCode){
|
||||||
|
RegressSt *pSim = NULL;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
pSim = (RegressSt *) self->pData;
|
||||||
|
assert(pSim);
|
||||||
|
|
||||||
|
if(pSim->recover == 1){
|
||||||
|
pSim->errType = NONE;
|
||||||
|
return COREDO;
|
||||||
|
} else {
|
||||||
|
return COTERM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int RegressSet(struct __COUNTER *self, char *name, int iCter, float FVal){
|
||||||
|
RegressSt *pSim = NULL;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
pSim = (RegressSt *) self->pData;
|
||||||
|
assert(pSim);
|
||||||
|
|
||||||
|
if(strcmp(name,"errortype") == 0){
|
||||||
|
pSim->errType = (int)FVal;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(strcmp(name,"recover") == 0){
|
||||||
|
pSim->recover = (int)FVal;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(strcmp(name,"finish") == 0){
|
||||||
|
pSim->state = STATEIDLE;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int RegressGet(struct __COUNTER *self, char *name,
|
||||||
|
int iCter, float *fVal){
|
||||||
|
RegressSt *pSim = NULL;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
pSim = (RegressSt *) self->pData;
|
||||||
|
assert(pSim);
|
||||||
|
|
||||||
|
if(strcmp(name,"errortype") == 0){
|
||||||
|
*fVal = pSim->errType;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(strcmp(name,"recover") == 0){
|
||||||
|
*fVal = pSim->recover;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
static int RegressSend(struct __COUNTER *self, char *pText,
|
||||||
|
char *pReply, int iReplyLen){
|
||||||
|
strncpy(pReply, "Simulated response", iReplyLen);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
pCounterDriver NewRegressCounter(char *name){
|
||||||
|
pCounterDriver pRes = NULL;
|
||||||
|
RegressSt *pData = NULL;
|
||||||
|
int iRet;
|
||||||
|
int iC1, iC2, iC3;
|
||||||
|
char *pErr;
|
||||||
|
char pBueffel[132];
|
||||||
|
|
||||||
|
pRes = CreateCounterDriver(name, "Regress");
|
||||||
|
if (!pRes) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pData = (RegressSt *) malloc(sizeof(RegressSt));
|
||||||
|
if (!pData) {
|
||||||
|
DeleteCounterDriver(pRes);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(pData,0,sizeof(RegressSt));
|
||||||
|
pRes->pData = pData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* assign functions
|
||||||
|
*/
|
||||||
|
pRes->GetStatus = RegressGetStatus;
|
||||||
|
pRes->Start = RegressStart;
|
||||||
|
pRes->Halt = RegressHalt;
|
||||||
|
pRes->ReadValues = RegressReadValues;
|
||||||
|
pRes->GetError = RegressGetError;
|
||||||
|
pRes->TryAndFixIt = RegressTryAndFixIt;
|
||||||
|
pRes->Pause = RegressPause;
|
||||||
|
pRes->Continue = RegressContinue;
|
||||||
|
pRes->Set = RegressSet;
|
||||||
|
pRes->Get = RegressGet;
|
||||||
|
pRes->Send = RegressSend;
|
||||||
|
pRes->KillPrivate = NULL;
|
||||||
|
pRes->iNoOfMonitors = 8;
|
||||||
|
|
||||||
|
return pRes;
|
||||||
|
}
|
7
remob.c
7
remob.c
@ -19,6 +19,7 @@ M. Zolliker July 04
|
|||||||
#include "status.h"
|
#include "status.h"
|
||||||
#include "servlog.h"
|
#include "servlog.h"
|
||||||
#include "site.h"
|
#include "site.h"
|
||||||
|
#include "commandlog.h"
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
#define INTERRUPTMODE 0
|
#define INTERRUPTMODE 0
|
||||||
#define ACCESSCODE 1
|
#define ACCESSCODE 1
|
||||||
@ -242,8 +243,10 @@ static int RemServerTask(void *data) {
|
|||||||
rc = &remserver->rc[isUser];
|
rc = &remserver->rc[isUser];
|
||||||
if (RemRead(rc, 0) <= 0) continue;
|
if (RemRead(rc, 0) <= 0) continue;
|
||||||
|
|
||||||
/* printf("< %s\n", buf); */
|
if (strstr(rc->line, " ") == rc->line) {
|
||||||
|
WriteToCommandLog("REMOB>", "infinite echo loop detected");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (isUser == 0) {
|
if (isUser == 0) {
|
||||||
if (RemHandle(remserver)) { /* handle drivstat messages */
|
if (RemHandle(remserver)) { /* handle drivstat messages */
|
||||||
continue;
|
continue;
|
||||||
|
@ -434,6 +434,42 @@ void getRS232Error(int iCode, char *errorBuffer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
|
int fixRS232Error(prs232 self, int iCode){
|
||||||
|
int i, status, read;
|
||||||
|
char buffer[8192];
|
||||||
|
|
||||||
|
switch(iCode){
|
||||||
|
case BADMEMORY:
|
||||||
|
case FAILEDCONNECT:
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case INCOMPLETE:
|
||||||
|
case TIMEOUT:
|
||||||
|
/*
|
||||||
|
* try to clear possibly pending stuff
|
||||||
|
*/
|
||||||
|
for(i = 0; i < 3; i++){
|
||||||
|
if(availableRS232(self)){
|
||||||
|
read = 8192;
|
||||||
|
readRS232(self,buffer,&read);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case NOTCONNECTED:
|
||||||
|
case BADSEND:
|
||||||
|
closeRS232(self);
|
||||||
|
status = initRS232(self);
|
||||||
|
if(status){
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
int getRS232Timeout(prs232 self){
|
int getRS232Timeout(prs232 self){
|
||||||
return self->timeout;
|
return self->timeout;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
|
|
||||||
void getRS232Error(int iCode, char *errorBuffer,
|
void getRS232Error(int iCode, char *errorBuffer,
|
||||||
int errorBufferLen);
|
int errorBufferLen);
|
||||||
|
int fixRS232Error(prs232 self, int iCode);
|
||||||
int getRS232Timeout(prs232 self);
|
int getRS232Timeout(prs232 self);
|
||||||
int initRS232(prs232 self);
|
int initRS232(prs232 self);
|
||||||
int initRS232WithFlags(prs232 self, int flags);
|
int initRS232WithFlags(prs232 self, int flags);
|
||||||
|
19
scan.c
19
scan.c
@ -385,6 +385,7 @@ int AppendScanLine(pScanData self, char *line)
|
|||||||
}
|
}
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
extern char *stptok(const char *s, char *t, int len, char *brk);
|
extern char *stptok(const char *s, char *t, int len, char *brk);
|
||||||
|
extern char *trim(char *txt);
|
||||||
|
|
||||||
int StoreScanCounts(pScanData self, char *data)
|
int StoreScanCounts(pScanData self, char *data)
|
||||||
{
|
{
|
||||||
@ -402,7 +403,7 @@ int StoreScanCounts(pScanData self, char *data)
|
|||||||
InitCountEntry(&sCount);
|
InitCountEntry(&sCount);
|
||||||
|
|
||||||
/* parse the data */
|
/* parse the data */
|
||||||
pPtr = data;
|
pPtr = trim(data);
|
||||||
pPtr = stptok(pPtr,pNumber,29," \t");
|
pPtr = stptok(pPtr,pNumber,29," \t");
|
||||||
if(pPtr != NULL)
|
if(pPtr != NULL)
|
||||||
{
|
{
|
||||||
@ -1584,7 +1585,7 @@ static int PrintTimes(pScanData self, SConnection *pCon,
|
|||||||
|
|
||||||
snprintf(pBueffel,59,"%s.scantimes = { ",name);
|
snprintf(pBueffel,59,"%s.scantimes = { ",name);
|
||||||
DynStringCopy(data,pBueffel);
|
DynStringCopy(data,pBueffel);
|
||||||
for(i = 0; i < self->iNP; i++)
|
for(i = 0; i < self->iCounts; i++)
|
||||||
{
|
{
|
||||||
DynarGet(self->pCounts,i,&pPtr);
|
DynarGet(self->pCounts,i,&pPtr);
|
||||||
pData = (pCountEntry)pPtr;
|
pData = (pCountEntry)pPtr;
|
||||||
@ -2414,6 +2415,20 @@ static int DumpScan(pScanData self, SConnection *pCon)
|
|||||||
}
|
}
|
||||||
return AppendVarPos(pCon,self,i,(float)fStep);
|
return AppendVarPos(pCon,self,i,(float)fStep);
|
||||||
}
|
}
|
||||||
|
else if(strcmp(argv[1],"softpos") == 0){
|
||||||
|
if(argc > 2) {
|
||||||
|
if(!SCMatchRights(pCon,usMugger)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->posSoft = atoi(argv[2]);
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
sprintf(pBueffel,"%s.softpos = %d", argv[0],self->posSoft);
|
||||||
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
/*------- savecounter */
|
/*------- savecounter */
|
||||||
else if(strcmp(argv[1],"savecounter") == 0)
|
else if(strcmp(argv[1],"savecounter") == 0)
|
||||||
{
|
{
|
||||||
|
2
sics.h
2
sics.h
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
/* the following line suppresses const declarations in tcl.h.
|
/* the following line suppresses const declarations in tcl.h.
|
||||||
-> makes the compiler happy M.Z. */
|
-> makes the compiler happy M.Z. */
|
||||||
#define NO_CONST
|
/* #define NO_CONST */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
34
sicscron.c
34
sicscron.c
@ -11,7 +11,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <tcl.h>
|
#include "macro.h"
|
||||||
#include "fortify.h"
|
#include "fortify.h"
|
||||||
#include "sics.h"
|
#include "sics.h"
|
||||||
#include "splitter.h"
|
#include "splitter.h"
|
||||||
@ -24,6 +24,7 @@
|
|||||||
char *pCommand;
|
char *pCommand;
|
||||||
SConnection *pCon;
|
SConnection *pCon;
|
||||||
int iEnd;
|
int iEnd;
|
||||||
|
Statistics *stat;
|
||||||
} Cron, *pCron;
|
} Cron, *pCron;
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
@ -43,12 +44,19 @@
|
|||||||
{
|
{
|
||||||
SCDeleteConnection(self->pCon);
|
SCDeleteConnection(self->pCon);
|
||||||
}
|
}
|
||||||
|
if (self->stat) {
|
||||||
|
StatisticsKill(self->stat);
|
||||||
|
}
|
||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
static int CronTask(void *pData)
|
static int CronTask(void *pData)
|
||||||
{
|
{
|
||||||
|
Statistics *old;
|
||||||
|
|
||||||
pCron self = (pCron)pData;
|
pCron self = (pCron)pData;
|
||||||
|
int iRet;
|
||||||
|
Tcl_Interp *pTcl = pServ->pSics->pTcl;
|
||||||
|
|
||||||
if(!self)
|
if(!self)
|
||||||
{
|
{
|
||||||
@ -57,7 +65,17 @@
|
|||||||
|
|
||||||
if(time(NULL) > self->tNext)
|
if(time(NULL) > self->tNext)
|
||||||
{
|
{
|
||||||
SCInvoke(self->pCon,pServ->pSics,self->pCommand);
|
MacroPush(self->pCon);
|
||||||
|
old=StatisticsBegin(self->stat);
|
||||||
|
iRet = Tcl_Eval(pTcl,self->pCommand);
|
||||||
|
StatisticsEnd(old);
|
||||||
|
MacroPop();
|
||||||
|
if (iRet != TCL_OK) {
|
||||||
|
SCPrintf(self->pCon, eStatus,
|
||||||
|
"ERROR in sicscron script: %s", pTcl->result);
|
||||||
|
self->iEnd = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
self->tNext = time(NULL) + self->iIntervall;
|
self->tNext = time(NULL) + self->iIntervall;
|
||||||
}
|
}
|
||||||
return self->iEnd;
|
return self->iEnd;
|
||||||
@ -82,11 +100,11 @@
|
|||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
{
|
{
|
||||||
pCron pNew = NULL;
|
pCron pNew = NULL;
|
||||||
int iVal, iRet;
|
int iVal, iRet, rights;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
|
|
||||||
/* only managers may do this */
|
/* need user priv. */
|
||||||
if(!SCMatchRights(pCon,usMugger))
|
if(!SCMatchRights(pCon,usUser))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -123,10 +141,16 @@
|
|||||||
SCWrite(pCon,"ERROR: out of memory in sicscron",eError);
|
SCWrite(pCon,"ERROR: out of memory in sicscron",eError);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
rights = SCGetRights(pCon);
|
||||||
|
if (rights > usMugger) {
|
||||||
|
/* transfer the rights to the dummy connection */
|
||||||
|
SCSetRights(pNew->pCon, rights);
|
||||||
|
}
|
||||||
pNew->iIntervall = iVal;
|
pNew->iIntervall = iVal;
|
||||||
pNew->pCommand = cmd;
|
pNew->pCommand = cmd;
|
||||||
pNew->tNext = 0;
|
pNew->tNext = 0;
|
||||||
pNew->iEnd = 1;
|
pNew->iEnd = 1;
|
||||||
|
pNew->stat = StatisticsNew(cmd);
|
||||||
|
|
||||||
TaskRegister(pServ->pTasker,
|
TaskRegister(pServ->pTasker,
|
||||||
CronTask,
|
CronTask,
|
||||||
|
160
sicsdata.c
160
sicsdata.c
@ -4,6 +4,8 @@
|
|||||||
An attempt to a generic interface to SICS data for all sorts of SICS
|
An attempt to a generic interface to SICS data for all sorts of SICS
|
||||||
clients.
|
clients.
|
||||||
|
|
||||||
|
WARNING: this code only works when ints and floats are of the same size!
|
||||||
|
|
||||||
copyright: see file COPYRIGHT
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
Mark Koennecke, June 2003
|
Mark Koennecke, June 2003
|
||||||
@ -17,7 +19,7 @@
|
|||||||
#include "scan.h"
|
#include "scan.h"
|
||||||
#include "HistMem.h"
|
#include "HistMem.h"
|
||||||
#include "sicsdata.h"
|
#include "sicsdata.h"
|
||||||
|
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
static void KillSICSData(void *pData){
|
static void KillSICSData(void *pData){
|
||||||
pSICSData self = NULL;
|
pSICSData self = NULL;
|
||||||
@ -60,6 +62,47 @@ pSICSData createSICSData(void){
|
|||||||
pNew->dataUsed = 0;
|
pNew->dataUsed = 0;
|
||||||
return pNew;
|
return pNew;
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int getSICSDataInt(pSICSData self, int pos, int *value){
|
||||||
|
|
||||||
|
if(pos >= self->dataUsed || self->dataType[pos] != INTTYPE){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*value = self->data[pos];
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int getSICSDataFloat(pSICSData self, int pos, float *value){
|
||||||
|
if(pos >= self->dataUsed || self->dataType[pos] != FLOATTYPE){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy(value,&self->data[pos],sizeof(float));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int setSICSDataInt(pSICSData self, int pos, int value){
|
||||||
|
int *idata = NULL;
|
||||||
|
|
||||||
|
idata = getSICSDataPointer(self,0,pos+1);
|
||||||
|
if(idata == NULL){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
idata[pos] = value;
|
||||||
|
self->dataType[pos] = INTTYPE;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
int setSICSDataFloat(pSICSData self, int pos, float value){
|
||||||
|
int *idata = NULL;
|
||||||
|
|
||||||
|
idata = getSICSDataPointer(self,0,pos+1);
|
||||||
|
if(idata == NULL){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memcpy(&idata[pos],&value,sizeof(float));
|
||||||
|
self->dataType[pos] = FLOATTYPE;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/*-------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------*/
|
||||||
int *getSICSDataPointer(pSICSData self, int start, int end){
|
int *getSICSDataPointer(pSICSData self, int start, int end){
|
||||||
int newSize;
|
int newSize;
|
||||||
@ -134,7 +177,7 @@ static void netEncode(pSICSData self){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------*/
|
||||||
static void clearSICSData(pSICSData self){
|
void clearSICSData(pSICSData self){
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
self->dataUsed = 0;
|
self->dataUsed = 0;
|
||||||
@ -236,6 +279,74 @@ static int putFloat(pSICSData self, int argc, char *argv[],
|
|||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
static int getPos(pSICSData self, char *name,
|
||||||
|
SConnection *pCon, int pos){
|
||||||
|
char pBueffel[512];
|
||||||
|
float value;
|
||||||
|
|
||||||
|
if(pos >= self->dataUsed){
|
||||||
|
SCWrite(pCon,"ERROR: requested position out of range",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(self->dataType[pos] == FLOATTYPE){
|
||||||
|
memcpy(&value,&self->data[pos],sizeof(float));
|
||||||
|
snprintf(pBueffel,511,"%s = %f", name, value);
|
||||||
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(self->dataType[pos] == INTTYPE){
|
||||||
|
snprintf(pBueffel,511,"%s = %d", name, self->data[pos]);
|
||||||
|
SCWrite(pCon,pBueffel,eValue);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
static float getDataPos(pSICSData self, int pos){
|
||||||
|
float value;
|
||||||
|
|
||||||
|
assert(pos < self->dataUsed);
|
||||||
|
if(self->dataType[pos] == FLOATTYPE){
|
||||||
|
memcpy(&value,&self->data[pos],sizeof(float));
|
||||||
|
} else {
|
||||||
|
value = (float)self->data[pos];
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
static int divideSicsData(pSICSData self, SicsInterp *pSics,
|
||||||
|
SConnection *pCon, char *name){
|
||||||
|
int i;
|
||||||
|
pSICSData other = NULL;
|
||||||
|
float val, div;
|
||||||
|
|
||||||
|
other = (pSICSData)FindCommandData(pSics,name,"SICSData");
|
||||||
|
if(other == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: requested SICSData object to divide not found",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(other->dataUsed < self->dataUsed){
|
||||||
|
SCWrite(pCon,"ERROR: not enough data in SICSData for division",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for(i = 0; i < self->dataUsed; i++){
|
||||||
|
div = getDataPos(other,i);
|
||||||
|
if(ABS(div) > .00001){
|
||||||
|
val = getDataPos(self,i)/div;
|
||||||
|
} else {
|
||||||
|
val = .0;
|
||||||
|
}
|
||||||
|
if(self->dataType[i] == INTTYPE){
|
||||||
|
self->data[i] = (int)val;
|
||||||
|
} else {
|
||||||
|
memcpy(&self->data[i],&val,sizeof(float));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/*-------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------*/
|
||||||
static int copyScanCounts(pSICSData self, int argc, char *argv[],
|
static int copyScanCounts(pSICSData self, int argc, char *argv[],
|
||||||
SConnection *pCon, SicsInterp *pSics){
|
SConnection *pCon, SicsInterp *pSics){
|
||||||
@ -475,6 +586,35 @@ static int copyHM(pSICSData self, int argc, char *argv[],
|
|||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
static int copyData(pSICSData self,SicsInterp *pSics,
|
||||||
|
SConnection *pCon,int argc, char *argv[]){
|
||||||
|
pSICSData other = NULL;
|
||||||
|
int pos, start, end, i;
|
||||||
|
|
||||||
|
if(argc < 6){
|
||||||
|
SCWrite(pCon,"ERROR: Insufficient number of arguments to copydata",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pos = atoi(argv[2]);
|
||||||
|
start = atoi(argv[4]);
|
||||||
|
end = atoi(argv[5]);
|
||||||
|
if((other = FindCommandData(pSics,argv[3],"SICSData")) == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: invalid SICSData requested",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(start > end || end > other->dataUsed){
|
||||||
|
SCWrite(pCon,"ERROR: invalid copy range specified",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
getSICSDataPointer(self,pos, pos + (end -start));
|
||||||
|
memcpy(&self->data[pos],&other->data[start],(end-start)*sizeof(int));
|
||||||
|
memcpy(&self->dataType[pos],&other->dataType[start],
|
||||||
|
(end-start)*sizeof(char));
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
/*----------------------------------------------------------------------
|
/*----------------------------------------------------------------------
|
||||||
Look here in order to find out about commands understood
|
Look here in order to find out about commands understood
|
||||||
----------------------------------------------------------------------*/
|
----------------------------------------------------------------------*/
|
||||||
@ -482,6 +622,7 @@ int SICSDataAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
int argc, char *argv[]){
|
int argc, char *argv[]){
|
||||||
pSICSData self = NULL;
|
pSICSData self = NULL;
|
||||||
char pBueffel[132];
|
char pBueffel[132];
|
||||||
|
int pos;
|
||||||
|
|
||||||
self = (pSICSData)pData;
|
self = (pSICSData)pData;
|
||||||
assert(self);
|
assert(self);
|
||||||
@ -509,6 +650,21 @@ int SICSDataAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return dumpSICSData(self,argv[2],pCon);
|
return dumpSICSData(self,argv[2],pCon);
|
||||||
|
} else if(strcmp(argv[1],"get") == 0){
|
||||||
|
if(argc < 3){
|
||||||
|
SCWrite(pCon,"ERROR: need a position to read",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pos = atoi(argv[2]);
|
||||||
|
return getPos(self,argv[0],pCon,pos);
|
||||||
|
} else if(strcmp(argv[1],"divideby") == 0){
|
||||||
|
if(argc < 3){
|
||||||
|
SCWrite(pCon,"ERROR: need a SICSdata to divide by",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return divideSicsData(self,pSics,pCon,argv[2]);
|
||||||
|
} else if(strcmp(argv[1],"copydata") == 0){
|
||||||
|
return copyData(self,pSics,pCon,argc, argv);
|
||||||
} else if(strcmp(argv[1],"putint") == 0){
|
} else if(strcmp(argv[1],"putint") == 0){
|
||||||
/*---------- putint */
|
/*---------- putint */
|
||||||
return putInt(self,argc-2,&argv[2],pCon, pSics);
|
return putInt(self,argc-2,&argv[2],pCon, pSics);
|
||||||
|
@ -40,4 +40,11 @@
|
|||||||
void *pData,
|
void *pData,
|
||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
|
|
||||||
|
void clearSICSData(pSICSData self);
|
||||||
|
int getSICSDataInt(pSICSData self, int pos, int *value);
|
||||||
|
int getSICSDataFloat(pSICSData self, int pos, float *value);
|
||||||
|
int setSICSDataInt(pSICSData self, int pos, int value);
|
||||||
|
int setSICSDataFloat(pSICSData self, int pos, float value);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,8 @@ sources such as histogram memories or scans. Data assembled in this
|
|||||||
way, for instance through scripts, can then be forwarded to clients
|
way, for instance through scripts, can then be forwarded to clients
|
||||||
either in UUencoded form or as a zipped array.
|
either in UUencoded form or as a zipped array.
|
||||||
|
|
||||||
|
WARNING: this code only works right when integers and floats are of the same size!
|
||||||
|
|
||||||
In a later stage this may be extended to support selected mathematical
|
In a later stage this may be extended to support selected mathematical
|
||||||
operations as well. In another stage this may supersede the uuget and
|
operations as well. In another stage this may supersede the uuget and
|
||||||
zipget methods in the scan, histogram memory and specialized status
|
zipget methods in the scan, histogram memory and specialized status
|
||||||
@ -48,6 +50,13 @@ This object exports the following functions:
|
|||||||
int SICSDataAction(SConnection *pCon, SicsInterp *pSics,
|
int SICSDataAction(SConnection *pCon, SicsInterp *pSics,
|
||||||
void *pData,
|
void *pData,
|
||||||
int argc, char *argv[]);
|
int argc, char *argv[]);
|
||||||
|
|
||||||
|
void clearSICSData(pSICSData self);
|
||||||
|
int getSICSDataInt(pSICSData self, int pos, int *value);
|
||||||
|
int getSICSDataFloat(pSICSData self, int pos, float *value);
|
||||||
|
int setSICSDataInt(pSICSData self, int pos, int value);
|
||||||
|
int setSICSDataFloat(pSICSData self, int pos, float value);
|
||||||
|
|
||||||
@}
|
@}
|
||||||
\begin{description}
|
\begin{description}
|
||||||
\item[getSICSDataPointer] returns a pointer to the first element of
|
\item[getSICSDataPointer] returns a pointer to the first element of
|
||||||
|
513
sicshdbadapter.c
Normal file
513
sicshdbadapter.c
Normal file
@ -0,0 +1,513 @@
|
|||||||
|
/*
|
||||||
|
* Experience has shown that integrating existing SICS objects into the
|
||||||
|
* Hierarchical Parameter Database (Hdb) is a difficult task without reworking
|
||||||
|
* the complete SICS object model. Rather, it seems easier to adapt some
|
||||||
|
* critical objects to the Hdb with some glue code. Following the facade or
|
||||||
|
* adapter design pattern. This is the purpose of this module. For the moment
|
||||||
|
* the external interface is only an interpreter function which will be used to
|
||||||
|
* install suitable SICS objects into the Hdb tree and generates the necessary
|
||||||
|
* adapters internally. This code can be used to adapt to:
|
||||||
|
* - motors
|
||||||
|
* - the data segment of histogram memories
|
||||||
|
*
|
||||||
|
* copyright: see file COPYRIGHT
|
||||||
|
*
|
||||||
|
* Mark Koennecke, November 2006
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sics.h>
|
||||||
|
#include "stptok.h"
|
||||||
|
#include "motor.h"
|
||||||
|
#include "HistMem.h"
|
||||||
|
#include "sicsvar.h"
|
||||||
|
#include "sicshipadaba.h"
|
||||||
|
#include "sicshdbadapter.h"
|
||||||
|
|
||||||
|
#define PRIVNAM "priv"
|
||||||
|
/*==================== support code ====================================*/
|
||||||
|
static void AddPrivProperty(pHdb node, int priv){
|
||||||
|
char pPriv[80];
|
||||||
|
switch(priv){
|
||||||
|
case usInternal:
|
||||||
|
strcpy(pPriv,"internal");
|
||||||
|
break;
|
||||||
|
case usMugger:
|
||||||
|
strcpy(pPriv,"manager");
|
||||||
|
break;
|
||||||
|
case usUser:
|
||||||
|
strcpy(pPriv,"user");
|
||||||
|
break;
|
||||||
|
case usSpy:
|
||||||
|
strcpy(pPriv,"spy");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SetHdbProperty(node,PRIVNAM,pPriv);
|
||||||
|
}
|
||||||
|
/*=================== motor code =======================================*/
|
||||||
|
static int MoveCallback(int iEvent, void *eventData, void *userData,
|
||||||
|
commandContext cc){
|
||||||
|
MotCallback *motData = (MotCallback *)eventData;
|
||||||
|
pHdb motor = (pHdb)userData;
|
||||||
|
pHdb pos = NULL;
|
||||||
|
|
||||||
|
if(iEvent == MOTDRIVE && motData != NULL && motor != NULL){
|
||||||
|
UpdateHipadabaPar(motor,MakeHdbFloat((double)motData->fVal)
|
||||||
|
,NULL);
|
||||||
|
pos = GetHipadabaNode(motor,"position");
|
||||||
|
if(pos != NULL){
|
||||||
|
UpdateHipadabaPar(pos,MakeHdbFloat((double)motData->fVal)
|
||||||
|
,NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static int MotorValueCallback(int iEvent, void *eventData, void *userData,
|
||||||
|
commandContext cc){
|
||||||
|
pHdb motor = (pHdb)userData;
|
||||||
|
pMotor pMot = (pMotor)eventData;
|
||||||
|
pHdb current = NULL;
|
||||||
|
float fVal;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* as setting some motor parameters might cause other motor
|
||||||
|
* parametes to change too, I opt for the cheap solution to check
|
||||||
|
* them all.
|
||||||
|
*/
|
||||||
|
if(iEvent == HDBVAL && motor != NULL && pMot != NULL){
|
||||||
|
current = motor->child;
|
||||||
|
while(current != NULL){
|
||||||
|
MotorGetPar(pMot,current->name,&fVal);
|
||||||
|
if(fVal != current->value.v.doubleValue) {
|
||||||
|
UpdateHipadabaPar(current,MakeHdbFloat((double)fVal),NULL);
|
||||||
|
}
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static int MotorParSetCallback(void *userData, void *callData,
|
||||||
|
pHdb currentNode, hdbValue v){
|
||||||
|
pMotor pMot = (pMotor)userData;
|
||||||
|
SConnection *pCon = (SConnection *)callData;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
assert(pMot != NULL && pCon != NULL);
|
||||||
|
status = MotorSetPar(pMot,pCon,currentNode->name, (float)v.v.doubleValue);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
static int MotorParGetCallback(void *userData, void *callData,
|
||||||
|
pHdb currentNode, hdbValue v){
|
||||||
|
pMotor pMot = (pMotor)userData;
|
||||||
|
float fVal;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
assert(pMot != NULL);
|
||||||
|
status = MotorGetPar(pMot,currentNode->name,&fVal);
|
||||||
|
currentNode->value.v.doubleValue = fVal;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static pHdb MakeMotParNode(char *name, pMotor pMot){
|
||||||
|
pHdb node = NULL;
|
||||||
|
pHdbCallback pCall = NULL;
|
||||||
|
|
||||||
|
node = MakeHipadabaNode(name, HIPFLOAT, 1);
|
||||||
|
if(node != NULL) {
|
||||||
|
pCall = MakeHipadabaCallback(MotorParSetCallback,pMot,NULL,-1,-1);
|
||||||
|
if(pCall == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
AppendHipadabaCallback(node,HCBSET,pCall);
|
||||||
|
pCall = MakeHipadabaCallback(MotorParGetCallback,pMot,NULL,-1,-1);
|
||||||
|
if(pCall == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
AppendHipadabaCallback(node,HCBREAD,pCall);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static int AddStdMotorPar(pHdb motorNode, pMotor pMot){
|
||||||
|
int i;
|
||||||
|
pHdb parNode = NULL;
|
||||||
|
char *addPar[] = {"target",
|
||||||
|
"hardlowerlim",
|
||||||
|
"hardupperlim",
|
||||||
|
NULL};
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while(addPar[i] != NULL){
|
||||||
|
parNode = MakeMotParNode(addPar[i],pMot);
|
||||||
|
SetHdbProperty(parNode,PRIVNAM,"internal");
|
||||||
|
if(parNode == NULL){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
AddHipadabaChild(motorNode,parNode, NULL);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add the parameters in the obpar array
|
||||||
|
*/
|
||||||
|
for(i = 0; i < MOTOBPARLENGTH; i++){
|
||||||
|
parNode = MakeMotParNode(pMot->ParArray[i].name,pMot);
|
||||||
|
if(parNode == NULL){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
AddHipadabaChild(motorNode,parNode, NULL);
|
||||||
|
AddPrivProperty(parNode,pMot->ParArray[i].iCode);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static char *getDriverParList(MotorDriver *pDriv){
|
||||||
|
SConnection *pCon = NULL;
|
||||||
|
pDynString list = NULL;
|
||||||
|
char *listData = NULL;
|
||||||
|
|
||||||
|
if(pDriv->ListDriverPar != NULL){
|
||||||
|
pCon = SCCreateDummyConnection(pServ->pSics);
|
||||||
|
if(pCon == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
SCStartBuffering(pCon);
|
||||||
|
pDriv->ListDriverPar(pDriv,"test.", pCon);
|
||||||
|
list = SCEndBuffering(pCon);
|
||||||
|
if(list != NULL){
|
||||||
|
listData = strdup(GetCharArray(list));
|
||||||
|
SCDeleteConnection(pCon);
|
||||||
|
} else {
|
||||||
|
listData = NULL;
|
||||||
|
}
|
||||||
|
return listData;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
extern char *trim(char *str);
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static char *extractName(char *line){
|
||||||
|
char *name = NULL, *pEnd = NULL;
|
||||||
|
|
||||||
|
name = strchr(line,'.');
|
||||||
|
assert(name != NULL);
|
||||||
|
while(*name == '.'){
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
pEnd = strchr(name,'=');
|
||||||
|
assert(pEnd != NULL);
|
||||||
|
*pEnd = '\0';
|
||||||
|
return trim(name);
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
static int CreateDriverParameters(pMotor pM, pHdb parent){
|
||||||
|
char *listPtr = NULL, line[80], *pPtr, *name;
|
||||||
|
pHdb node = NULL;
|
||||||
|
|
||||||
|
listPtr = getDriverParList(pM->pDriver);
|
||||||
|
if(listPtr == NULL){
|
||||||
|
/*
|
||||||
|
* no driver parameters
|
||||||
|
*/
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
pPtr = listPtr;
|
||||||
|
while((pPtr = stptok(pPtr,line,79,"\n")) != NULL){
|
||||||
|
name = extractName(line);
|
||||||
|
node = MakeMotParNode(name,pM);
|
||||||
|
SetHdbProperty(node,PRIVNAM,"manager");
|
||||||
|
if(node != NULL){
|
||||||
|
AddHipadabaChild(parent,node,NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(listPtr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
static pHdb CreateMotorAdapter(char *name, pMotor pMot){
|
||||||
|
pHdb result = NULL;
|
||||||
|
commandContext comCom;
|
||||||
|
float access;
|
||||||
|
|
||||||
|
assert(pMot != NULL);
|
||||||
|
|
||||||
|
result = MakeSICSHdbDriv(name,usUser,pMot,HIPFLOAT);
|
||||||
|
if(result == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
MotorGetPar(pMot,"accesscode",&access);
|
||||||
|
AddPrivProperty(result,(int)access);
|
||||||
|
SetHdbProperty(result,"type","drivable");
|
||||||
|
SetHdbProperty(result,"sicsdev",pMot->name);
|
||||||
|
/*
|
||||||
|
* We want to be notified when this motor drives around. Or
|
||||||
|
* its parameters change.
|
||||||
|
*/
|
||||||
|
strncpy(comCom.deviceID,name,255);
|
||||||
|
comCom.transID = -77;
|
||||||
|
RegisterCallback(pMot->pCall,comCom, MOTDRIVE, MoveCallback,
|
||||||
|
result,NULL);
|
||||||
|
RegisterCallback(pMot->pCall,comCom, HDBVAL, MotorValueCallback,
|
||||||
|
result,NULL);
|
||||||
|
|
||||||
|
if(!AddStdMotorPar(result,pMot)){
|
||||||
|
DeleteHipadabaNode(result,NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!CreateDriverParameters(pMot,result)){
|
||||||
|
DeleteHipadabaNode(result,NULL);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
result->protected = 1;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*============== histogram memory ======================================*/
|
||||||
|
static long totalSum(int *data, int length){
|
||||||
|
long result = 0l;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(data == NULL){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
for(i = 0; i < length; i++){
|
||||||
|
result += data[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
static int HMDataGetCallback(void *userData, void *callData,
|
||||||
|
pHdb currentNode, hdbValue v){
|
||||||
|
pHistMem pHM = (pHistMem)userData;
|
||||||
|
SConnection *pCon = (SConnection *)callData;
|
||||||
|
long sum1, sum2;
|
||||||
|
|
||||||
|
assert(pHM != NULL);
|
||||||
|
if(pCon == NULL){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sum1 = totalSum(currentNode->value.v.intArray, currentNode->value.arrayLength);
|
||||||
|
currentNode->value.arrayLength = GetHistLength(pHM);
|
||||||
|
currentNode->value.v.intArray = (int *)GetHistogramPointer(pHM,pCon);
|
||||||
|
sum2 = totalSum(currentNode->value.v.intArray, currentNode->value.arrayLength);
|
||||||
|
if(sum1 != sum2){
|
||||||
|
UpdateHipadabaPar(currentNode,currentNode->value,NULL);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
static pHdb MakeHMDataNode(pHistMem pHM, char *name){
|
||||||
|
pHdb node = NULL;
|
||||||
|
pHdbCallback pCall = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
node = MakeHipadabaNode(name,HIPINTVARAR,2);
|
||||||
|
if(node == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pCall = MakeHipadabaCallback(HMDataGetCallback,pHM,NULL,-1,-1);
|
||||||
|
if(pCall == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
AppendHipadabaCallback(node,HCBREAD,pCall);
|
||||||
|
AppendHipadabaCallback(node,HCBSET,MakeReadOnlyCallback());
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
/*================ SICS Variable ======================================*/
|
||||||
|
static int SicsVarSetCallback(void *userData, void *callData,
|
||||||
|
pHdb currentNode, hdbValue v){
|
||||||
|
pSicsVariable pVar = (pSicsVariable)userData;
|
||||||
|
SConnection *pCon = (SConnection *)callData;
|
||||||
|
int userRights = usMugger;
|
||||||
|
|
||||||
|
assert(pVar != NULL);
|
||||||
|
|
||||||
|
if(pCon != NULL){
|
||||||
|
userRights = SCGetRights(pCon);
|
||||||
|
}
|
||||||
|
switch(currentNode->value.dataType){
|
||||||
|
case HIPINT:
|
||||||
|
VarSetInt(pVar, v.v.intValue, userRights);
|
||||||
|
break;
|
||||||
|
case HIPFLOAT:
|
||||||
|
VarSetFloat(pVar, (float)v.v.doubleValue, userRights);
|
||||||
|
break;
|
||||||
|
case HIPTEXT:
|
||||||
|
VarSetText(pVar, v.v.text, userRights);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
static int ValueCallback(int iEvent, void *eventData, void *userData,
|
||||||
|
commandContext cc){
|
||||||
|
pSicsVariable pVar = (pSicsVariable)eventData;
|
||||||
|
pHdb node = (pHdb)userData;
|
||||||
|
hdbValue v;
|
||||||
|
|
||||||
|
if(iEvent == VALUECHANGE && pVar != NULL && node != NULL){
|
||||||
|
switch(pVar->eType){
|
||||||
|
case veInt:
|
||||||
|
v = MakeHdbInt(pVar->iVal);
|
||||||
|
break;
|
||||||
|
case veFloat:
|
||||||
|
v = MakeHdbFloat((double)pVar->fVal);
|
||||||
|
break;
|
||||||
|
case veText:
|
||||||
|
v = MakeHdbText(pVar->text);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
UpdateHipadabaPar(node,v,NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
static pHdb MakeSicsVarNode(pSicsVariable pVar, char *name){
|
||||||
|
pHdb node = NULL;
|
||||||
|
pHdbCallback pCall = NULL;
|
||||||
|
commandContext comCom;
|
||||||
|
int type;
|
||||||
|
|
||||||
|
switch(pVar->eType){
|
||||||
|
case veInt:
|
||||||
|
type = HIPINT;
|
||||||
|
break;
|
||||||
|
case veFloat:
|
||||||
|
type = HIPFLOAT;
|
||||||
|
break;
|
||||||
|
case veText:
|
||||||
|
type = HIPTEXT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
node = MakeHipadabaNode(name,type,1);
|
||||||
|
if(node == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(pVar->iLock == 1) {
|
||||||
|
AddPrivProperty(node,usInternal);
|
||||||
|
} else {
|
||||||
|
AddPrivProperty(node,pVar->iAccessCode);
|
||||||
|
}
|
||||||
|
pCall = MakeHipadabaCallback(SicsVarSetCallback,pVar,NULL,-1,-1);
|
||||||
|
if(pCall == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
strncpy(comCom.deviceID,name,255);
|
||||||
|
comCom.transID = -77;
|
||||||
|
AppendHipadabaCallback(node,HCBSET,pCall);
|
||||||
|
RegisterCallback(pVar->pCall,comCom, VALUECHANGE, ValueCallback,
|
||||||
|
node,NULL);
|
||||||
|
|
||||||
|
node->protected = 1;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
/*============== interpreter function ==================================*/
|
||||||
|
int SICSHdbAdapter(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]){
|
||||||
|
pHdb root = NULL;
|
||||||
|
pHdb path = NULL;
|
||||||
|
pHdb node = NULL;
|
||||||
|
pMotor pMot = NULL;
|
||||||
|
pHistMem pHM = NULL;
|
||||||
|
CommandList *pCom = NULL;
|
||||||
|
pIDrivable pDriv = NULL;
|
||||||
|
pSicsVariable pVar = NULL;
|
||||||
|
char buffer[512];
|
||||||
|
|
||||||
|
root = GetHipadabaRoot();
|
||||||
|
assert(root != NULL);
|
||||||
|
|
||||||
|
if(!SCMatchRights(pCon,usMugger)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(argc < 4) {
|
||||||
|
SCWrite(pCon,"ERROR: Insufficient number of arguments",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = GetHipadabaNode(root,argv[1]);
|
||||||
|
if(path == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: path to attach object too not found",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* look for motors
|
||||||
|
*/
|
||||||
|
pMot = (pMotor)FindCommandData(pSics,argv[2],"Motor");
|
||||||
|
if(pMot != NULL){
|
||||||
|
node = CreateMotorAdapter(argv[3],pMot);
|
||||||
|
if(node == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: out of memory creating motor node",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
AddHipadabaChild(path,node,pCon);
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* look for drivables
|
||||||
|
*/
|
||||||
|
pDriv = FindDrivable(pSics,argv[2]);
|
||||||
|
pCom = FindCommand(pSics,argv[2]);
|
||||||
|
if(pDriv != NULL && pCom != NULL && pCom->pData != NULL){
|
||||||
|
node = MakeSICSHdbDriv(argv[3],usUser,pCom->pData,HIPFLOAT);
|
||||||
|
if(node == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: out of memory creating drivable node",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SetHdbProperty(node,PRIVNAM,"user");
|
||||||
|
SetHdbProperty(node,"type","drivable");
|
||||||
|
SetHdbProperty(node,"sicsdev",argv[2]);
|
||||||
|
AddHipadabaChild(path,node,pCon);
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* look for SICS Variables
|
||||||
|
*/
|
||||||
|
pVar = (pSicsVariable)FindCommandData(pSics,argv[2],"SicsVariable");
|
||||||
|
if(pVar != NULL){
|
||||||
|
node = MakeSicsVarNode(pVar,argv[3]);
|
||||||
|
if(node == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: out of memory creating SICS variable node",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
AddHipadabaChild(path,node,pCon);
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* look for histogram memories
|
||||||
|
*/
|
||||||
|
pHM = (pHistMem)FindCommandData(pSics,argv[2],"HistMem");
|
||||||
|
if(pHM != NULL){
|
||||||
|
node = MakeHMDataNode(pHM,argv[3]);
|
||||||
|
if(node == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: out of memory creating HM node",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
AddHipadabaChild(path,node,pCon);
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(buffer,511,
|
||||||
|
"ERROR: attaching this type of object: %s at %s not implemented",
|
||||||
|
argv[2], argv[1]);
|
||||||
|
SCWrite(pCon,buffer,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user