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
|
||||
@ -58,6 +58,9 @@
|
||||
SConnection *pCon);
|
||||
float (*GetTime)(pHistDriver self,
|
||||
SConnection *pCon);
|
||||
HistInt *(*SubSample)(pHistDriver self,
|
||||
SConnection *pCon,int bank,
|
||||
char *command);
|
||||
int (*Preset)(pHistDriver self,
|
||||
SConnection *pCon,
|
||||
HistInt iVal);
|
||||
@ -69,17 +72,17 @@
|
||||
void *pPriv;
|
||||
} HistDriver;
|
||||
|
||||
#line 474 "histogram.w"
|
||||
#line 477 "histogram.w"
|
||||
|
||||
|
||||
#line 229 "histogram.w"
|
||||
#line 232 "histogram.w"
|
||||
|
||||
pHistDriver CreateHistDriver(pStringDict pDict);
|
||||
void DeleteHistDriver(pHistDriver self);
|
||||
int HistDriverConfig(pHistDriver self, pStringDict pOpt,
|
||||
SConnection *pCon);
|
||||
|
||||
#line 475 "histogram.w"
|
||||
#line 478 "histogram.w"
|
||||
|
||||
|
||||
#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
|
||||
@ -42,22 +42,22 @@
|
||||
eReflect
|
||||
} OverFlowMode;
|
||||
|
||||
#line 455 "histogram.w"
|
||||
#line 458 "histogram.w"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
#line 287 "histogram.w"
|
||||
#line 290 "histogram.w"
|
||||
|
||||
pHistMem CreateHistMemory(char *drivername);
|
||||
void DeleteHistMemory(void *self);
|
||||
|
||||
#line 303 "histogram.w"
|
||||
#line 306 "histogram.w"
|
||||
|
||||
int HistGetOption(pHistMem self, char *name, char *result, int iResultLen);
|
||||
int HistSetOption(pHistMem self, char *name, char *value);
|
||||
int HistConfigure(pHistMem self, SConnection *pCon, SicsInterp *pSics);
|
||||
|
||||
#line 331 "histogram.w"
|
||||
#line 334 "histogram.w"
|
||||
|
||||
float GetHistPreset(pHistMem self);
|
||||
int SetHistPreset(pHistMem self, float fVal);
|
||||
@ -73,7 +73,7 @@
|
||||
void HistDirty(pHistMem self);
|
||||
|
||||
|
||||
#line 361 "histogram.w"
|
||||
#line 364 "histogram.w"
|
||||
|
||||
int SetHistogram(pHistMem self, SConnection *pCon,
|
||||
int i,int iStart, int iEnd, HistInt *lData);
|
||||
@ -85,7 +85,7 @@
|
||||
HistInt *lData, int iDataLen);
|
||||
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 argc, char *argv[]);
|
||||
@ -94,7 +94,7 @@
|
||||
int argc, char *argv[]);
|
||||
|
||||
|
||||
#line 457 "histogram.w"
|
||||
#line 460 "histogram.w"
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
#line 480 "histogram.w"
|
||||
#line 483 "histogram.w"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
H I S T M E M -- Internal
|
||||
@ -11,7 +11,7 @@
|
||||
#ifndef SICSHISTMEMINT
|
||||
#define SICSHISTMEMINT
|
||||
|
||||
#line 251 "histogram.w"
|
||||
#line 254 "histogram.w"
|
||||
|
||||
typedef struct __HistMem {
|
||||
pObjectDescriptor pDes;
|
||||
@ -23,7 +23,7 @@
|
||||
pICallBack pCall;
|
||||
} HistMem;
|
||||
|
||||
#line 490 "histogram.w"
|
||||
#line 493 "histogram.w"
|
||||
|
||||
|
||||
#endif
|
||||
|
69
SCinter.c
69
SCinter.c
@ -41,7 +41,7 @@
|
||||
Mark Koennecke, August 2001, modified SicsWriteStatus to write motor
|
||||
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
|
||||
|
||||
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.
|
||||
Paul Hathaway, May 2004
|
||||
|
||||
Added FindAlias function, Mark Koennecke, January 2007
|
||||
---------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -67,6 +69,7 @@
|
||||
#include "motor.h"
|
||||
#include "obdes.h"
|
||||
#include "lld.h"
|
||||
#include "dynstring.h"
|
||||
|
||||
/* M.Z. */
|
||||
#include "definealias.h"
|
||||
@ -134,6 +137,7 @@ static void freeList(int listID);
|
||||
SICSLogWrite(pBueffel,eInternal);
|
||||
return 0;
|
||||
}
|
||||
memset(pNew,0,sizeof(CommandList));
|
||||
|
||||
/* if no data given, initialise with Dummy struct */
|
||||
if(!pData)
|
||||
@ -431,7 +435,7 @@ extern char *SkipSpace(char *pPtr);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
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,
|
||||
eWarning,
|
||||
eError,
|
||||
eHdb
|
||||
eHdbValue,
|
||||
eHdbEvent
|
||||
} OutCode;
|
||||
|
||||
#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));
|
||||
if(iRet != TCL_OK){
|
||||
SCWrite(pCon,"ERROR: Movement not possible or bad collider script",eError);
|
||||
SCWrite(pCon,Tcl_DStringValue(&command),eError);
|
||||
/*
|
||||
SCWrite(pCon,pServ->pSics->pTcl->result,eError);
|
||||
*/
|
||||
|
91
conman.c
91
conman.c
@ -39,6 +39,8 @@
|
||||
fields.
|
||||
Mark Koennecke, December 2004
|
||||
|
||||
Aded buffering support, Mark Koennecke, July 2006
|
||||
|
||||
Copyright: see copyright.h
|
||||
-----------------------------------------------------------------------------*/
|
||||
#include "fortify.h"
|
||||
@ -92,6 +94,8 @@ extern pServer pServ;
|
||||
static int iName = 0;
|
||||
static SConnection *freeConnections = NULL;
|
||||
static long lastIdent = 0;
|
||||
/*------------- sending connection (prevent double write when listening) ----*/
|
||||
static SConnection *sendingConnection = NULL;
|
||||
/*===========================================================================*/
|
||||
static char *ConName(long ident) {
|
||||
static char name[32];
|
||||
@ -457,6 +461,11 @@ extern pServer pServ;
|
||||
DeleteCommandStack(pVictim->pStack);
|
||||
}
|
||||
|
||||
/* remove possible buffers */
|
||||
if(pVictim->data != NULL)
|
||||
{
|
||||
DeleteDynString(pVictim->data);
|
||||
}
|
||||
|
||||
pVictim->lMagic=0; /* make a write to a freed connection harmless */
|
||||
/* finally free pVictim*/
|
||||
@ -692,10 +701,21 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
||||
SICSLogWrite(buffer,iOut);
|
||||
|
||||
/* write to commandlog if user or manager privilege */
|
||||
if(SCGetRights(self) <= usUser && self->iMacro != 1)
|
||||
if(SCGetRights(self) <= usUser)
|
||||
{
|
||||
sprintf(pBueffel,"To sock %d :",iRet);
|
||||
WriteToCommandLog(pBueffel,buffer);
|
||||
if(self->iMacro != 1)
|
||||
{
|
||||
sprintf(pBueffel,"To sock %d :",iRet);
|
||||
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 */
|
||||
@ -754,7 +774,9 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
||||
if(SCGetRights(self) <= usUser && self->iMacro != 1)
|
||||
{
|
||||
sprintf(pBueffel,"To sock %d :",iRet);
|
||||
sendingConnection = self;
|
||||
WriteToCommandLog(pBueffel,buffer);
|
||||
sendingConnection = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -809,6 +831,52 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
||||
free(bufPtr);
|
||||
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)
|
||||
{
|
||||
@ -1378,7 +1446,16 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
||||
{
|
||||
strcat(pBueffel,"CONT or CRON>> ");
|
||||
}
|
||||
WriteToCommandLog(pBueffel,pCommand);
|
||||
/*
|
||||
* This is a fix to suppress cron messages in the success
|
||||
* case
|
||||
*/
|
||||
if(SCGetWriteFunc(self) != SCNotWrite)
|
||||
{
|
||||
sendingConnection = self;
|
||||
WriteToCommandLog(pBueffel,pCommand);
|
||||
sendingConnection = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* invoke */
|
||||
@ -1900,8 +1977,8 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
||||
SCSetRights(self,iRet);
|
||||
pHost[0] = '\0';
|
||||
NETInfo(self->pSock,pHost,131);
|
||||
sprintf(pBueffel,"Accepted connection on socket %d from %s",
|
||||
self->pSock->sockid, pHost);
|
||||
sprintf(pBueffel,"Accepted connection %s on socket %d from %s",
|
||||
ConName(self->ident), self->pSock->sockid, pHost);
|
||||
SICSLogWrite(pBueffel,eInternal);
|
||||
WriteToCommandLog("SYS >", pBueffel);
|
||||
free(pPtr);
|
||||
@ -1965,7 +2042,7 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
||||
else if(iSignal == COMLOG && self->listening == 1)
|
||||
{
|
||||
pPtr = (char *)pSigData;
|
||||
if(pPtr != NULL)
|
||||
if(pPtr != NULL && self != sendingConnection)
|
||||
{
|
||||
doSockWrite(self,pPtr);
|
||||
}
|
||||
|
10
conman.h
10
conman.h
@ -24,6 +24,7 @@
|
||||
#include "network.h"
|
||||
#include "obdes.h"
|
||||
#include "commandcontext.h"
|
||||
#include "dynstring.h"
|
||||
|
||||
#define MAXLOGFILES 10
|
||||
|
||||
@ -59,6 +60,12 @@ typedef int (*writeFunc)(struct __SConnection *pCon,
|
||||
int iGrab; /* grab flag for token*/
|
||||
int parameterChange;
|
||||
int sicsError;
|
||||
|
||||
/*
|
||||
* for I/O Buffering
|
||||
*/
|
||||
pDynString data;
|
||||
writeFunc oldWriteFunc;
|
||||
|
||||
/*
|
||||
stuff supporting the sycamore protocol and a
|
||||
@ -116,6 +123,9 @@ typedef int (*writeFunc)(struct __SConnection *pCon,
|
||||
int SCNotWrite(SConnection *self, char *buffer, int iOut);
|
||||
int SCNormalWrite(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 *********************************** */
|
||||
int SCRegister(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pInter, long lID);
|
||||
|
@ -88,4 +88,10 @@
|
||||
* file: mcstascounter.c
|
||||
*/
|
||||
pCounterDriver NewMcStasCounter(char *name);
|
||||
|
||||
/*
|
||||
* for regression testing
|
||||
* file: regresscter.c
|
||||
*/
|
||||
pCounterDriver NewRegressCounter(char *name);
|
||||
#endif
|
||||
|
14
counter.c
14
counter.c
@ -103,9 +103,9 @@
|
||||
if(iRet == OKOK)
|
||||
{
|
||||
self->isUpToDate = 0;
|
||||
self->badStatusCount = 0;
|
||||
self->badStatusCount = 0;
|
||||
self->tStart = time(&tX);
|
||||
InvokeCallBack(self->pCall,COUNTSTART,pCon);
|
||||
InvokeCallBack(self->pCall,COUNTSTART,pCon);
|
||||
return iRet;
|
||||
}
|
||||
else
|
||||
@ -314,7 +314,7 @@
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
iRet = self->pDriv->ReadValues(self->pDriv);
|
||||
if(iRet)
|
||||
if(iRet == OKOK)
|
||||
{
|
||||
self->isUpToDate = 1;
|
||||
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
|
||||
*/
|
||||
@ -907,6 +914,7 @@
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
case 11: /* status */
|
||||
self->pCountInt->TransferData(self,pCon);
|
||||
if(GetCounterMode(self) == ePreset)
|
||||
{
|
||||
sprintf(pBueffel,"%s.CountStatus = %d %d Beam: %ld E6",
|
||||
|
36
devexec.c
36
devexec.c
@ -70,18 +70,23 @@ static FILE *devLog = NULL;
|
||||
int openDevexecLog(){
|
||||
char *fileName = NULL;
|
||||
char fileBuffer[1024];
|
||||
time_t iDate;
|
||||
struct tm *psTime;
|
||||
|
||||
|
||||
if(devLog == NULL){
|
||||
fileName = IFindOption(pSICSOptions,"devexeclog");
|
||||
if(fileName != NULL){
|
||||
strcpy(fileBuffer,fileName);
|
||||
} else {
|
||||
iDate = time(NULL);
|
||||
psTime = localtime(&iDate);
|
||||
fileBuffer[0] = '\0';
|
||||
fileName = getenv("HOME");
|
||||
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+");
|
||||
}
|
||||
@ -168,6 +173,20 @@ typedef struct {
|
||||
} ExeList;
|
||||
|
||||
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)
|
||||
{
|
||||
@ -200,8 +219,10 @@ typedef struct {
|
||||
pRes->lTask = -1;
|
||||
pRes->iLock = 0;
|
||||
pRes->drivePrint = 0;
|
||||
pRes->paused = 0;
|
||||
pRes->pCall = CreateCallBackInterface();
|
||||
pRes->lastRun = time(NULL);
|
||||
pRes->pDes->GetInterface = DevexecInterface;
|
||||
return pRes;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -508,7 +529,7 @@ typedef struct {
|
||||
ExeInterest(self, pDev, "finished");
|
||||
DeleteDevEntry(pDev);
|
||||
LLDnodeDelete(self->iList);
|
||||
SCWrite(pCon, "Finished", eFinish);
|
||||
SCWrite(pCon, "", eFinish);
|
||||
iRet = LLDnodePtr2Prev(self->iList);
|
||||
if(SCGetInterrupt(self->pOwner) != eContinue)
|
||||
{
|
||||
@ -667,7 +688,6 @@ static int errorDevice(pCheckContext pCheck){
|
||||
|
||||
ExeInterest(pCheck->self, pCheck->pDev, "finished with problem");
|
||||
DevexecLog("STOP",pCheck->pDev->name);
|
||||
DeleteDevEntry(pCheck->pDev);
|
||||
LLDnodeDelete(pCheck->self->iList);
|
||||
status = LLDnodePtr2Prev(pCheck->self->iList);
|
||||
SCWrite(pCheck->self->pOwner, "", eFinish);
|
||||
@ -675,7 +695,9 @@ static int errorDevice(pCheckContext pCheck){
|
||||
if(pCheck->pDrivInt != NULL) {
|
||||
pCheck->pDrivInt->iErrorCount++;
|
||||
}
|
||||
return checkInterrupt(pCheck,status);
|
||||
status = checkInterrupt(pCheck,status);
|
||||
DeleteDevEntry(pCheck->pDev);
|
||||
return status;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int testFinish(pExeList self){
|
||||
@ -1121,7 +1143,7 @@ static int testFinish(pExeList self){
|
||||
{
|
||||
ListPending(self,pCon);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
iRet = StopExe(self,argv[1]);
|
||||
if(!iRet)
|
||||
@ -1143,7 +1165,7 @@ static int testFinish(pExeList self){
|
||||
SCPopContext(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int ListExe(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
|
10
devexec.h
10
devexec.h
@ -118,6 +118,8 @@
|
||||
#line 259 "devexec.w"
|
||||
|
||||
/*-------------------------- Commands ------------------------------------*/
|
||||
int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/*
|
||||
@ -152,11 +154,7 @@
|
||||
/*
|
||||
continues execution
|
||||
*/
|
||||
int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/*
|
||||
* various commands
|
||||
*/
|
||||
|
||||
/*--------------------------- Locking ---------------------------------*/
|
||||
|
||||
#line 183 "devexec.w"
|
||||
@ -165,7 +163,7 @@
|
||||
void UnlockDeviceExecutor(pExeList self);
|
||||
|
||||
|
||||
#line 297 "devexec.w"
|
||||
#line 299 "devexec.w"
|
||||
|
||||
/* -------------------------- Executor management -------------------------*/
|
||||
|
||||
|
@ -312,6 +312,8 @@ to the global SICS device executor.
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$devstop {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\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 argc, char *argv[]);@\\
|
||||
\mbox{}\verb@ /*@\\
|
||||
|
@ -258,6 +258,8 @@ to the global SICS device executor.
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@<devstop@>
|
||||
/*-------------------------- Commands ------------------------------------*/
|
||||
int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/*
|
||||
|
@ -104,7 +104,7 @@ the dictionary file:
|
||||
would denote the normal counting tube at a scanning type of
|
||||
experiment.
|
||||
</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
|
||||
the alias hmAlias. Nxscript automatically updates the dim0, dim1, ..., timedim
|
||||
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
|
||||
dictionary though which contains the length of a time binning if
|
||||
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
|
||||
<dd>Writes the time binning at histogram memory hmName to file using
|
||||
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
|
||||
definiton string belonging to aliasName does not need to contain a
|
||||
-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
|
||||
<dd>This writes an global attribute attName. Everything after attName
|
||||
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
|
||||
<dd>This creates a symbolic link for victimAlias in the group
|
||||
designated by targetAlias.
|
||||
|
@ -65,6 +65,9 @@ file.
|
||||
<dt>updateintervall
|
||||
<dd>The time intervall in seconds between updates. The defualt is
|
||||
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>
|
||||
</p>
|
||||
</BODY>
|
||||
|
@ -21,6 +21,37 @@ The TAS requires the following initializations in its instrument file:
|
||||
<dt>MakeTasUB tasub
|
||||
<dd>Installs the TAS crystallographic calculation module into SICS. It will
|
||||
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
|
||||
<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.
|
||||
|
@ -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 be the full path name of the file to execute.
|
||||
</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>
|
||||
</HTML>
|
||||
|
||||
|
@ -45,6 +45,13 @@ named buffer within the stack of nested buffers.
|
||||
<dt>Clears the queue of batch buffers
|
||||
<dt>exe 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
|
||||
<dd>Starts executing the batch buffers in the queue.
|
||||
<dt>exe print buffername
|
||||
@ -58,7 +65,12 @@ most useful for SICS clients watching the progress of the experiment.
|
||||
<dt>exe append some text
|
||||
<dd> Appends a line with everything after append to the upload buffer
|
||||
<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>
|
||||
</P>
|
||||
</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.
|
||||
</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
|
||||
understand the following commands:
|
||||
<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.
|
||||
<DT>opti run
|
||||
<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>
|
||||
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
|
||||
@ -72,5 +87,12 @@ status of the countmode parameter this is either a preset time or a preset
|
||||
monitor.
|
||||
</DL>
|
||||
</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>
|
||||
</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:
|
||||
a3, the sample rotation, a4, sample two theta, sgu, upper tilt cradle, sgl, lower tilt
|
||||
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>
|
||||
</p>
|
||||
<h3>Calculations</h3>
|
||||
|
@ -971,12 +971,15 @@ static void ErrReport(pEVControl self)
|
||||
{
|
||||
ObPar *pPar = NULL;
|
||||
char pBueffel[512];
|
||||
int iRet;
|
||||
int iRet, savedStatus;
|
||||
|
||||
assert(self);
|
||||
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);
|
||||
SetStatus(savedStatus);
|
||||
if(!iRet)
|
||||
{
|
||||
return iRet;
|
||||
@ -1102,8 +1105,11 @@ static void ErrReport(pEVControl self)
|
||||
iRet = EVCGetPos(self,pCon,&fPos);
|
||||
if(iRet)
|
||||
{
|
||||
/*
|
||||
sprintf(pBueffel,"%s.%s = %g",self->pName,"CurrentValue", fPos);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
*/
|
||||
SCPrintf(pCon, eValue, "%s = %g", self->pName, fPos);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
5
event.c
5
event.c
@ -64,6 +64,11 @@
|
||||
"BATCHAREA",
|
||||
"BATCHEND",
|
||||
"DRIVSTAT",
|
||||
"STATUS",
|
||||
"POSITION",
|
||||
"HDBVAL",
|
||||
"STATESTART",
|
||||
"STATEEND",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
22
event.h
22
event.h
@ -1,5 +1,5 @@
|
||||
|
||||
#line 89 "event.w"
|
||||
#line 103 "event.w"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
E V E N T
|
||||
@ -14,15 +14,15 @@
|
||||
#ifndef SICSEVENT
|
||||
#define SICSEVENT
|
||||
|
||||
#line 13 "event.w"
|
||||
#line 14 "event.w"
|
||||
|
||||
int Text2Event(char *pText);
|
||||
|
||||
#line 102 "event.w"
|
||||
#line 116 "event.w"
|
||||
|
||||
|
||||
|
||||
#line 20 "event.w"
|
||||
#line 21 "event.w"
|
||||
|
||||
#define VALUECHANGE 0
|
||||
#define MOTDRIVE 1
|
||||
@ -42,14 +42,18 @@
|
||||
#define BATCHAREA 15
|
||||
#define BATCHEND 16
|
||||
#define DRIVSTAT 17
|
||||
#define STATUS 18
|
||||
#define POSITION 19 /* Position event for motors - ffr */
|
||||
#line 104 "event.w"
|
||||
#define STATUS 18
|
||||
#define POSITION 19
|
||||
#define HDBVAL 20
|
||||
#define STSTART 21
|
||||
#define STEND 22
|
||||
|
||||
#line 118 "event.w"
|
||||
|
||||
|
||||
/*--------------- Signals for the Signalfunction of each task ------------*/
|
||||
|
||||
#line 73 "event.w"
|
||||
#line 87 "event.w"
|
||||
|
||||
#define SICSINT 300
|
||||
#define SICSBROADCAST 301
|
||||
@ -57,6 +61,6 @@
|
||||
#define TOKENRELEASE 303
|
||||
#define COMLOG 304
|
||||
|
||||
#line 107 "event.w"
|
||||
#line 121 "event.w"
|
||||
|
||||
#endif
|
||||
|
@ -53,6 +53,9 @@ $\langle$VE {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@#define BATCHAREA 15@\\
|
||||
\mbox{}\verb@#define BATCHEND 16@\\
|
||||
\mbox{}\verb@#define DRIVSTAT 17@\\
|
||||
\mbox{}\verb@#define STATUS 18@\\
|
||||
\mbox{}\verb@#define POSITION 19@\\
|
||||
\mbox{}\verb@#define HDBVAL 20@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
@ -87,6 +90,10 @@ operation.
|
||||
\item[BATCHEND] signals the end of the batch buffers processing.
|
||||
\item[DRIVSTAT] signals a change in the status of a driving operation
|
||||
(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}
|
||||
|
||||
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 BATCHEND 16
|
||||
#define DRIVSTAT 17
|
||||
#define STATUS 18
|
||||
#define POSITION 19
|
||||
#define HDBVAL 20
|
||||
@}
|
||||
\begin{description}
|
||||
\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[DRIVSTAT] signals a change in the status of a driving operation
|
||||
(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}
|
||||
|
||||
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 runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics,
|
||||
char *name);
|
||||
pDynString findBatchFile(SicsInterp *pSics, char *name);
|
||||
@}
|
||||
|
||||
@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
|
||||
@ -89,7 +89,7 @@
|
||||
*/
|
||||
char *exeBufName(pExeBuf self);
|
||||
|
||||
#line 222 "exe.w"
|
||||
#line 223 "exe.w"
|
||||
|
||||
|
||||
#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
|
||||
@ -16,6 +16,6 @@ typedef struct __EXEBUF{
|
||||
int lineno;
|
||||
} 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);
|
||||
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,
|
||||
SicsInterp *pSics, char *name){
|
||||
@ -937,6 +974,7 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
char pBufferName[256];
|
||||
int status;
|
||||
pDynString dirList = NULL;
|
||||
pDynString fullPath = NULL;
|
||||
|
||||
self = (pExeMan)pData;
|
||||
assert(self != NULL);
|
||||
@ -1012,6 +1050,24 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
SCWrite(pCon,"Nothing found",eValue);
|
||||
}
|
||||
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){
|
||||
clearQueue(self);
|
||||
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 runExeBatchBuffer(void *pData, SConnection *pCon, SicsInterp *pSics,
|
||||
char *name);
|
||||
pDynString findBatchFile(SicsInterp *pSics, char *name);
|
||||
|
||||
#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
|
||||
@ -20,5 +20,5 @@ typedef struct __EXEMAN{
|
||||
int echo;
|
||||
}ExeMan, *pExeMan;
|
||||
|
||||
#line 183 "exe.w"
|
||||
#line 184 "exe.w"
|
||||
|
||||
|
13
fitcenter.c
13
fitcenter.c
@ -421,6 +421,7 @@
|
||||
pFit self = NULL;
|
||||
int iRet;
|
||||
char pBueffel[256];
|
||||
pDynString buf = NULL;
|
||||
|
||||
self = (pFit)pData;
|
||||
assert(self);
|
||||
@ -466,10 +467,18 @@
|
||||
sprintf(pBueffel,"%f", self->fCenter);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
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 */
|
||||
SCStartBuffering(pCon);
|
||||
sprintf(pBueffel,"Estimated Peak Center: %f, StdDev: %f \n",
|
||||
self->fCenter,self->fStddev);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
@ -477,6 +486,10 @@
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
sprintf(pBueffel,"Approximate FWHM: %f\n",self->FWHM);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
buf = SCEndBuffering(pCon);
|
||||
if(buf != NULL){
|
||||
SCWrite(pCon,GetCharArray(buf),eValue);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
24
fourlib.c
24
fourlib.c
@ -625,6 +625,10 @@ int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4],
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(testFunc(userData, fSet, mask) == 1){
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(psi = .0; psi < 360.; psi += .5){
|
||||
rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi);
|
||||
fTest[0] = stt;
|
||||
@ -638,6 +642,26 @@ int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4],
|
||||
}
|
||||
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) {
|
||||
/*
|
||||
* 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_*/
|
353
hipadaba.c
353
hipadaba.c
@ -38,6 +38,10 @@ static void DeleteNodeData(pHdb node){
|
||||
DeleteCallbackChain(node->writeCallbacks);
|
||||
DeleteCallbackChain(node->updateCallbacks);
|
||||
DeleteCallbackChain(node->readCallbacks);
|
||||
DeleteCallbackChain(node->treeChangeCallbacks);
|
||||
if(node->properties != NULL){
|
||||
DeleteStringDict(node->properties);
|
||||
}
|
||||
|
||||
if(node->name != NULL){
|
||||
free(node->name);
|
||||
@ -52,8 +56,24 @@ static void DeleteNodeData(pHdb 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 current = NULL;
|
||||
|
||||
@ -68,6 +88,8 @@ void RemoveHdbNodeFromParent(pHdb node){
|
||||
current = current->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;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
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)
|
||||
{
|
||||
@ -270,9 +276,9 @@ hdbValue makeHdbValue(int datatype, int length){
|
||||
case HIPINTAR:
|
||||
case HIPINTVARAR:
|
||||
val.arrayLength = length;
|
||||
val.v.intArray = malloc(length*sizeof(long));
|
||||
val.v.intArray = malloc(length*sizeof(int));
|
||||
if(val.v.intArray != NULL){
|
||||
memset(val.v.intArray,0,length*sizeof(long));
|
||||
memset(val.v.intArray,0,length*sizeof(int));
|
||||
}
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
@ -285,15 +291,71 @@ hdbValue makeHdbValue(int datatype, int length){
|
||||
break;
|
||||
case HIPTEXT:
|
||||
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;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
hdbValue MakeHdbInt(int initValue){
|
||||
hdbValue result;
|
||||
|
||||
result.dataType = HIPINT;
|
||||
result.arrayLength = 1;
|
||||
result.v.intValue = initValue;
|
||||
return result;
|
||||
}
|
||||
@ -302,6 +364,7 @@ hdbValue MakeHdbFloat(double initValue){
|
||||
hdbValue result;
|
||||
|
||||
result.dataType = HIPFLOAT;
|
||||
result.arrayLength = 1;
|
||||
result.v.doubleValue = initValue;
|
||||
return result;
|
||||
}
|
||||
@ -311,10 +374,11 @@ hdbValue MakeHdbText(char *initText){
|
||||
|
||||
result.dataType = HIPTEXT;
|
||||
result.v.text = initText;
|
||||
result.arrayLength = strlen(initText);
|
||||
return result;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
hdbValue MakeHdbIntArray(int length, long *data){
|
||||
hdbValue MakeHdbIntArray(int length, int *data){
|
||||
hdbValue result;
|
||||
|
||||
result.dataType = HIPINTAR;
|
||||
@ -409,6 +473,13 @@ int compareHdbValue(hdbValue v1, hdbValue v2){
|
||||
}
|
||||
return 1;
|
||||
break;
|
||||
case HIPOBJ:
|
||||
if(v2.v.obj == v1.v.obj) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
@ -422,6 +493,35 @@ int cloneHdbValue(hdbValue *source, hdbValue *clone){
|
||||
clone->dataType = source->dataType;
|
||||
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 ========================================*/
|
||||
pHdb MakeHipadabaNode(char *name, int datatype, int length){
|
||||
pHdb pNew = NULL;
|
||||
@ -434,15 +534,19 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length){
|
||||
pNew->magic = HDBMAGICK;
|
||||
pNew->name = strdup(name);
|
||||
pNew->value.dataType = datatype;
|
||||
pNew->properties = CreateStringDict();
|
||||
if(pNew->properties == NULL || pNew->name == NULL){
|
||||
return NULL;
|
||||
}
|
||||
switch(datatype){
|
||||
case HIPINTAR:
|
||||
case HIPINTVARAR:
|
||||
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){
|
||||
return NULL;
|
||||
}
|
||||
memset(pNew->value.v.intArray,0,length*sizeof(long));
|
||||
memset(pNew->value.v.intArray,0,length*sizeof(int));
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
case HIPFLOATVARAR:
|
||||
@ -454,16 +558,20 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length){
|
||||
memset(pNew->value.v.floatArray,0,length*sizeof(double));
|
||||
break;
|
||||
case HIPTEXT:
|
||||
pNew->value.arrayLength = length;
|
||||
pNew->value.v.text = strdup("UNKNOWN");
|
||||
break;
|
||||
}
|
||||
return pNew;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void AddHipadabaChild(pHdb parent, pHdb child){
|
||||
void AddHipadabaChild(pHdb parent, pHdb child, void *callData){
|
||||
pHdb current = NULL, prev = NULL;
|
||||
|
||||
assert(parent != NULL && child != NULL);
|
||||
assert(parent != NULL);
|
||||
if(child == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
current = parent->child;
|
||||
child->mama = parent;
|
||||
@ -481,16 +589,18 @@ void AddHipadabaChild(pHdb parent, pHdb child){
|
||||
child->next = NULL;
|
||||
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;
|
||||
|
||||
if(node == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveHdbNodeFromParent(node);
|
||||
RemoveHdbNodeFromParent(node, callData);
|
||||
|
||||
DeleteNodeData(node);
|
||||
}
|
||||
@ -637,6 +747,14 @@ void AppendHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
||||
current = node->readCallbacks;
|
||||
}
|
||||
break;
|
||||
case HCBTREE:
|
||||
if(node->treeChangeCallbacks == NULL){
|
||||
node->treeChangeCallbacks = newCB;
|
||||
return;
|
||||
} else {
|
||||
current = node->treeChangeCallbacks;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
@ -649,7 +767,6 @@ void AppendHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
||||
newCB->previous = current;
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void PrependHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
||||
switch(type){
|
||||
@ -683,6 +800,16 @@ void PrependHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
||||
node->readCallbacks = newCB;
|
||||
}
|
||||
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:
|
||||
assert(0);
|
||||
break;
|
||||
@ -695,6 +822,7 @@ void RemoveHipadabaCallback(pHdb root, int id){
|
||||
root->writeCallbacks = DeleteForID(root->writeCallbacks,id);
|
||||
root->updateCallbacks = DeleteForID(root->updateCallbacks,id);
|
||||
root->readCallbacks = DeleteForID(root->readCallbacks,id);
|
||||
root->treeChangeCallbacks = DeleteForID(root->treeChangeCallbacks,id);
|
||||
|
||||
current = root->child;
|
||||
while(current != NULL){
|
||||
@ -709,6 +837,7 @@ void InternalRemoveHipadabaCallback(pHdb root, int internalID){
|
||||
root->writeCallbacks = DeleteForInternalID(root->writeCallbacks,internalID);
|
||||
root->updateCallbacks = DeleteForInternalID(root->updateCallbacks,internalID);
|
||||
root->readCallbacks = DeleteForInternalID(root->readCallbacks,internalID);
|
||||
root->treeChangeCallbacks = DeleteForInternalID(root->treeChangeCallbacks,internalID);
|
||||
|
||||
current = root->child;
|
||||
while(current != NULL){
|
||||
@ -741,24 +870,26 @@ int copyHdbValue(hdbValue *source, hdbValue *target){
|
||||
break;
|
||||
case HIPINTAR:
|
||||
case HIPINTVARAR:
|
||||
if(target->arrayLength != source->arrayLength){
|
||||
if(target->arrayLength != source->arrayLength || target->v.intArray == NULL){
|
||||
if(target->v.intArray != NULL){
|
||||
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){
|
||||
return 0;
|
||||
}
|
||||
memset(target->v.intArray,0,source->arrayLength * sizeof(long));
|
||||
memset(target->v.intArray,0,source->arrayLength * sizeof(int));
|
||||
target->arrayLength = source->arrayLength;
|
||||
}
|
||||
for(i = 0; i < source->arrayLength; i++){
|
||||
target->v.intArray[i] = source->v.intArray[i];
|
||||
if(source->v.intArray != NULL){
|
||||
for(i = 0; i < source->arrayLength; i++){
|
||||
target->v.intArray[i] = source->v.intArray[i];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
case HIPFLOATVARAR:
|
||||
if(target->arrayLength != source->arrayLength){
|
||||
if(target->arrayLength != source->arrayLength || target->v.floatArray == NULL){
|
||||
if(target->v.floatArray != NULL){
|
||||
free(target->v.floatArray);
|
||||
}
|
||||
@ -768,10 +899,15 @@ int copyHdbValue(hdbValue *source, hdbValue *target){
|
||||
}
|
||||
memset(target->v.floatArray,0,source->arrayLength * sizeof(double));
|
||||
target->arrayLength = source->arrayLength;
|
||||
}
|
||||
if(source->v.floatArray != NULL){
|
||||
for(i = 0; i < source->arrayLength; i++){
|
||||
target->v.floatArray[i] = source->v.floatArray[i];
|
||||
}
|
||||
}
|
||||
for(i = 0; i < source->arrayLength; i++){
|
||||
target->v.floatArray[i] = source->v.floatArray[i];
|
||||
}
|
||||
break;
|
||||
case HIPOBJ:
|
||||
target->v.obj = source->v.obj;
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
@ -812,4 +948,149 @@ int GetHipadabaPar(pHdb node, hdbValue *v, void *callData){
|
||||
copyHdbValue(&node->value,v);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
119
hipadaba.h
119
hipadaba.h
@ -20,9 +20,14 @@
|
||||
* copyright: GPL
|
||||
*
|
||||
* Mark Koennecke, June 2006
|
||||
*
|
||||
* Added treeChange callback, Mark Koennecke, November 2006
|
||||
*
|
||||
* Added support for properties, Mark Koennecke, January 2007
|
||||
*/
|
||||
#ifndef HIPADABA
|
||||
#define HIPADABA
|
||||
#include <stringdict.h>
|
||||
|
||||
/*------- datatypes */
|
||||
#define HIPNONE -1
|
||||
@ -33,20 +38,26 @@
|
||||
#define HIPFLOATAR 4
|
||||
#define HIPINTVARAR 5
|
||||
#define HIPFLOATVARAR 6
|
||||
#define HIPOBJ 7
|
||||
/* -------- callback types */
|
||||
#define HCBSET 0
|
||||
#define HCBUPDATE 1
|
||||
#define HCBREAD 2
|
||||
#define HCBTREE 3
|
||||
/*--------- error codes */
|
||||
#define HDBTYPEMISMATCH -7701
|
||||
#define HDBLENGTHMISMATCH -7702
|
||||
/*===================== structure definitions ===================================*/
|
||||
typedef struct __hdbValue {
|
||||
int dataType;
|
||||
int arrayLength;
|
||||
union __value {
|
||||
long intValue;
|
||||
int intValue;
|
||||
double doubleValue;
|
||||
char *text;
|
||||
long *intArray;
|
||||
int *intArray;
|
||||
double *floatArray;
|
||||
void *obj;
|
||||
}v;
|
||||
}hdbValue;
|
||||
/*------------------------------------------------------------------------------*/
|
||||
@ -58,12 +69,15 @@ typedef struct __hipadaba {
|
||||
struct __hdbcallback *writeCallbacks;
|
||||
struct __hdbcallback *updateCallbacks;
|
||||
struct __hdbcallback *readCallbacks;
|
||||
struct __hdbcallback *treeChangeCallbacks;
|
||||
char *name;
|
||||
hdbValue value;
|
||||
int protected;
|
||||
pStringDict properties;
|
||||
}Hdb, *pHdb;
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
typedef int (*hdbCallbackFunction)(void *userData, void *callData,
|
||||
pHdb currentNode, hdbValue v );
|
||||
pHdb currentNode, hdbValue v);
|
||||
typedef void (*killUserData)(void *data);
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
typedef struct __hdbcallback {
|
||||
@ -77,6 +91,15 @@ typedef struct __hdbcallback {
|
||||
}hdbCallback, *pHdbCallback;
|
||||
/*======================== Function protoypes: hdbData ========================*/
|
||||
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
|
||||
* @param initValue the initial value of the int
|
||||
@ -107,7 +130,7 @@ hdbValue MakeHdbText(char *initText);
|
||||
* data points to dynamically allocated memory.
|
||||
* @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
|
||||
* @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
|
||||
*/
|
||||
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 =======================*/
|
||||
/**
|
||||
* make a new hipadaba node
|
||||
@ -156,16 +185,18 @@ int cloneHdbValue(hdbValue *source, hdbValue *clone);
|
||||
*/
|
||||
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 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
|
||||
* @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
|
||||
* @param node The node to check
|
||||
@ -189,8 +220,9 @@ char *GetHipadabaPath(pHdb node);
|
||||
/**
|
||||
* removes a node from the parents child list.
|
||||
* @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
|
||||
* @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);
|
||||
/**
|
||||
* Update a hipadaba parameter. This is an internal update of a parameter, during
|
||||
* driving etc.
|
||||
* Update a hipadaba parameter. This is an internal update of a parameter,
|
||||
* during driving etc.
|
||||
* @param node The node for which to update the parameter
|
||||
* @param v The new value for the node
|
||||
* @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
|
||||
*/
|
||||
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
|
||||
|
87
histmem.c
87
histmem.c
@ -68,6 +68,10 @@
|
||||
/*
|
||||
#define LOADDEBUG 1
|
||||
*/
|
||||
/*
|
||||
* from histregress.c
|
||||
*/
|
||||
extern pHistDriver CreateRegressHM(pStringDict pOpt);
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int HistHalt(void *pData)
|
||||
{
|
||||
@ -171,7 +175,9 @@
|
||||
iRet = self->pDriv->Start(self->pDriv, pCon);
|
||||
if(iRet == OKOK)
|
||||
{
|
||||
updateHMData(self->pDriv->data);
|
||||
/* send a COUNTSTART event */
|
||||
InvokeCallBack(self->pCall,COUNTSTART,pCon);
|
||||
updateHMData(self->pDriv->data);
|
||||
return iRet;
|
||||
}
|
||||
else
|
||||
@ -450,8 +456,12 @@
|
||||
}
|
||||
else if(strcmp(driver,"mcstas") == 0)
|
||||
{
|
||||
pNew->pDriv = NewMcStasHM(pOption);
|
||||
}
|
||||
pNew->pDriv = NewMcStasHM(pOption);
|
||||
}
|
||||
else if(strcmp(driver,"regress") == 0)
|
||||
{
|
||||
pNew->pDriv = CreateRegressHM(pOption);
|
||||
}
|
||||
else
|
||||
{
|
||||
site = getSite();
|
||||
@ -721,8 +731,6 @@ void HistDirty(pHistMem self)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
/* send a COUNTSTART event */
|
||||
InvokeCallBack(self->pCall,COUNTSTART,pCon);
|
||||
|
||||
/* start */
|
||||
return StartDevice(GetExecutor(),"HistogramMemory", self->pDes, self,
|
||||
@ -744,9 +752,6 @@ void HistDirty(pHistMem self)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* send a COUNTSTART event */
|
||||
InvokeCallBack(self->pCall,COUNTSTART,pCon);
|
||||
|
||||
/* wait till end */
|
||||
iRet = Wait4Success(GetExecutor());
|
||||
if(iRet == DEVINT)
|
||||
@ -1233,13 +1238,19 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
}
|
||||
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))
|
||||
{
|
||||
iRet = HistConfigure(self,pCon,pSics);
|
||||
if(iRet)
|
||||
{
|
||||
self->iInit = 1;
|
||||
SCSendOK(pCon);
|
||||
SCSendOK(pCon);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1357,6 +1368,31 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
}
|
||||
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 */
|
||||
{
|
||||
/* check parameters, first required: no of Hist */
|
||||
@ -1383,11 +1419,16 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
iStart = 0;
|
||||
}
|
||||
|
||||
if(argc > 4){
|
||||
iEnd = checkHMEnd(self,argv[4]);
|
||||
} else {
|
||||
iEnd = checkHMEnd(self,NULL);
|
||||
}
|
||||
if(argc > 4){
|
||||
iEnd = checkHMEnd(self,argv[4]);
|
||||
} else {
|
||||
iEnd = checkHMEnd(self,NULL);
|
||||
}
|
||||
|
||||
if(iNum != 0 && argc > 4)
|
||||
{
|
||||
iEnd = atoi(argv[4]);
|
||||
}
|
||||
|
||||
/* allocate data storage and get it */
|
||||
lData = (HistInt *)malloc(iEnd*sizeof(HistInt));
|
||||
@ -1397,8 +1438,14 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
return 0;
|
||||
}
|
||||
memset(lData,0,iEnd*sizeof(HistInt));
|
||||
iRet = GetHistogram(self,pCon,iNum,iStart,iEnd,
|
||||
lData,iEnd*sizeof(long));
|
||||
if(iNum == 0)
|
||||
{
|
||||
iRet = GetHistogram(self,pCon,iNum,iStart,iEnd,
|
||||
lData,iEnd*sizeof(long));
|
||||
} else {
|
||||
iRet = GetHistogramDirect(self,pCon,iNum,iStart, iEnd,
|
||||
lData, iEnd*sizeof(long));
|
||||
}
|
||||
if(!iRet)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot retrieve histogram %d",iNum);
|
||||
@ -1565,10 +1612,10 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
else if(strcmp(argv[1],"timebin") == 0)
|
||||
{
|
||||
Tcl_DStringInit(&tResult);
|
||||
Tcl_DStringAppend(&tResult,"histogram.timebins = ",-1);
|
||||
Tcl_DStringAppend(&tResult,"histogram.timebins =",-1);
|
||||
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);
|
||||
}
|
||||
/* Write it */
|
||||
@ -1586,8 +1633,8 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
return 0;
|
||||
}
|
||||
if(GetStatus() == eCounting)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot modify timebinning while counting",
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot modify timebinning while counting",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
@ -163,6 +163,9 @@ $\langle$HistType {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ SConnection *pCon);@\\
|
||||
\mbox{}\verb@ float (*GetTime)(pHistDriver self,@\\
|
||||
\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@ SConnection *pCon,@\\
|
||||
\mbox{}\verb@ HistInt iVal);@\\
|
||||
|
@ -130,6 +130,9 @@ definition:
|
||||
SConnection *pCon);
|
||||
float (*GetTime)(pHistDriver self,
|
||||
SConnection *pCon);
|
||||
HistInt *(*SubSample)(pHistDriver self,
|
||||
SConnection *pCon,int bank,
|
||||
char *command);
|
||||
int (*Preset)(pHistDriver self,
|
||||
SConnection *pCon,
|
||||
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;
|
||||
}
|
||||
}
|
||||
else if(iSet == 2)
|
||||
{
|
||||
for(ii = iStart; ii < iEnd; ii++)
|
||||
{
|
||||
lData[ii-iStart] = self->data->localBuffer[ii];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(ii = iStart; ii < iEnd; ii++)
|
||||
@ -196,7 +203,7 @@
|
||||
static int SimSetHistogram(pHistDriver self, SConnection *pCon,
|
||||
int i, int iStart, int iEnd, HistInt *lData)
|
||||
{
|
||||
iSet = 1;
|
||||
iSet = 2;
|
||||
iSetVal = lData[0];
|
||||
return 1;
|
||||
}
|
||||
|
89
hkl.c
89
hkl.c
@ -61,7 +61,6 @@
|
||||
fprintf(fd,"%s hm %d\n",name, self->iHM);
|
||||
fprintf(fd,"%s scantolerance %f\n", name,self->scanTolerance);
|
||||
fprintf(fd,"%s nb %d\n", name, self->iNOR);
|
||||
fprintf(fd,"%s phiom %d\n", name, self->iOMPHI);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -689,7 +688,7 @@ int hklInRange(void *data, float fSet[4], int mask[4])
|
||||
fSet[0] = dTheta;
|
||||
|
||||
/* for omega check against the limits +- SCANBORDER in order to allow for
|
||||
a omega scan
|
||||
a omega scan.
|
||||
*/
|
||||
MotorGetPar(self->pOmega,"softlowerlim",&fLimit);
|
||||
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)
|
||||
{
|
||||
double stt, om, chi, phi, psi, ompsi, chipsi, phipsi;
|
||||
int i, test;
|
||||
int i, test, mask[4];
|
||||
|
||||
/*
|
||||
just the plain angle calculation
|
||||
@ -731,16 +730,31 @@ static int calculateBisecting(MATRIX z1, pHKL self, SConnection *pCon,
|
||||
return 0;
|
||||
}
|
||||
|
||||
fSet[0] = stt;
|
||||
fSet[1] = om;
|
||||
fSet[2] = chi;
|
||||
fSet[3] = phi;
|
||||
if(iRetry == 1) {
|
||||
rotatePsi(om,chi,phi,psi,&ompsi,&chipsi,&phipsi);
|
||||
rotatePsi(om,chi,phi,myPsi,&ompsi,&chipsi,&phipsi);
|
||||
fSet[1] = ompsi;
|
||||
fSet[2] = circlify(chipsi);
|
||||
fSet[3] = circlify(phipsi);
|
||||
return 1;
|
||||
} else {
|
||||
return findAllowedBisecting(self->fLambda, z1, fSet, hklInRange,self);
|
||||
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 {
|
||||
return findAllowedBisecting(self->fLambda, z1, fSet, hklInRange,self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
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);
|
||||
omnb += 180.;
|
||||
/* omnb += 180.; */
|
||||
mat_free(z3);
|
||||
if(status != 1)
|
||||
{
|
||||
@ -789,7 +803,11 @@ static int calculateNormalBeam(MATRIX z1, pHKL self, SConnection *pCon,
|
||||
if(checkNormalBeam(omnb, &gamma, nu,fSet,pCon,self)){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
if(checkNormalBeam(omnb + 360., &gamma, nu, fSet,pCon,self)){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
@ -850,7 +868,7 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
|
||||
{
|
||||
if(checkNormalBeam(om, &gamma, nu,fSet,pCon,self))
|
||||
{
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -903,31 +921,7 @@ static int calculateNormalBeamOmega(MATRIX z1, pHKL self,
|
||||
if(self->iNOR == 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
status = calculateNormalBeam(z1,self,pCon,fSet, myPsi, iRetry);
|
||||
@ -1414,8 +1408,8 @@ ente:
|
||||
if(strcmp(argv[1],"list") == 0 )
|
||||
{
|
||||
sprintf(pBueffel,
|
||||
"lambda = %f Normal Beam = %d PHIOM = %d Quadrant = %d HM = %d",
|
||||
self->fLambda, self->iNOR, self->iOMPHI,
|
||||
"lambda = %f Normal Beam = %d Quadrant = %d HM = %d",
|
||||
self->fLambda, self->iNOR,
|
||||
self->iQuad,self->iHM);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
sprintf(pBueffel,"UB = { %f %f %f",
|
||||
@ -1654,29 +1648,6 @@ ente:
|
||||
SCSendOK(pCon);
|
||||
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 */
|
||||
else if(strcmp(argv[1],"quadrant") == 0)
|
||||
{
|
||||
|
1
hkl.i
1
hkl.i
@ -15,7 +15,6 @@
|
||||
int iManual;
|
||||
double fLastHKL[5];
|
||||
int iNOR;
|
||||
int iOMPHI;
|
||||
int iQuad;
|
||||
int iHM;
|
||||
pMotor pTheta;
|
||||
|
1
hkl.tex
1
hkl.tex
@ -26,7 +26,6 @@ $\langle$hkldat {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ int iManual;@\\
|
||||
\mbox{}\verb@ double fLastHKL[5];@\\
|
||||
\mbox{}\verb@ int iNOR;@\\
|
||||
\mbox{}\verb@ int iOMPHI;@\\
|
||||
\mbox{}\verb@ int iQuad;@\\
|
||||
\mbox{}\verb@ int iHM;@\\
|
||||
\mbox{}\verb@ pMotor pTheta;@\\
|
||||
|
1
hkl.w
1
hkl.w
@ -21,7 +21,6 @@ The object uses the following object data structure:
|
||||
int iManual;
|
||||
double fLastHKL[5];
|
||||
int iNOR;
|
||||
int iOMPHI;
|
||||
int iQuad;
|
||||
int iHM;
|
||||
pMotor pTheta;
|
||||
|
@ -310,7 +310,7 @@ int HMControlAction(SConnection *pCon, SicsInterp *pSics,
|
||||
assert(self);
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
130
hmdata.c
130
hmdata.c
@ -5,11 +5,15 @@
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, January 2003
|
||||
|
||||
Added loading HM data from file, Mark Koennecke, November 2006
|
||||
-------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include "splitter.h"
|
||||
#include "fortify.h"
|
||||
#include "hmdata.h"
|
||||
#include "HistMem.h"
|
||||
@ -46,7 +50,7 @@ void clearHMData(pHMdata self){
|
||||
size *= self->iDim[i];
|
||||
}
|
||||
if(self->tofMode){
|
||||
size *= self->nTimeChan;
|
||||
size *= getNoOfTimebins(self);
|
||||
}
|
||||
memset(self->localBuffer,0,size*sizeof(HistInt));
|
||||
}
|
||||
@ -60,7 +64,7 @@ static int resizeBuffer(pHMdata self){
|
||||
size *= self->iDim[i];
|
||||
}
|
||||
if(self->tofMode){
|
||||
size *= self->nTimeChan;
|
||||
size *= getNoOfTimebins(self);
|
||||
}
|
||||
if(self->localBuffer != NULL){
|
||||
free(self->localBuffer);
|
||||
@ -80,6 +84,7 @@ int configureHMdata(pHMdata self, pStringDict pOpt,
|
||||
int status, i;
|
||||
float fVal;
|
||||
char pValue[80];
|
||||
pHistMem master = NULL;
|
||||
|
||||
if(self->nTimeChan > 2) {
|
||||
self->tofMode = 1;
|
||||
@ -111,6 +116,18 @@ int configureHMdata(pHMdata self, pStringDict pOpt,
|
||||
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
|
||||
*/
|
||||
@ -138,7 +155,7 @@ int configureHMdata(pHMdata self, pStringDict pOpt,
|
||||
int genTimeBinning(pHMdata self, float start, float step, int noSteps){
|
||||
int i;
|
||||
|
||||
if(noSteps >= MAXCHAN){
|
||||
if(noSteps >= MAXCHAN || self->timeslave != NULL){
|
||||
return 0;
|
||||
}
|
||||
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){
|
||||
if(self->timeslave != NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(index >= 0 && index < MAXCHAN){
|
||||
self->timeBinning[index] = value;
|
||||
} else {
|
||||
@ -157,7 +178,7 @@ int setTimeBin(pHMdata self, int index, float value){
|
||||
}
|
||||
self->tofMode = 1;
|
||||
if(index > self->nTimeChan){
|
||||
self->nTimeChan = index;
|
||||
self->nTimeChan = index+1;
|
||||
return resizeBuffer(self);
|
||||
}
|
||||
return 1;
|
||||
@ -168,17 +189,27 @@ int isInTOFMode(pHMdata self){
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
int getNoOfTimebins(pHMdata self){
|
||||
return self->nTimeChan;
|
||||
if(self->timeslave != NULL){
|
||||
return getNoOfTimebins(self->timeslave);
|
||||
} else {
|
||||
return self->nTimeChan;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
float *getTimeBinning(pHMdata self){
|
||||
return self->timeBinning;
|
||||
if(self->timeslave != NULL){
|
||||
return getTimeBinning(self->timeslave);
|
||||
} else {
|
||||
return self->timeBinning;
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
void clearTimeBinning(pHMdata self){
|
||||
self->nTimeChan = 1;
|
||||
self->tofMode = 0;
|
||||
resizeBuffer(self);
|
||||
if(self->timeslave == NULL){
|
||||
self->nTimeChan = 1;
|
||||
self->tofMode = 0;
|
||||
resizeBuffer(self);
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
void getHMDataDim(pHMdata self, int iDim[MAXDIM], int *rank){
|
||||
@ -193,7 +224,7 @@ long getHMDataLength(pHMdata self){
|
||||
length *= self->iDim[i];
|
||||
}
|
||||
if(self->tofMode){
|
||||
length *= self->nTimeChan;
|
||||
length *= getNoOfTimebins(self);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
@ -227,6 +258,10 @@ static int updateHMbuffer(pHistMem hist, int bank, SConnection *pCon){
|
||||
|
||||
assert(self);
|
||||
|
||||
if(self->timeslave != NULL){
|
||||
resizeBuffer(self);
|
||||
}
|
||||
|
||||
for(i = 0; i < 3; i++){
|
||||
status = hist->pDriv->GetHistogram(hist->pDriv,pCon,
|
||||
bank,0,getHMDataLength(self),
|
||||
@ -292,7 +327,7 @@ HistInt *getHMDataBufferPointer(pHistMem hist,SConnection *pCon){
|
||||
|
||||
assert(self);
|
||||
|
||||
if(self->localBuffer == NULL){
|
||||
if(self->localBuffer == NULL || self->timeslave != NULL){
|
||||
resizeBuffer(self);
|
||||
}
|
||||
/*
|
||||
@ -327,7 +362,7 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
||||
int iStart[MAXDIM], int iEnd[MAXDIM]) {
|
||||
HistInt *iData;
|
||||
pHMdata self = hist->pDriv->data;
|
||||
int i, iHistLength, status, iIndex;
|
||||
int i, iHistLength, status, iIndex, myrank;
|
||||
char pBueffel[256];
|
||||
unsigned long lSum, lRowSum;
|
||||
|
||||
@ -336,7 +371,12 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
||||
/*
|
||||
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]) ) {
|
||||
sprintf(pBueffel,"ERROR: %d is out of data dimension range",
|
||||
iStart[i]);
|
||||
@ -367,25 +407,35 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
||||
|
||||
iHistLength = getHMDataLength(self);
|
||||
/* actually sum */
|
||||
switch(self->rank)
|
||||
switch(myrank)
|
||||
{
|
||||
case 1:
|
||||
lSum = SumRow(self->localBuffer, iHistLength,
|
||||
iStart[0], iEnd[0]);
|
||||
break;
|
||||
case 2:
|
||||
lSum = 0;
|
||||
for(i = iStart[0]; i < iEnd[0]; i++){
|
||||
iIndex = i*self->iDim[1];
|
||||
lRowSum = SumRow(self->localBuffer,iHistLength,
|
||||
if(isInTOFMode(self)){
|
||||
lSum = 0;
|
||||
for(i = iStart[0]; i < iEnd[0]; i++){
|
||||
iIndex = i*self->iDim[1];
|
||||
lRowSum = SumRow(self->localBuffer,iHistLength,
|
||||
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;
|
||||
default:
|
||||
sprintf(pBueffel,
|
||||
"ERROR: summing in %d dimensions not yet implemented",
|
||||
self->rank);
|
||||
myrank);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return -1;
|
||||
break;
|
||||
@ -395,3 +445,43 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
|
||||
}
|
||||
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
|
||||
|
||||
|
||||
typedef struct {
|
||||
typedef struct __hmdata{
|
||||
int rank;
|
||||
int iDim[MAXDIM];
|
||||
int nTimeChan;
|
||||
@ -26,6 +26,7 @@
|
||||
int updateIntervall;
|
||||
int updateFlag;
|
||||
HistInt *localBuffer;
|
||||
struct __hmdata *timeslave;
|
||||
} HMdata, *pHMdata;
|
||||
|
||||
|
||||
@ -56,6 +57,7 @@
|
||||
|
||||
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
|
||||
int start[MAXDIM], int end[MAXDIM]);
|
||||
int loadHMData(pHMdata self, SConnection *pCon, char *filename);
|
||||
|
||||
|
||||
#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:
|
||||
@d hmdatadat @{
|
||||
typedef struct {
|
||||
typedef struct __hmdata{
|
||||
int rank;
|
||||
int iDim[MAXDIM];
|
||||
int nTimeChan;
|
||||
@ -21,6 +21,7 @@ In order to do this, the following data structure is needed:
|
||||
int updateIntervall;
|
||||
int updateFlag;
|
||||
HistInt *localBuffer;
|
||||
struct __hmdata *timeslave;
|
||||
} HMdata, *pHMdata;
|
||||
@}
|
||||
|
||||
@ -52,6 +53,7 @@ The following functions work on this data structure:
|
||||
|
||||
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
|
||||
int start[MAXDIM], int end[MAXDIM]);
|
||||
int loadHMData(pHMdata self, SConnection *pCon, char *filename);
|
||||
@}
|
||||
|
||||
\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!
|
||||
\item[sumHMDataRectangle] sums a rectangular box delimted by start and end
|
||||
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}
|
||||
|
||||
|
||||
|
@ -12,8 +12,9 @@ Markus Zolliker, March 2005
|
||||
|
||||
typedef struct Item {
|
||||
struct Item *next;
|
||||
const char *type;
|
||||
const char *name;
|
||||
char *type;
|
||||
char *name;
|
||||
char *desc;
|
||||
Initializer maker;
|
||||
int startupOnly;
|
||||
} Item;
|
||||
@ -21,15 +22,17 @@ typedef struct Item {
|
||||
static Item *list = NULL;
|
||||
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 = calloc(1, sizeof *item);
|
||||
assert(item);
|
||||
item->maker = maker;
|
||||
item->next = list;
|
||||
item->type = type;
|
||||
item->name = name;
|
||||
item->type = strdup(type);
|
||||
item->name = strdup(name);
|
||||
item->desc = strdup(desc);
|
||||
item->startupOnly = startupOnly;
|
||||
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,
|
||||
void *data, int argc, char *argv[]) {
|
||||
CmdInitializer cmdin;
|
||||
@ -91,7 +128,7 @@ static int RemoveObject(SConnection *con, SicsInterp *sics,
|
||||
char *className;
|
||||
|
||||
if (argc != 2) {
|
||||
SCPrintf(con, eError, "%s has 1 argument", argv[0]);
|
||||
SCPrintf(con, eError, "%s needs 1 argument", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -124,16 +161,20 @@ static void KillInitializers(void *data) {
|
||||
item = list;
|
||||
while (item) {
|
||||
next = item->next;
|
||||
if (item->name) free(item->name);
|
||||
if (item->type) free(item->type);
|
||||
if (item->desc) free(item->desc);
|
||||
free(item);
|
||||
item = next;
|
||||
}
|
||||
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")) {
|
||||
AddCommandWithFlag(pServ->pSics, "MakeObject", MakeObject, KillInitializers, 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);
|
||||
|
||||
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
|
||||
|
||||
@ -54,7 +55,8 @@ typedef int (*CmdInitializer) (SConnection *pCon, int argc, char *argv[], int dy
|
||||
- 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.
|
||||
- startupOnly: the driver creation should only be possible at startup
|
||||
|
@ -34,7 +34,7 @@
|
||||
/*-------------------------- conversion routines -------------------------*/
|
||||
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)
|
||||
@ -44,7 +44,7 @@
|
||||
assert(self->length > 0.);
|
||||
|
||||
dt = fX/self->length;
|
||||
return RD*asin(dt) - self->zero;
|
||||
return RD*atan(dt) - self->zero;
|
||||
}
|
||||
/*============== functions in the interface ============================*/
|
||||
static void *Lin2AngGetInterface(void *pData, int iID)
|
||||
|
@ -9,4 +9,4 @@
|
||||
|
||||
MFLAGS=-f makefile_linux$(DUMMY)
|
||||
|
||||
HDFROOT=/afs/psi.ch/project/sinq/sl-linux
|
||||
HDFROOT=/usr/local
|
||||
|
134
macro.c
134
macro.c
@ -2,7 +2,7 @@
|
||||
|
||||
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
|
||||
strong Tcl-interpreter to SICS. The problem is that Tcl does not
|
||||
know anything about connections and our error handling. We have
|
||||
@ -770,6 +770,127 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
||||
}
|
||||
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 argc, char *argv[])
|
||||
@ -891,14 +1012,9 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
||||
if (pCommand != pBueffel) free(pCommand);
|
||||
if(iRet == TCL_OK)
|
||||
{
|
||||
/* we do not now why, but at some time it was found that
|
||||
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);
|
||||
if(strlen(pTcl->result) > 0){
|
||||
SCPrintf(pCon, eStatus, "%s", pTcl->result);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
|
3
macro.h
3
macro.h
@ -14,6 +14,7 @@
|
||||
#ifndef SICSMACRO
|
||||
#define SICSMACRO
|
||||
#include <tcl.h>
|
||||
#include "sics.h"
|
||||
#include "SCinter.h"
|
||||
|
||||
Tcl_Interp *MacroInit(SicsInterp *pInter);
|
||||
@ -30,6 +31,8 @@
|
||||
int argc, char *argv[]);
|
||||
int ClientPut(SConnection *pCon, SicsInterp *pInter, void *pData,
|
||||
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 argc, char *argv[]);
|
||||
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\
|
||||
hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.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
|
||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||
VELOOBJ = velo.o velosim.o
|
||||
|
||||
.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
|
||||
|
||||
|
@ -6,11 +6,11 @@
|
||||
# Markus Zolliker, March 2003
|
||||
#==========================================================================
|
||||
# assign if the National Instrument GPIB driver is available
|
||||
SINQDIR=/afs/psi.ch/project/sinq
|
||||
NI=
|
||||
#NI= -DHAVENI
|
||||
#NIOBJ= nigpib.o
|
||||
#NILIB=$(SINQDIR)/linux/lib/cib.o
|
||||
SINQDIR=/usr/local
|
||||
#NI=
|
||||
NI= -DHAVENI
|
||||
NIOBJ= nigpib.o
|
||||
NILIB=$(SINQDIR)/lib/cib.o
|
||||
|
||||
include linux_def
|
||||
|
||||
@ -26,7 +26,7 @@ SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \
|
||||
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\
|
||||
-ltcl8.4 -lmxml $(HDFROOT)/lib/libhdf5.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
|
||||
|
||||
|
@ -26,7 +26,7 @@ SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \
|
||||
LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\
|
||||
-ltcl8.3 $(HDFROOT)/lib/libhdf5.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
|
||||
|
||||
|
110
maximize.c
110
maximize.c
@ -47,6 +47,7 @@
|
||||
#include "counter.h"
|
||||
#include "drive.h"
|
||||
#include "maximize.h"
|
||||
#include "motor.h"
|
||||
|
||||
#define MAXPTS 100
|
||||
#define DEBUG 1
|
||||
@ -55,6 +56,7 @@
|
||||
pObjectDescriptor pDes;
|
||||
pCounter pCount;
|
||||
int i360;
|
||||
int maxpts;
|
||||
}Maxxii;
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
@ -134,7 +136,25 @@
|
||||
}
|
||||
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,
|
||||
float fStep, CounterMode eMode,
|
||||
@ -159,27 +179,27 @@
|
||||
start:
|
||||
lMax = 0;
|
||||
lMin = 0x7fffffff;
|
||||
fStart = pDriv->GetValue(pVar,pCon);
|
||||
fStart = readMPDrivable(pVar,pCon);
|
||||
if(fStart < -999999.)
|
||||
{
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* search to the left until out of space or lCts < lMax/2. */
|
||||
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 */
|
||||
fPos = fStart - (MAXPTS/2 - i)*fStep;
|
||||
fPos = fStart - (self->maxpts/2 - i)*fStep;
|
||||
fPos = in360(self,fPos);
|
||||
if(maxDrive(pVar,pVarName,fPos,pCon) != 1)
|
||||
{
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
x[i] = pDriv->GetValue(pVar,pCon);
|
||||
x[i] = readMPDrivable(pVar,pCon);
|
||||
/* count */
|
||||
if(maxCount(self->pCount,eMode,fPreset, &lCts,pCon) != 1)
|
||||
{
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* print a message */
|
||||
@ -218,7 +238,7 @@
|
||||
goto start;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
@ -227,7 +247,7 @@
|
||||
/* next case: all of the peak in measured 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)
|
||||
{
|
||||
@ -246,16 +266,16 @@
|
||||
lMin = 100000;
|
||||
lMax = -100000;
|
||||
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 */
|
||||
fPos = fStart + (i - MAXPTS/2) * fStep;
|
||||
fPos = fStart + (i - self->maxpts/2) * fStep;
|
||||
fPos = in360(self,fPos);
|
||||
if(maxDrive(pVar,pVarName,fPos,pCon) != 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
x[i] = pDriv->GetValue(pVar,pCon);
|
||||
x[i] = readMPDrivable(pVar,pCon);
|
||||
/* count */
|
||||
if(maxCount(self->pCount,eMode,fPreset, &lCts,pCon) != 1)
|
||||
{
|
||||
@ -292,18 +312,18 @@
|
||||
iTop = i;
|
||||
iTop++;
|
||||
/* 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;
|
||||
}
|
||||
/* second case: no peak */
|
||||
if( (iTop > MAXPTS-2) )
|
||||
if( (iTop > self->maxpts-2) )
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no peak found!",eError);
|
||||
return 0;
|
||||
}
|
||||
/* third case: normal peak */
|
||||
if(y[MAXPTS/2] >= 0.5*lMax)
|
||||
if(y[self->maxpts/2] >= 0.5*lMax)
|
||||
{
|
||||
iTop--;
|
||||
}
|
||||
@ -313,7 +333,7 @@
|
||||
*/
|
||||
else
|
||||
{
|
||||
for(i = MAXPTS/2; i < MAXPTS; i++)
|
||||
for(i = self->maxpts/2; i < self->maxpts; i++)
|
||||
{
|
||||
if(y[i] > lMax/2)
|
||||
{
|
||||
@ -325,7 +345,7 @@
|
||||
}
|
||||
} /* 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);
|
||||
return 0;
|
||||
@ -420,11 +440,14 @@
|
||||
pNew->pDes = CreateDescriptor("Maximizer");
|
||||
pNew->pCount = pCom->pData;
|
||||
pNew->i360 = 0;
|
||||
pNew->maxpts = 100;
|
||||
|
||||
AddCommand(pSics,"max",MaximizeAction,MaxKill,pNew);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------*/
|
||||
/*------------------------------------------------------------------
|
||||
* max motor step preset mode
|
||||
* ---------------------------------------------------------------------*/
|
||||
int MaximizeAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
@ -434,7 +457,7 @@
|
||||
double dVal;
|
||||
float fStep, fPreset;
|
||||
CounterMode eCount;
|
||||
int iRet;
|
||||
int iRet, iVal;
|
||||
|
||||
self = (pMax)pData;
|
||||
assert(self);
|
||||
@ -446,9 +469,56 @@
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* enough arguments ?*/
|
||||
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",
|
||||
eError);
|
||||
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
|
||||
#
|
||||
# Mark Koennecke, May 2004
|
||||
# This is a special version for virtual DMC on lns00
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
proc storeMonochromator {} {
|
||||
@ -75,14 +76,34 @@ proc makeLinks {} {
|
||||
nxscript makelink dana dtnstep
|
||||
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
|
||||
#-------------------------------------------------------------------------
|
||||
proc storedata {} {
|
||||
global home
|
||||
set fil [newFileName]
|
||||
global home wwwMode
|
||||
|
||||
if {$wwwMode == 1} {
|
||||
set fil [makeSimFileName]
|
||||
} else {
|
||||
set fil [newFileName]
|
||||
}
|
||||
lastdatafile $fil
|
||||
clientput "Opening $fil for writing"
|
||||
nxscript create4 $fil $home/dmc.dic
|
||||
nxscript createxml $fil $home/dmc.dic
|
||||
|
||||
writeStandardAttributes $fil
|
||||
writeTextVar etitle title
|
||||
|
@ -1,13 +1,19 @@
|
||||
# --------------------------------------------------------------------------
|
||||
#--------------------------------------------------------------------------
|
||||
# Initialization script for a virtual DMC instrument using a McStas
|
||||
# simulationas a data source
|
||||
#
|
||||
# Dr. Mark Koennecke, June 2005
|
||||
#---------------------------------------------------------------------------
|
||||
# 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
|
||||
#ServerOption RedirectFile $home/stdcdmc
|
||||
ServerOption ReadTimeOut 10
|
||||
@ -120,18 +126,20 @@ SicsDataPrefix vdmc
|
||||
#--------- make data number
|
||||
MakeDataNumber SicsDataNumber $home/DataNumber
|
||||
VarMake SicsDataPostFix Text Internal
|
||||
SicsDataPostFix ".hdf"
|
||||
SicsDataPostFix ".xml"
|
||||
VarMake Adress Text User
|
||||
VarMake phone Text User
|
||||
VarMake fax Text User
|
||||
VarMake email Text User
|
||||
VarMake sample_mur Float User
|
||||
VarMake lastdatafile Text User
|
||||
#--------------------------------------------------------------------------
|
||||
# P R O C E D U R E S
|
||||
#--------------------------------------------------------------------------
|
||||
MakeDrive
|
||||
MakeBatchManager
|
||||
MakeNXScript
|
||||
MakeRuenBuffer
|
||||
#-------------------- initialize scripted commands
|
||||
source $home/vdmccom.tcl
|
||||
#-------------------- configure commandlog
|
||||
@ -139,7 +147,6 @@ commandlog auto
|
||||
commandlog intervall 5
|
||||
|
||||
#----------- enable sycamore
|
||||
#InstallProtocolHandler
|
||||
#InstallSinfox
|
||||
#source sycFormat.tcl
|
||||
#source /usr/lib/tcllib1.6.1/stooop/stooop.tcl
|
||||
@ -147,3 +154,95 @@ commandlog intervall 5
|
||||
#source sinfo.tcl
|
||||
#source sycamore.tcl
|
||||
#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 sample User
|
||||
Publish wwwsics Spy
|
||||
Publish wwwfilefornumber Spy
|
||||
mcinstall
|
||||
Publish gethm Spy
|
||||
}
|
||||
source $home/log.tcl
|
||||
source $home/nxsupport.tcl
|
||||
@ -38,12 +40,19 @@ proc washlazy {name} {
|
||||
if { [string first "H K L THETA 2THETA D VALUE" $line] > 0} {
|
||||
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
|
||||
puts $out "// mult Q(hkl) F2 DW w"
|
||||
clientput "HKL found at: $line"
|
||||
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"\
|
||||
h k l th th2 d di sin h2 k2 l2 I F A B ang mul]
|
||||
clientput "Line = $num, $line"
|
||||
if { $num == 17} {
|
||||
set q [expr (2.*3.14159265358979323846)/$d]
|
||||
set f2 [expr $F * $F]
|
||||
@ -155,6 +164,7 @@ proc rundmcoptsim {mode preset } {
|
||||
} else {
|
||||
return $msg
|
||||
}
|
||||
wait 5
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc copydmcdataold { } {
|
||||
@ -363,7 +373,7 @@ proc wwwpar {type mot} {
|
||||
}
|
||||
#------------- wwwuser formats user information into a html table
|
||||
proc wwwuser {} {
|
||||
lappend list title sample user email phone adress
|
||||
lappend list title user email phone adress
|
||||
append txt "<table>"
|
||||
foreach e $list {
|
||||
set ret [catch {$e} msg]
|
||||
@ -376,6 +386,14 @@ proc wwwuser {} {
|
||||
}
|
||||
return $txt
|
||||
}
|
||||
|
||||
#------------- wwwfilefornumber returns the path to a data file for a
|
||||
# number
|
||||
proc wwwfilefornumber {num} {
|
||||
return [makeSimForNum $num]
|
||||
}
|
||||
#-------------------------------------------------------------------
|
||||
proc gethm {} {
|
||||
banana uuget 0
|
||||
}
|
||||
|
||||
|
||||
|
64
mesure.c
64
mesure.c
@ -33,6 +33,7 @@
|
||||
#include "fourtable.h"
|
||||
#include "lld.h"
|
||||
#include "stdscan.h"
|
||||
#include "exeman.h"
|
||||
|
||||
extern void SNXFormatTime(char *pBueffel, int iLen);
|
||||
extern float nintf(float f);
|
||||
@ -445,7 +446,9 @@ static int MesureCalculateSettings(pMesure self, float fHKL[3], float fSet[4],
|
||||
float fPsi, SConnection *pCon)
|
||||
{
|
||||
int status, np;
|
||||
float step, tolerance;
|
||||
float step, tolerance, fHard;
|
||||
char *scanvar = NULL;
|
||||
char buffer[256];
|
||||
|
||||
SetHKLScanTolerance(self->pCryst,.0);
|
||||
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]);
|
||||
tolerance = (step * (float)np)/2. + .2;
|
||||
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,
|
||||
@ -972,7 +994,9 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
static float fMax = 10.;
|
||||
int iRet, i,ii, iLF, iNP;
|
||||
char pBueffel[512], pNum[10], pTime[132];
|
||||
pEVControl pEva = NULL;
|
||||
pEVControl pEva = NULL;
|
||||
pDummy pPtr = NULL;
|
||||
pIDrivable pDriv = NULL;
|
||||
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
@ -1058,7 +1082,20 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
fTemp = -777.77;
|
||||
pEva = (pEVControl)FindCommandData(pServ->pSics,"temperature",
|
||||
"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);
|
||||
}
|
||||
@ -1120,6 +1157,19 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
}
|
||||
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)
|
||||
{
|
||||
@ -1132,7 +1182,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
assert(pCon);
|
||||
|
||||
/* well before doing a thing, open the list file */
|
||||
fd = fopen(pFile,"r");
|
||||
fd = openListFile(pFile);
|
||||
if(!fd)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
|
||||
@ -1221,7 +1271,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
assert(pCon);
|
||||
|
||||
/* well before doing a thing, open the list file */
|
||||
fd = fopen(pFile,"r");
|
||||
fd = openListFile(pFile);
|
||||
if(!fd)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
|
||||
@ -1280,7 +1330,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
assert(pCon);
|
||||
|
||||
/* well before doing a thing, open the list file */
|
||||
fd = fopen(pFile,"r");
|
||||
fd = openListFile(pFile);
|
||||
if(!fd)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: reflection file %s NOT found!",pFile);
|
||||
|
1
modriv.h
1
modriv.h
@ -73,5 +73,6 @@
|
||||
/* ----------------------- Simulation -----------------------------------*/
|
||||
MotorDriver *CreateSIM(SConnection *pCon, int argc, char *argv[]);
|
||||
void KillSIM(void *pData);
|
||||
MotorDriver *RGMakeMotorDriver(void);
|
||||
#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;
|
||||
}
|
||||
|
36
motor.c
36
motor.c
@ -76,13 +76,6 @@
|
||||
#define IGNOREFAULT 10
|
||||
#define MOVECOUNT 11
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
a tiny structure used in CallBack work
|
||||
*/
|
||||
typedef struct {
|
||||
float fVal;
|
||||
char *pName;
|
||||
} MotCallback;
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void *MotorGetInterface(void *pData, int iID)
|
||||
@ -416,7 +409,7 @@ static void handleMoveCallback(pMotor self, SConnection *pCon)
|
||||
|
||||
|
||||
/* create and initialize parameters */
|
||||
pM->ParArray = ObParCreate(12);
|
||||
pM->ParArray = ObParCreate(MOTOBPARLENGTH);
|
||||
if(!pM->ParArray)
|
||||
{
|
||||
free(pM);
|
||||
@ -606,6 +599,7 @@ extern void KillPiPiezo(void *pData);
|
||||
if(iRet == 1)
|
||||
{
|
||||
SCparChange(pCon);
|
||||
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||
return iRet;
|
||||
}
|
||||
}
|
||||
@ -631,6 +625,7 @@ extern void KillPiPiezo(void *pData);
|
||||
fLimit -= fChange;
|
||||
ObParSet(self->ParArray,self->name,"softlowerlim",fLimit,pCon);
|
||||
SCparChange(pCon);
|
||||
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -652,6 +647,7 @@ extern void KillPiPiezo(void *pData);
|
||||
ObParInit(self->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser);
|
||||
}
|
||||
}
|
||||
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||
SCparChange(pCon);
|
||||
|
||||
return iRet;
|
||||
@ -747,10 +743,11 @@ extern void KillPiPiezo(void *pData);
|
||||
}
|
||||
|
||||
/* check boundaries first */
|
||||
iRet = MotorCheckBoundary(self,fNew,&fHard,pBueffel,511);
|
||||
iRet = MotorCheckBoundary(self,fNew,&fHard,pError,131);
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
snprintf(pBueffel,511,"ERROR: %s",pError);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
SCSetInterrupt(pCon,eAbortOperation);
|
||||
return 0;
|
||||
}
|
||||
@ -784,6 +781,7 @@ extern void KillPiPiezo(void *pData);
|
||||
self->retryCount = 0;
|
||||
self->stopped = 0;
|
||||
self->fTarget = fHard;
|
||||
InvokeCallBack(self->pCall,HDBVAL,self);
|
||||
self->posCount = 0;
|
||||
iRet = self->pDriver->RunTo(self->pDriver,fHard);
|
||||
if(iRet != OKOK)
|
||||
@ -1024,7 +1022,22 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
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
|
||||
{
|
||||
site = getSite();
|
||||
@ -1085,7 +1098,6 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
||||
{
|
||||
self->pDriver->ListDriverPar(self->pDriver,self->name, pCon);
|
||||
}
|
||||
SCWrite(pCon,"ENDLIST",eFinish);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void MotorReset(pMotor pM)
|
||||
|
8
motor.h
8
motor.h
@ -14,6 +14,7 @@
|
||||
#include "obdes.h"
|
||||
#include "interface.h"
|
||||
|
||||
#define MOTOBPARLENGTH 12
|
||||
typedef struct __Motor {
|
||||
pObjectDescriptor pDescriptor;
|
||||
ObPar *ParArray;
|
||||
@ -32,6 +33,13 @@
|
||||
int stopped;
|
||||
} Motor;
|
||||
typedef Motor *pMotor;
|
||||
/*------------------------------------------------------------------------
|
||||
a tiny structure used in CallBack work
|
||||
--------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
float fVal;
|
||||
char *pName;
|
||||
} MotCallback;
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/* 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];
|
||||
int i, iToken, iRet;
|
||||
sParser PP;
|
||||
CommandList *pCom = NULL;
|
||||
|
||||
assert(pCon);
|
||||
assert(pSics);
|
||||
@ -345,9 +346,10 @@
|
||||
break;
|
||||
case ENDCONFIG:
|
||||
/* reconfigure command to final state */
|
||||
RemoveCommand(pSics,argv[0]);
|
||||
AddCommand(pSics,argv[0],MultiWrapper,KillMultiMotor,
|
||||
self);
|
||||
pCom = FindCommand(pSics,argv[0]);
|
||||
assert(pCom != NULL);
|
||||
pCom->OFunc = MultiWrapper;
|
||||
pCom->KFunc = KillMultiMotor;
|
||||
return 1;
|
||||
break;
|
||||
case ALIAS:
|
||||
|
14
network.c
14
network.c
@ -424,9 +424,14 @@ CreateSocketAdress(
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef CYGNUS
|
||||
/* setup for select first */
|
||||
tmo.tv_usec = 100;
|
||||
/*
|
||||
* 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
|
||||
tmo.tv_usec = 10;
|
||||
FD_ZERO(&lMask);
|
||||
FD_SET(self->sockid,&lMask);
|
||||
if((self->sockid >= FD_SETSIZE) || (self->sockid < 0) )
|
||||
@ -445,7 +450,8 @@ CreateSocketAdress(
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
iRet = send(self->sockid,buffer,lLen,0);
|
||||
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 iCount;
|
||||
NetItem NItem;
|
||||
int conCount = 0;
|
||||
char num[50];
|
||||
IPair *options = NULL;
|
||||
|
||||
self = (pNetRead)pData;
|
||||
assert(self);
|
||||
@ -716,9 +719,13 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
{
|
||||
iCount = NItem.pSock->sockid;
|
||||
}
|
||||
conCount++;
|
||||
iRet = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
|
||||
snprintf(num,50,"%d", conCount);
|
||||
IFSetOption(pSICSOptions,"ConnectionCount",num);
|
||||
|
||||
/* the select itself */
|
||||
tmo.tv_usec = self->iReadTimeout;
|
||||
iCount++;
|
||||
|
@ -109,6 +109,8 @@
|
||||
/* initialise tasker */
|
||||
assert(TaskerInit(&self->pTasker));
|
||||
|
||||
pSICSOptions = IFAddOption(pSICSOptions, "ConnectionCount","0");
|
||||
|
||||
/* initialise the server from script */
|
||||
if(file == NULL)
|
||||
{
|
||||
@ -397,13 +399,13 @@
|
||||
*/
|
||||
killTclDrivable();
|
||||
|
||||
/* close the List system */
|
||||
LLDsystemClose();
|
||||
|
||||
KillFreeConnections();
|
||||
|
||||
killSICSHipadaba();
|
||||
|
||||
/* close the List system */
|
||||
LLDsystemClose();
|
||||
|
||||
/* make fortify print his findings */
|
||||
Fortify_DumpAllMemory(iFortifyScope);
|
||||
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){
|
||||
int iDim[MAXDIM];
|
||||
int i, rank, timeLength, status;
|
||||
@ -412,7 +437,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
||||
pNXScript self,
|
||||
int argc, char *argv[]){
|
||||
pHistMem mem = NULL;
|
||||
int status, start, length, i, subset = 0;
|
||||
int status, start, length, i, subset = 0, bank = 0;
|
||||
HistInt *iData = NULL;
|
||||
char buffer[256];
|
||||
|
||||
@ -460,6 +485,19 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
@ -472,7 +510,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
||||
return;
|
||||
}
|
||||
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));
|
||||
}else{
|
||||
/*
|
||||
@ -712,7 +750,10 @@ static void putArray(SConnection *pCon, SicsInterp *pSics,
|
||||
data = (float *)malloc(length*sizeof(float));
|
||||
}
|
||||
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;
|
||||
}
|
||||
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){
|
||||
/*===============*/
|
||||
putSicsData(pCon,pSics,self,argc,argv);
|
||||
}else if(strcmp(argv[1],"putattribute") == 0){
|
||||
/*===============*/
|
||||
putAttribute(pCon,pSics,self,argc,argv);
|
||||
} else {
|
||||
SCWrite(pCon,"ERROR: put command not recognised",eError);
|
||||
}
|
||||
@ -1032,6 +1076,7 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
pNXScript self = (pNXScript)pData;
|
||||
char *pFile = NULL;
|
||||
int status;
|
||||
char buffer[132];
|
||||
|
||||
/*
|
||||
preliminary checks
|
||||
@ -1095,6 +1140,20 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
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){
|
||||
makeLink(pCon,pSics,self,argc,argv);
|
||||
return 1;
|
||||
|
15
nxutil.c
15
nxutil.c
@ -28,8 +28,9 @@
|
||||
int iRet;
|
||||
|
||||
/* Find the motor */
|
||||
strtolower(pName);
|
||||
pMot = FindMotor(pSics,pName);
|
||||
strncpy(pBueffel,pName,511);
|
||||
strtolower(pBueffel);
|
||||
pMot = FindMotor(pSics,pBueffel);
|
||||
if(!pMot)
|
||||
{
|
||||
sprintf(pBueffel,"WARNING: cannot find motor %s",pName);
|
||||
@ -58,8 +59,9 @@
|
||||
int iRet;
|
||||
|
||||
/* Find the motor */
|
||||
strtolower(pName);
|
||||
pMot = FindMotor(pSics,pName);
|
||||
strncpy(pBueffel,pName,511);
|
||||
strtolower(pBueffel);
|
||||
pMot = FindMotor(pSics,pBueffel);
|
||||
if(!pMot)
|
||||
{
|
||||
sprintf(pBueffel,"WARNING: cannot find motor %s",pName);
|
||||
@ -95,8 +97,9 @@
|
||||
char *pText = NULL;
|
||||
|
||||
/* find it */
|
||||
strtolower(pName);
|
||||
pVar = FindVariable(pSics,pName);
|
||||
strncpy(pBueffel,pName,511);
|
||||
strtolower(pBueffel);
|
||||
pVar = FindVariable(pSics,pBueffel);
|
||||
if(!pVar)
|
||||
{
|
||||
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->mama == NULL){
|
||||
DeleteHipadabaNode(self->parNode);
|
||||
DeleteHipadabaNode(self->parNode,NULL);
|
||||
}
|
||||
}
|
||||
free(self);
|
||||
|
17
ofac.c
17
ofac.c
@ -6,7 +6,7 @@
|
||||
|
||||
|
||||
|
||||
Mark Koennecke, November 1996 -- ????
|
||||
Mark Koennecke, November 1996 -- ????
|
||||
|
||||
heavy modifications to separate PSI specific commands into a
|
||||
separate library. Mark Koennecke, June 2003
|
||||
@ -119,6 +119,9 @@
|
||||
#include "sicslist.h"
|
||||
#include "cone.h"
|
||||
#include "sicshipadaba.h"
|
||||
#include "multicounter.h"
|
||||
#include "sicspoll.h"
|
||||
#include "statemon.h"
|
||||
/*----------------------- Server options creation -------------------------*/
|
||||
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
@ -214,6 +217,7 @@
|
||||
AddCommand(pInter,"FileWhere",MacroWhere,WhereKill,NULL);
|
||||
*/
|
||||
AddCommand(pInter,"ClientPut",ClientPut,NULL,NULL);
|
||||
AddCommand(pInter,"GumPut",GumPut,NULL,NULL);
|
||||
AddCommand(pInter,"broadcast",Broadcast,NULL,NULL);
|
||||
AddCommand(pInter,"transact",TransactAction,NULL,NULL);
|
||||
AddCommand(pInter,"fulltransact",TransactAction,NULL,NULL);
|
||||
@ -273,7 +277,8 @@
|
||||
AddCommand(pInter,"MakeEnergy",MakeEnergyVar,NULL,NULL);
|
||||
AddCommand(pInter,"MakeCounter",MakeCounter,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,"MakeHM",MakeHistMemory,NULL,NULL);
|
||||
AddCommand(pInter,"VelocitySelector",VelSelFactory,NULL,NULL);
|
||||
@ -328,6 +333,12 @@
|
||||
InstallSinfox,NULL,NULL);
|
||||
AddCommand(pInter,"MakeCone",
|
||||
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
|
||||
@ -396,6 +407,8 @@
|
||||
RemoveCommand(pSics,"InstallProtocolHandler");
|
||||
RemoveCommand(pSics,"InstallSinfox");
|
||||
RemoveCommand(pSics,"MakeCone");
|
||||
RemoveCommand(pSics,"MakeMultiCounter");
|
||||
RemoveCommand(pSics,"MakeStateMon");
|
||||
/*
|
||||
remove site specific installation commands
|
||||
*/
|
||||
|
84
optimise.c
84
optimise.c
@ -519,38 +519,13 @@ static int ClimbDrive(SConnection *pCon,char *name, float value)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
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;
|
||||
|
||||
/*
|
||||
* test for upwards direction
|
||||
*/
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int findDirection(pOptimise self, pOVarEntry pOvar, SConnection *pCon)
|
||||
{
|
||||
int status, direction;
|
||||
float varValue;
|
||||
long oneCount, twoCount;
|
||||
|
||||
varValue = pOvar->fCenter + pOvar->fStep;
|
||||
status = ClimbDrive(pCon,pOvar->pName,varValue);
|
||||
if(!status)
|
||||
@ -584,14 +559,46 @@ static int ClimbDrive(SConnection *pCon,char *name, float value)
|
||||
if(oneCount > twoCount)
|
||||
{
|
||||
direction = 1;
|
||||
lastCount = oneCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
*/
|
||||
@ -600,7 +607,12 @@ static int ClimbDrive(SConnection *pCon,char *name, float value)
|
||||
if(!status)
|
||||
{
|
||||
return DRIVEERROR;
|
||||
}
|
||||
}
|
||||
lastCount = ClimbCount(self,pCon);
|
||||
if(lastCount < 0)
|
||||
{
|
||||
return SCANERROR;
|
||||
}
|
||||
currentCount = lastCount;
|
||||
|
||||
/*
|
||||
|
@ -21,6 +21,7 @@
|
||||
"warning",
|
||||
"error",
|
||||
"hdb",
|
||||
"hdbEvent",
|
||||
NULL };
|
||||
static int iNoCodes = 11;
|
||||
static int iNoCodes = 13;
|
||||
#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);
|
||||
}
|
83
protocol.c
83
protocol.c
@ -16,7 +16,7 @@
|
||||
#include <dynstring.h>
|
||||
#include "commandlog.h"
|
||||
#include "protocol.h"
|
||||
#include "json.h"
|
||||
#include <json/json.h>
|
||||
|
||||
#define MAXMSG 1024
|
||||
#define INIT_STR_SIZE 256
|
||||
@ -87,8 +87,6 @@ pProtocol CreateProtocol(void);
|
||||
static int ProtocolOptions(SConnection* pCon, pProtocol pPro);
|
||||
static int ProtocolHelp(SConnection* pCon, Protocol* pPro);
|
||||
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);
|
||||
int ProtocolAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
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 *pIndex)
|
||||
int ProtocolGet(SConnection* pCon, void* pData, char *pProName, int len)
|
||||
{
|
||||
int Index;
|
||||
Protocol *pPro = (Protocol *)pData;
|
||||
if(!SCVerifyConnection(pCon))
|
||||
{
|
||||
return 0;
|
||||
@ -309,24 +308,27 @@ static int ProtocolGet(SConnection* pCon, Protocol* pPro, char *pProName,
|
||||
pPro->isDefaultSet = 1;
|
||||
pCon->iProtocolID = 0;
|
||||
}
|
||||
|
||||
*pIndex = (int)malloc(sizeof(int));
|
||||
*pIndex = pCon->iProtocolID;
|
||||
strncpy(pProName, pPro->pProList[pCon->iProtocolID], len);
|
||||
return 1;
|
||||
#if 0
|
||||
Index = pCon->iProtocolID;
|
||||
|
||||
/* check list of protocols for valid name */
|
||||
switch(*pIndex)
|
||||
switch(Index)
|
||||
{
|
||||
case 0: /* default = psi_sics */
|
||||
case 1: /* normal (connection start default) */
|
||||
case 2: /* outcodes */
|
||||
case 3: /* sycamore */
|
||||
pProName = strdup(pPro->pProList[*pIndex]);
|
||||
case 4: /* json */
|
||||
pProName = pPro->pProList[Index];
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
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]));
|
||||
break;
|
||||
}
|
||||
if (iOut == eHdb) {
|
||||
if (iOut == eHdbValue || iOut == eHdbEvent) {
|
||||
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 {
|
||||
/* Strip \r and \n */
|
||||
for (pBufferFrom=pBufferTo=pBuffer; ; pBufferFrom++) {
|
||||
if (*pBufferFrom == '\r' || *pBufferFrom == '\n')
|
||||
continue;
|
||||
*pBufferTo = *pBufferFrom;
|
||||
pBufferTo = pBufferFrom;
|
||||
if (*pBufferTo == '\0')
|
||||
break;
|
||||
pBufferTo++;
|
||||
}
|
||||
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);
|
||||
return msg_json;
|
||||
|
||||
reporterr:
|
||||
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);
|
||||
SCSetWriteFunc(pCon,SCWriteJSON_String);
|
||||
cleanup:
|
||||
if (tmp_json != NULL)
|
||||
if (tmp_json != NULL && !is_error(tmp_json))
|
||||
json_object_put(tmp_json);
|
||||
if (msg_json != NULL)
|
||||
if (msg_json != NULL && !is_error(msg_json))
|
||||
json_object_put(msg_json);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int SCWriteJSON_String(SConnection *pCon, char *pBuffer, int iOut)
|
||||
{
|
||||
struct json_object *my_object=NULL;
|
||||
char pBueffel[MAXMSG];
|
||||
int iRet;
|
||||
struct json_object *my_object=NULL, *tmp_json=NULL;
|
||||
char pBueffel[MAXMSG], errBuff[MAXMSG];
|
||||
int iRet, errLen = MAXMSG;
|
||||
|
||||
if (strlen(pBuffer) == 0)
|
||||
return 1;
|
||||
@ -688,21 +691,48 @@ int SCWriteJSON_String(SConnection *pCon, char *pBuffer, int iOut)
|
||||
/* write to commandlog if user or manager privilege */
|
||||
if(SCGetRights(pCon) <= usUser)
|
||||
{
|
||||
if(pCon->iMacro != 1)
|
||||
{
|
||||
sprintf(pBueffel,"To sock %d :",iRet);
|
||||
WriteToCommandLog(pBueffel,pBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(iOut == eError || iOut == eWarning)
|
||||
{
|
||||
sprintf(pBueffel,"To sock %d :",iRet);
|
||||
WriteToCommandLog(pBueffel,pBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(SCinMacro(pCon))
|
||||
{
|
||||
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 {
|
||||
my_object = mkJSON_Object(pCon, pBuffer, iOut);
|
||||
iRet = SCDoSockWrite(pCon,json_object_to_json_string(my_object));
|
||||
SCWriteToLogFiles(pCon,pBuffer);
|
||||
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 {
|
||||
iRet = SCDoSockWrite(pCon,json_object_to_json_string(my_object));
|
||||
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);
|
||||
return 1;
|
||||
return iRet;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Protocol API */
|
||||
@ -731,6 +761,7 @@ char * GetProtocolName(SConnection* pCon)
|
||||
case 1: /* normal (connection start default) */
|
||||
case 2: /* outcodes */
|
||||
case 3: /* sycamore */
|
||||
case 4: /* json */
|
||||
return strdup(pPro->pProList[pCon->iProtocolID]);
|
||||
break;
|
||||
default:
|
||||
|
@ -30,5 +30,6 @@ int SCWriteSycamore(SConnection *pCon, char *pBuffer, int iOut);
|
||||
/*--------------------- implement protocol API -----------------------*/
|
||||
char * GetProtocolName(SConnection *pCon);
|
||||
int GetProtocolID(SConnection *pCon);
|
||||
int ProtocolGet(SConnection* pCon, void* pData, char *pProName, int len);
|
||||
/*-----------------------------------------------------------------------*/
|
||||
#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 "servlog.h"
|
||||
#include "site.h"
|
||||
#include "commandlog.h"
|
||||
/*-------------------------------------------------------------------------*/
|
||||
#define INTERRUPTMODE 0
|
||||
#define ACCESSCODE 1
|
||||
@ -242,8 +243,10 @@ static int RemServerTask(void *data) {
|
||||
rc = &remserver->rc[isUser];
|
||||
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 (RemHandle(remserver)) { /* handle drivstat messages */
|
||||
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){
|
||||
return self->timeout;
|
||||
}
|
||||
|
@ -65,6 +65,7 @@
|
||||
|
||||
void getRS232Error(int iCode, char *errorBuffer,
|
||||
int errorBufferLen);
|
||||
int fixRS232Error(prs232 self, int iCode);
|
||||
int getRS232Timeout(prs232 self);
|
||||
int initRS232(prs232 self);
|
||||
int initRS232WithFlags(prs232 self, int flags);
|
||||
|
23
scan.c
23
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 *trim(char *txt);
|
||||
|
||||
int StoreScanCounts(pScanData self, char *data)
|
||||
{
|
||||
@ -402,7 +403,7 @@ int StoreScanCounts(pScanData self, char *data)
|
||||
InitCountEntry(&sCount);
|
||||
|
||||
/* parse the data */
|
||||
pPtr = data;
|
||||
pPtr = trim(data);
|
||||
pPtr = stptok(pPtr,pNumber,29," \t");
|
||||
if(pPtr != NULL)
|
||||
{
|
||||
@ -1584,7 +1585,7 @@ static int PrintTimes(pScanData self, SConnection *pCon,
|
||||
|
||||
snprintf(pBueffel,59,"%s.scantimes = { ",name);
|
||||
DynStringCopy(data,pBueffel);
|
||||
for(i = 0; i < self->iNP; i++)
|
||||
for(i = 0; i < self->iCounts; i++)
|
||||
{
|
||||
DynarGet(self->pCounts,i,&pPtr);
|
||||
pData = (pCountEntry)pPtr;
|
||||
@ -2127,8 +2128,8 @@ static int DumpScan(pScanData self, SConnection *pCon)
|
||||
}
|
||||
/*------------ functions */
|
||||
else if(strcmp(argv[1],"function") == 0)
|
||||
{
|
||||
return InterpretScanFunctions(self, pCon, argc, argv);
|
||||
{
|
||||
return InterpretScanFunctions(self, pCon, argc, argv);
|
||||
}
|
||||
/*---------- scan */
|
||||
else if(strcmp(argv[1],"run") == 0)
|
||||
@ -2414,6 +2415,20 @@ static int DumpScan(pScanData self, SConnection *pCon)
|
||||
}
|
||||
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 */
|
||||
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.
|
||||
-> makes the compiler happy M.Z. */
|
||||
#define NO_CONST
|
||||
/* #define NO_CONST */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
34
sicscron.c
34
sicscron.c
@ -11,7 +11,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <tcl.h>
|
||||
#include "macro.h"
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "splitter.h"
|
||||
@ -24,6 +24,7 @@
|
||||
char *pCommand;
|
||||
SConnection *pCon;
|
||||
int iEnd;
|
||||
Statistics *stat;
|
||||
} Cron, *pCron;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
@ -43,12 +44,19 @@
|
||||
{
|
||||
SCDeleteConnection(self->pCon);
|
||||
}
|
||||
if (self->stat) {
|
||||
StatisticsKill(self->stat);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int CronTask(void *pData)
|
||||
{
|
||||
Statistics *old;
|
||||
|
||||
pCron self = (pCron)pData;
|
||||
int iRet;
|
||||
Tcl_Interp *pTcl = pServ->pSics->pTcl;
|
||||
|
||||
if(!self)
|
||||
{
|
||||
@ -57,7 +65,17 @@
|
||||
|
||||
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;
|
||||
}
|
||||
return self->iEnd;
|
||||
@ -82,11 +100,11 @@
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pCron pNew = NULL;
|
||||
int iVal, iRet;
|
||||
int iVal, iRet, rights;
|
||||
char *cmd;
|
||||
|
||||
/* only managers may do this */
|
||||
if(!SCMatchRights(pCon,usMugger))
|
||||
/* need user priv. */
|
||||
if(!SCMatchRights(pCon,usUser))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -123,10 +141,16 @@
|
||||
SCWrite(pCon,"ERROR: out of memory in sicscron",eError);
|
||||
return 0;
|
||||
}
|
||||
rights = SCGetRights(pCon);
|
||||
if (rights > usMugger) {
|
||||
/* transfer the rights to the dummy connection */
|
||||
SCSetRights(pNew->pCon, rights);
|
||||
}
|
||||
pNew->iIntervall = iVal;
|
||||
pNew->pCommand = cmd;
|
||||
pNew->tNext = 0;
|
||||
pNew->iEnd = 1;
|
||||
pNew->stat = StatisticsNew(cmd);
|
||||
|
||||
TaskRegister(pServ->pTasker,
|
||||
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
|
||||
clients.
|
||||
|
||||
WARNING: this code only works when ints and floats are of the same size!
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, June 2003
|
||||
@ -17,7 +19,7 @@
|
||||
#include "scan.h"
|
||||
#include "HistMem.h"
|
||||
#include "sicsdata.h"
|
||||
|
||||
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||
/*--------------------------------------------------------------------*/
|
||||
static void KillSICSData(void *pData){
|
||||
pSICSData self = NULL;
|
||||
@ -60,6 +62,47 @@ pSICSData createSICSData(void){
|
||||
pNew->dataUsed = 0;
|
||||
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 newSize;
|
||||
@ -134,7 +177,7 @@ static void netEncode(pSICSData self){
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static void clearSICSData(pSICSData self){
|
||||
void clearSICSData(pSICSData self){
|
||||
assert(self);
|
||||
|
||||
self->dataUsed = 0;
|
||||
@ -236,6 +279,74 @@ static int putFloat(pSICSData self, int argc, char *argv[],
|
||||
SCSendOK(pCon);
|
||||
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[],
|
||||
SConnection *pCon, SicsInterp *pSics){
|
||||
@ -475,6 +586,35 @@ static int copyHM(pSICSData self, int argc, char *argv[],
|
||||
SCSendOK(pCon);
|
||||
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
|
||||
----------------------------------------------------------------------*/
|
||||
@ -482,6 +622,7 @@ int SICSDataAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pSICSData self = NULL;
|
||||
char pBueffel[132];
|
||||
int pos;
|
||||
|
||||
self = (pSICSData)pData;
|
||||
assert(self);
|
||||
@ -509,6 +650,21 @@ int SICSDataAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
return 0;
|
||||
}
|
||||
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){
|
||||
/*---------- putint */
|
||||
return putInt(self,argc-2,&argv[2],pCon, pSics);
|
||||
|
@ -39,5 +39,12 @@
|
||||
int SICSDataAction(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData,
|
||||
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
|
||||
|
@ -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
|
||||
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
|
||||
operations as well. In another stage this may supersede the uuget and
|
||||
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,
|
||||
void *pData,
|
||||
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}
|
||||
\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