- Reworked the connection object and the IO system
- Reworked the support for TRICS - Added a second generation motor
This commit is contained in:
29
SCinter.c
29
SCinter.c
@ -270,10 +270,10 @@ extern char *SkipSpace(char *pPtr);
|
||||
assert(pCon);
|
||||
|
||||
/* write info to Log */
|
||||
if(pCon->pSock)
|
||||
if(pCon->sockHandle >= 0)
|
||||
{
|
||||
sprintf(pBueffel,"Executing -> %s <- from socket %d",pText,
|
||||
pCon->pSock->sockid);
|
||||
pCon->sockHandle);
|
||||
SICSLogWrite(pBueffel,eCommand);
|
||||
}
|
||||
else
|
||||
@ -282,6 +282,7 @@ extern char *SkipSpace(char *pPtr);
|
||||
SICSLogWrite(pBueffel,eCommand);
|
||||
}
|
||||
|
||||
|
||||
/* convert to argc, argv */
|
||||
argc = 0;
|
||||
argv = NULL;
|
||||
@ -315,7 +316,7 @@ extern char *SkipSpace(char *pPtr);
|
||||
|
||||
|
||||
/* invoke the command */
|
||||
self->eOut = eStatus;
|
||||
self->eOut = eValue;
|
||||
Tcl_ResetResult((Tcl_Interp *)self->pTcl);
|
||||
MacroPush(pCon);
|
||||
pCon->conStatus = 0;
|
||||
@ -324,8 +325,8 @@ extern char *SkipSpace(char *pPtr);
|
||||
StatisticsEnd(old);
|
||||
/* If a task is registered with the dev exec then conStatus is HWBusy*/
|
||||
if (pCon->conStatus != HWBusy) {
|
||||
comCon = SCGetContext(pCon);
|
||||
if (0 != strcmp("contextdo",comCon.deviceID))
|
||||
/*comCon = SCGetContext(pCon);*/
|
||||
if (0 != strcmp("contextdo",pCon->deviceID))
|
||||
SCWrite(pCon,"",eFinish);
|
||||
}
|
||||
MacroPop();
|
||||
@ -552,7 +553,7 @@ static void printAll(SicsInterp *pSics, SConnection *pCon)
|
||||
strcat(pBueffel," ");
|
||||
strcat(pBueffel,pCurrent->pName);
|
||||
strcat(pBueffel,"\r\n");
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
iNum = 0;
|
||||
pBueffel[0]='\0';
|
||||
}
|
||||
@ -563,7 +564,7 @@ static void printAll(SicsInterp *pSics, SConnection *pCon)
|
||||
if(strlen(pBueffel) > 2)
|
||||
{
|
||||
strcat(pBueffel,"\r\n");
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
@ -597,7 +598,7 @@ static void printAllTypes(SicsInterp *pSics, SConnection *pCon, int iFiltered)
|
||||
if(-1==typeListID)
|
||||
{
|
||||
strcpy(pBueffel,"ERROR: Cannot generate list of object types\r\n");
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -679,7 +680,7 @@ static void printInterface(SicsInterp *pSics, SConnection *pCon, int id)
|
||||
strcat(pBueffel," ");
|
||||
strcat(pBueffel,pCurrent->pName);
|
||||
strcat(pBueffel,"\r\n");
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
iNum = 0;
|
||||
pBueffel[0]='\0';
|
||||
}
|
||||
@ -690,7 +691,7 @@ static void printInterface(SicsInterp *pSics, SConnection *pCon, int id)
|
||||
|
||||
/* write final entries */
|
||||
strcat(pBueffel,"\r\n");
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
/*-----------------------------------------------------------------------
|
||||
printMatch prints only those objects which match the wildcard string given
|
||||
@ -732,7 +733,7 @@ static void printMatch(SicsInterp *pSics, SConnection *pCon, char *mask)
|
||||
strcat(pBueffel," ");
|
||||
strcat(pBueffel,pCurrent->pName);
|
||||
strcat(pBueffel,"\r\n");
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
pBueffel[0]='\0';
|
||||
iNum = 0;
|
||||
}
|
||||
@ -743,7 +744,7 @@ static void printMatch(SicsInterp *pSics, SConnection *pCon, char *mask)
|
||||
|
||||
/* write final entries */
|
||||
strcat(pBueffel,"\r\n");
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
/*-----------------------------------------------------------------------
|
||||
printType prints only those objects whose descriptor match the type given
|
||||
@ -794,7 +795,7 @@ static void printType(SicsInterp *pSics, SConnection *pCon, char *typeName)
|
||||
|
||||
/* write final entries */
|
||||
strcat(pBueffel,"\r\n");
|
||||
SCWrite(pCon,Tcl_DStringValue(&txt),eStatus);
|
||||
SCWrite(pCon,Tcl_DStringValue(&txt),eValue);
|
||||
Tcl_DStringFree(&txt);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -1042,7 +1043,7 @@ static void printList(SConnection *pCon, int listID)
|
||||
if ((MAXBUF-3) > retCode) {
|
||||
retCode = LLDstringData(listID,pBueffel);
|
||||
strcat(pBueffel,"\r\n");
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
} while(0!=LLDnodePtr2Next(listID));
|
||||
}
|
||||
|
28
Scommon.h
28
Scommon.h
@ -40,19 +40,21 @@
|
||||
|
||||
/* this enum defines the output types in SICS */
|
||||
typedef enum {
|
||||
eInternal,
|
||||
eCommand,
|
||||
eHWError,
|
||||
eInError,
|
||||
eStatus,
|
||||
eValue,
|
||||
eStart,
|
||||
eFinish,
|
||||
eEvent,
|
||||
eWarning,
|
||||
eError,
|
||||
eHdbValue,
|
||||
eHdbEvent
|
||||
eInternal, /* internal */
|
||||
eCommand, /* reserved, not used */
|
||||
eHWError, /* reserved, used only for SICSLog */
|
||||
eInError, /* reserved, used as a mark in the handling of output codes */
|
||||
eStatus, /* reserved, deprecated */
|
||||
eValue, /* value reponse: copied into Tcl */
|
||||
eStart, /* start message */
|
||||
eFinish, /* finish message */
|
||||
eEvent, /* some callback messages */
|
||||
eWarning, /* warnings */
|
||||
eError, /* error: copied into Tcl */
|
||||
eHdbValue, /* hipadaba value chnage */
|
||||
eHdbEvent, /* Hipadaba event */
|
||||
eLog, /* log message: is always written to client */
|
||||
eLogError /* error message to log: is always written to client */
|
||||
} OutCode;
|
||||
|
||||
#include "interrupt.h"
|
||||
|
18
ascon.c
18
ascon.c
@ -305,7 +305,9 @@ int AsconStdHandler(Ascon *a) {
|
||||
l = GetDynStringLength(a->wrBuffer) - a->wrPos;
|
||||
ret = AsconWriteChars(a->fd, GetCharArray(a->wrBuffer) + a->wrPos, l);
|
||||
if (ret < 0) {
|
||||
AsconError(a, "send failed:", errno);
|
||||
if(errno != EINTR && errno != EAGAIN){
|
||||
AsconError(a, "send failed:", errno);
|
||||
}
|
||||
/*
|
||||
* Ooops: which state shall we go to after a write fail?
|
||||
* This seems to retry.
|
||||
@ -352,7 +354,10 @@ int AsconStdHandler(Ascon *a) {
|
||||
ret = AsconReadChar(a->fd, &chr);
|
||||
}
|
||||
if (ret < 0) {
|
||||
AsconError(a, "AsconReadChar failed:", errno);
|
||||
/* EINTR means we shall retry */
|
||||
if(errno != EINTR && errno != EAGAIN){
|
||||
AsconError(a, "AsconReadChar failed:", errno);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (a->state == AsconReadDone) {
|
||||
@ -453,6 +458,13 @@ void AsconKill(Ascon *a) {
|
||||
}
|
||||
free(a);
|
||||
}
|
||||
void AsconDisconnect(Ascon *a){
|
||||
if(a->fd > 0){
|
||||
close(a->fd);
|
||||
}
|
||||
a->fd = -1;
|
||||
a->state = AsconConnectStart;
|
||||
}
|
||||
|
||||
AsconStatus AsconTask(Ascon *a) {
|
||||
double now;
|
||||
@ -491,6 +503,8 @@ AsconStatus AsconTask(Ascon *a) {
|
||||
if (now > a->lastReconnect + a->reconnectInterval) {
|
||||
a->lastReconnect = now;
|
||||
close(a->fd);
|
||||
/* allow the system to cleanup the socket, otherwise a reconnect will fail*/
|
||||
sleep(1);
|
||||
a->fd = -1;
|
||||
a->state = AsconConnectStart;
|
||||
}
|
||||
|
4
ascon.h
4
ascon.h
@ -36,6 +36,10 @@ Ascon *AsconMake(SConnection *con, int argc, char *argv[]);
|
||||
* \param a the connection to be killed
|
||||
*/
|
||||
void AsconKill(Ascon *a);
|
||||
/** \brief Disconnect function
|
||||
* \param a the connection to disconnect
|
||||
*/
|
||||
void AsconDisconnect(Ascon *a);
|
||||
|
||||
/** \brief the task handler. To be called repeatedly.
|
||||
* \param a the connection
|
||||
|
@ -648,7 +648,7 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics,
|
||||
}
|
||||
else {
|
||||
snprintf(line, 132, "%s.delay = %d", argv[0], self->iDelay);
|
||||
SCWrite(pCon, line, eStatus);
|
||||
SCWrite(pCon, line, eValue);
|
||||
return OKOK;
|
||||
}
|
||||
return OKOK;
|
||||
@ -675,7 +675,7 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics,
|
||||
}
|
||||
else {
|
||||
snprintf(line, 132, "%s.timeout = %d", argv[0], self->timeout);
|
||||
SCWrite(pCon, line, eStatus);
|
||||
SCWrite(pCon, line, eValue);
|
||||
return OKOK;
|
||||
}
|
||||
return OKOK;
|
||||
@ -702,7 +702,7 @@ int AsyncQueueAction(SConnection *pCon, SicsInterp *pSics,
|
||||
}
|
||||
else {
|
||||
snprintf(line, 132, "%s.retries = %d", argv[0], self->retries);
|
||||
SCWrite(pCon, line, eStatus);
|
||||
SCWrite(pCon, line, eValue);
|
||||
return OKOK;
|
||||
}
|
||||
return OKOK;
|
||||
|
87
background.c
Normal file
87
background.c
Normal file
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* This is for backgrounding operations in SICS. They run in an own
|
||||
* task.
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, February 2009
|
||||
*/
|
||||
#include <sics.h>
|
||||
#include "splitter.h"
|
||||
#include "background.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
SConnection *con;
|
||||
char *command;
|
||||
} BckTask, *pBckTask;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void KillBckTask(void *data){
|
||||
pBckTask self = (pBckTask)data;
|
||||
if(self == NULL){
|
||||
return;
|
||||
}
|
||||
if(self->con){
|
||||
SCDeleteConnection(self->con);
|
||||
}
|
||||
if(self->command){
|
||||
free(self->command);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int BackgroundTask(void *data){
|
||||
pBckTask self = (pBckTask)data;
|
||||
|
||||
assert(self != NULL);
|
||||
|
||||
InterpExecute(pServ->pSics,self->con,self->command);
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int BackgroundCommand(SConnection *pCon, char *command){
|
||||
pBckTask self = NULL;
|
||||
|
||||
self = calloc(1,sizeof(BckTask));
|
||||
if(self == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
self->con = SCCopyConnection(pCon);
|
||||
self->command = strdup(command);
|
||||
if(self->con == NULL || self->command == NULL){
|
||||
free(self);
|
||||
return 0;
|
||||
}
|
||||
|
||||
TaskRegister(pServ->pTasker,
|
||||
BackgroundTask,
|
||||
NULL,
|
||||
KillBckTask,
|
||||
self,
|
||||
1);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int BackgroundAction(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData, int argc, char *argv[]){
|
||||
int status;
|
||||
char command[1024];
|
||||
|
||||
memset(command,0,1024);
|
||||
Arg2Text(argc-1,&argv[1], command, 1024);
|
||||
status = BackgroundCommand(pCon,command);
|
||||
if(status == 0){
|
||||
SCWrite(pCon,"ERROR: out of memory starting task", eError);
|
||||
return 0;
|
||||
}
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void InstallBackground(SicsInterp *pSics){
|
||||
AddCommand(pSics,
|
||||
"bg",
|
||||
BackgroundAction,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
26
background.h
Normal file
26
background.h
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* This is for backgrounding operations in SICS. They run in an own
|
||||
* task.
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, February 2009
|
||||
*/
|
||||
#ifndef BACKGROUND_H_
|
||||
#define BACKGROUND_H_
|
||||
|
||||
/**
|
||||
* interpreter inteface
|
||||
*/
|
||||
int BackgroundAction(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData, int argc, char *argv[]);
|
||||
/*
|
||||
* actual function which does the backgrounding
|
||||
*/
|
||||
int BackgroundCommand(SConnection *pCon, char *command);
|
||||
/*
|
||||
* used only once for installing Background
|
||||
*/
|
||||
void InstallBackground(SicsInterp *pSics);
|
||||
|
||||
#endif /*BACKGROUND_H_*/
|
255
callback.c
255
callback.c
@ -50,22 +50,24 @@
|
||||
#include "splitter.h"
|
||||
|
||||
#define CALLBACK 17777
|
||||
static int debug = 0;
|
||||
|
||||
/*--------------------- The interface datastructure ---------------------*/
|
||||
typedef struct __ICallBack {
|
||||
int iID;
|
||||
int iList;
|
||||
} ICallBack;
|
||||
|
||||
/*-------------- The data stored for a single callback ------------------*/
|
||||
typedef struct {
|
||||
typedef struct __CBItem{
|
||||
long iID;
|
||||
SICSCallBack pFunc;
|
||||
void *pUserData;
|
||||
KillFuncIT pKill;
|
||||
int iEvent;
|
||||
commandContext comCon;
|
||||
int killFlag;
|
||||
struct __CBItem *next;
|
||||
} CallBackItem, *pCallBackItem;
|
||||
/*--------------------- The interface datastructure ---------------------*/
|
||||
typedef struct __ICallBack {
|
||||
int iID;
|
||||
pCallBackItem head;
|
||||
} ICallBack;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int CheckPointer(pICallBack self)
|
||||
{
|
||||
@ -89,19 +91,14 @@
|
||||
}
|
||||
|
||||
pNew->iID = CALLBACK;
|
||||
pNew->iList = LLDcreate(sizeof(CallBackItem));
|
||||
if(pNew->iList < 0)
|
||||
{
|
||||
free(pNew);
|
||||
return NULL;
|
||||
}
|
||||
pNew->head = NULL;
|
||||
return pNew;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void DeleteCallBackInterface(pICallBack self)
|
||||
{
|
||||
int iRet;
|
||||
CallBackItem sItem;
|
||||
pCallBackItem pItem, pTmp;
|
||||
|
||||
if(!CheckPointer(self))
|
||||
{
|
||||
@ -109,73 +106,160 @@
|
||||
}
|
||||
|
||||
/* kill all userdata associated with callbacks */
|
||||
iRet = LLDnodePtr2First(self->iList);
|
||||
while(iRet != 0)
|
||||
pItem = self->head;
|
||||
while(pItem != NULL)
|
||||
{
|
||||
LLDnodeDataTo(self->iList,&sItem);
|
||||
if(sItem.pKill != NULL)
|
||||
{
|
||||
sItem.pKill(sItem.pUserData);
|
||||
}
|
||||
iRet = LLDnodePtr2Next(self->iList);
|
||||
pTmp = pItem->next;
|
||||
if(pItem->pKill != NULL)
|
||||
{
|
||||
pItem->pKill(pItem->pUserData);
|
||||
}
|
||||
free(pItem);
|
||||
pItem = pTmp;
|
||||
}
|
||||
|
||||
LLDdelete(self->iList);
|
||||
free(self);
|
||||
free(self);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static void markUserdata4Kill(pICallBack self, void *pData)
|
||||
{
|
||||
pCallBackItem pItem = NULL;
|
||||
|
||||
pItem = self->head;
|
||||
while(pItem != NULL){
|
||||
if(pData != NULL && pItem->pUserData == pData)
|
||||
{
|
||||
pItem->killFlag = 1;
|
||||
}
|
||||
pItem = pItem->next;
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void cleanCallbackList(pICallBack self)
|
||||
{
|
||||
pCallBackItem toKill, current;
|
||||
|
||||
/*
|
||||
* killing at the head
|
||||
*/
|
||||
while(self->head != NULL && self->head->killFlag == 0){
|
||||
toKill = self->head;
|
||||
self->head = toKill->next;
|
||||
if(toKill->pKill != NULL){
|
||||
toKill->pKill(toKill->pUserData);
|
||||
}
|
||||
free(toKill);
|
||||
}
|
||||
|
||||
if(self->head == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* killing in the middle and the end
|
||||
*/
|
||||
current = self->head;
|
||||
while(current->next != NULL){
|
||||
if(current->next->killFlag == 1){
|
||||
toKill = current->next;
|
||||
current->next = toKill->next;
|
||||
if(toKill->pKill != NULL){
|
||||
toKill->pKill(toKill->pUserData);
|
||||
}
|
||||
free(toKill);
|
||||
} else {
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int InvokeCallBack(pICallBack self, int iEvent, void *pEventData)
|
||||
{
|
||||
CallBackItem sItem;
|
||||
pCallBackItem pItem;
|
||||
int iCurrent, iRet;
|
||||
int iResult = 1;
|
||||
int iResult = 1, iKill = 0;;
|
||||
|
||||
if(!CheckPointer(self))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
iCurrent = LLDnodePtr2First(self->iList);
|
||||
while(iCurrent != 0)
|
||||
pItem = self->head;
|
||||
while(pItem != NULL)
|
||||
{
|
||||
LLDnodeDataTo(self->iList,&sItem);
|
||||
if(sItem.iEvent == iEvent)
|
||||
if(pItem->iEvent == iEvent && pItem->killFlag == 0)
|
||||
{
|
||||
iRet = sItem.pFunc(iEvent, pEventData,sItem.pUserData,sItem.comCon);
|
||||
if(!iRet)
|
||||
iRet = pItem->pFunc(iEvent, pEventData,pItem->pUserData);
|
||||
if(iRet < 0)
|
||||
{
|
||||
pItem->killFlag = 1;
|
||||
if(pItem->pUserData != NULL)
|
||||
{
|
||||
markUserdata4Kill(self, pItem->pUserData);
|
||||
iKill = 1;
|
||||
}
|
||||
}
|
||||
else if(iRet != 1)
|
||||
{
|
||||
iResult = 0;
|
||||
}
|
||||
}
|
||||
iCurrent = LLDnodePtr2Next(self->iList);
|
||||
pItem = pItem->next;
|
||||
}
|
||||
|
||||
/* kill run */
|
||||
if(iKill == 1){
|
||||
cleanCallbackList(self);
|
||||
}
|
||||
|
||||
return iResult;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static long lCount = 1L;
|
||||
|
||||
long RegisterCallback(pICallBack self, commandContext comCon, int iEvent,
|
||||
long RegisterCallback(pICallBack self, int iEvent,
|
||||
SICSCallBack pFunc,
|
||||
void *pUserData, KillFunc pKFunc)
|
||||
{
|
||||
CallBackItem sItem;
|
||||
pCallBackItem pItem = NULL;
|
||||
|
||||
if(!CheckPointer(self))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
sItem.iID = lCount++;
|
||||
pItem = calloc(1,sizeof(CallBackItem));
|
||||
if(pItem == NULL){
|
||||
return -1;
|
||||
}
|
||||
pItem->iID = lCount++;
|
||||
assert(pFunc);
|
||||
sItem.pFunc = pFunc;
|
||||
sItem.iEvent = iEvent;
|
||||
sItem.pUserData = pUserData;
|
||||
sItem.pKill = pKFunc;
|
||||
sItem.comCon = comCon;
|
||||
|
||||
LLDnodeAppendFrom(self->iList,&sItem);
|
||||
return sItem.iID;
|
||||
pItem->pFunc = pFunc;
|
||||
pItem->iEvent = iEvent;
|
||||
pItem->pUserData = pUserData;
|
||||
pItem->pKill = pKFunc;
|
||||
pItem->killFlag = 0;
|
||||
pItem->next = self->head;
|
||||
self->head = pItem;
|
||||
if(debug){
|
||||
printf("Registered callback at %p\n",self);
|
||||
}
|
||||
return pItem->iID;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static void markById(pICallBack self, int lID)
|
||||
{
|
||||
pCallBackItem pItem = NULL;
|
||||
|
||||
pItem = self->head;
|
||||
while(pItem != NULL)
|
||||
{
|
||||
if(pItem->iID == lID)
|
||||
{
|
||||
pItem->killFlag = 1;
|
||||
}
|
||||
pItem = pItem->next;
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int RemoveCallback(pICallBack self, long lID)
|
||||
{
|
||||
@ -186,22 +270,8 @@
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
iCurrent = LLDnodePtr2First(self->iList);
|
||||
while(iCurrent != 0)
|
||||
{
|
||||
LLDnodeDataTo(self->iList,&sItem);
|
||||
if(sItem.iID == lID)
|
||||
{
|
||||
if(sItem.pKill != NULL)
|
||||
{
|
||||
sItem.pKill(sItem.pUserData);
|
||||
}
|
||||
LLDnodeDelete(self->iList);
|
||||
return 1;
|
||||
}
|
||||
iCurrent = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
markById(self,lID);
|
||||
cleanCallbackList(self);
|
||||
return 0;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -214,23 +284,37 @@
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
iCurrent = LLDnodePtr2First(self->iList);
|
||||
while(iCurrent != 0)
|
||||
{
|
||||
LLDnodeDataTo(self->iList,&sItem);
|
||||
if(sItem.pUserData == pUserData)
|
||||
{
|
||||
if(sItem.pKill != NULL)
|
||||
{
|
||||
sItem.pKill(sItem.pUserData);
|
||||
}
|
||||
LLDnodeDelete(self->iList);
|
||||
}
|
||||
iCurrent = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
markUserdata4Kill(self,pUserData);
|
||||
cleanCallbackList(self);
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int RemoveCallbackCon(pICallBack self, SConnection *con)
|
||||
{
|
||||
pCallBackItem pItem;
|
||||
SConnection *tst = NULL;
|
||||
|
||||
if(!CheckPointer(self))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pItem = self->head;
|
||||
while(pItem != NULL)
|
||||
{
|
||||
tst = (SConnection *)pItem->pUserData;
|
||||
if(VerifyConnection(tst) && tst->ident == con->ident)
|
||||
{
|
||||
if(debug){
|
||||
printf("Killing callback on connection.ident = %ld\n", con->ident);
|
||||
}
|
||||
pItem->killFlag = 1;
|
||||
}
|
||||
pItem = pItem->next;
|
||||
}
|
||||
cleanCallbackList(self);
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------
|
||||
a write function for the connection which writes to stdout
|
||||
-------------------------------------------------------------------*/
|
||||
@ -246,8 +330,7 @@ static int CallbackWrite(SConnection *pCon,char *message, int outCode)
|
||||
/*-----------------------------------------------------------------------
|
||||
the actual callback function invoking the script
|
||||
------------------------------------------------------------------------*/
|
||||
static int ScriptCallback(int iEvent, void *pEventData, void *pUserData,
|
||||
commandContext cc)
|
||||
static int ScriptCallback(int iEvent, void *pEventData, void *pUserData)
|
||||
{
|
||||
SConnection *pCon = NULL;
|
||||
Tcl_Interp *pTcl;
|
||||
@ -264,18 +347,6 @@ static int ScriptCallback(int iEvent, void *pEventData, void *pUserData,
|
||||
fprintf(stdout,"ERROR: ScriptCallback: no script to execute\n");
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
SCSetWriteFunc(pCon,CallbackWrite);
|
||||
MacroPush(pCon);
|
||||
pTcl = InterpGetTcl(pServ->pSics);
|
||||
status = Tcl_Eval(pTcl,(char *)pUserData);
|
||||
if(status != TCL_OK)
|
||||
{
|
||||
fprintf(stdout,"ERROR: in CallbackScript: %s\n",(char *)pUserData);
|
||||
fprintf(stdout,"Tcl-error: %s\n",pTcl->result);
|
||||
}
|
||||
MacroPop();
|
||||
*/
|
||||
SCSetRights(pCon,usInternal);
|
||||
status = InterpExecute(pServ->pSics,pCon,(char *)pUserData);
|
||||
|
||||
@ -335,7 +406,7 @@ int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
return 0;
|
||||
}
|
||||
Arg2Text(argc-4,&argv[4],pBuffer,131);
|
||||
lID = RegisterCallback(pCall,SCGetContext(pCon),
|
||||
lID = RegisterCallback(pCall,
|
||||
iEvent,ScriptCallback,
|
||||
strdup(pBuffer),free);
|
||||
sprintf(pBuffer,"callback = %ld", lID);
|
||||
|
300
cone.c
300
cone.c
@ -5,6 +5,10 @@
|
||||
COPYRIGHT: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, March 2006
|
||||
|
||||
Reworked for new four circle infrastructure.
|
||||
|
||||
Mark Koennecke, August 2008
|
||||
------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
@ -12,11 +16,15 @@
|
||||
#include "hkl.i"
|
||||
#include "vector.h"
|
||||
#include "fourlib.h"
|
||||
#include "singlex.h"
|
||||
#include "sicsobj.h"
|
||||
#include "sicshipadaba.h"
|
||||
/*=================== Object Descriptor Interface ===================================================*/
|
||||
static void *ConeGetInterface(void *pData, int iID){
|
||||
pConeData self = NULL;
|
||||
pSICSOBJ obj = (pSICSOBJ)pData;
|
||||
|
||||
self = (pConeData)pData;
|
||||
self = (pConeData)obj->pPrivate;
|
||||
if(self == NULL){
|
||||
return NULL;
|
||||
}
|
||||
@ -25,28 +33,15 @@ static void *ConeGetInterface(void *pData, int iID){
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------------------------------*/
|
||||
static void ConeSaveStatus(void *data, char *name, FILE *fd){
|
||||
pConeData self = (pConeData)data;
|
||||
if(self == NULL){
|
||||
return;
|
||||
}
|
||||
fprintf(fd,"%s center %d\n", name,self->center);
|
||||
fprintf(fd,"%s target %f %f %f\n", name, self->target.h,
|
||||
self->target.k, self->target.l);
|
||||
fprintf(fd,"%s qscale %f \n", name, self->qScale);
|
||||
}
|
||||
/*=================== Drivable Interface ============================================================*/
|
||||
static int ConeHalt(void *pData){
|
||||
pSICSOBJ obj = pData;
|
||||
pConeData self = NULL;
|
||||
|
||||
self = (pConeData)pData;
|
||||
self = (pConeData)obj->pPrivate;
|
||||
assert(self != NULL);
|
||||
|
||||
self->pHkl->pTheta->pDrivInt->Halt(self->pHkl->pTheta);
|
||||
self->pHkl->pOmega->pDrivInt->Halt(self->pHkl->pOmega);
|
||||
self->pHkl->pChi->pDrivInt->Halt(self->pHkl->pChi);
|
||||
self->pHkl->pPhi->pDrivInt->Halt(self->pHkl->pPhi);
|
||||
|
||||
stopHKLMotors(self->pHkl);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------------------------*/
|
||||
@ -62,7 +57,7 @@ static int ConeCheckLimits(void *self, float fVal, char *error, int errLen){
|
||||
static MATRIX makeCsToPsiMatrix(reflection center, double lambda){
|
||||
MATRIX psiToCs = NULL, csToPsi = NULL, t1, t2;
|
||||
double z1[3], u;
|
||||
|
||||
|
||||
psiToCs = makeInstToConeVectorMatrix(center,lambda);
|
||||
if(psiToCs == NULL){
|
||||
return NULL;
|
||||
@ -88,37 +83,71 @@ static MATRIX makeCsToPsiMatrix(reflection center, double lambda){
|
||||
* me a lot of trouble keeping track of parameter changes in UBCALC etc.
|
||||
* ---------------------------------------------------------------------------*/
|
||||
static long ConeSetValue(void *pData, SConnection *pCon, float fVal){
|
||||
pSICSOBJ obj = pData, refList;
|
||||
pConeData self = NULL;
|
||||
float fSet[4];
|
||||
double fSet[4];
|
||||
float ffSet[4];
|
||||
double openingAngle, length;
|
||||
MATRIX csToPsi = NULL, B = NULL, newScat = NULL;
|
||||
int status;
|
||||
reflection center;
|
||||
int status, i;
|
||||
reflection center, target;
|
||||
char buffer[131];
|
||||
|
||||
const double *cell;
|
||||
double hkl[3], ang[4];
|
||||
lattice direct;
|
||||
hdbValue v;
|
||||
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
self = (pConeData)pData;
|
||||
self = (pConeData)obj->pPrivate;
|
||||
assert(self != NULL);
|
||||
|
||||
/*
|
||||
* calculate opening angle
|
||||
*/
|
||||
B = mat_creat(3,3,UNIT_MATRIX);
|
||||
status = calculateBMatrix(self->ubi->direct,B);
|
||||
cell = SXGetCell();
|
||||
direct.a = cell[0];
|
||||
direct.b = cell[1];
|
||||
direct.c = cell[2];
|
||||
direct.alpha = cell[3];
|
||||
direct.beta = cell[4];
|
||||
direct.gamma = cell[5];
|
||||
status = calculateBMatrix(direct,B);
|
||||
if(status < 0){
|
||||
SCWrite(pCon,"ERROR: cell has no volume",eError);
|
||||
return 0;
|
||||
}
|
||||
center = getReflection(self->ubi,self->center);
|
||||
openingAngle = angleBetweenReflections(B,center,self->target);
|
||||
/*
|
||||
* get center from the main reflection list
|
||||
*/
|
||||
refList = SXGetReflectionList();
|
||||
SICSHdbGetPar(obj,pCon,"center", &v);
|
||||
if(!GetRefIndexID(refList,v.v.text,hkl)){
|
||||
SCPrintf(pCon,eError,"ERROR: cannot find reflection with ID: %s", v.v.text);
|
||||
return 0;
|
||||
}
|
||||
center.h = hkl[0];
|
||||
center.k = hkl[1];
|
||||
center.l = hkl[2];
|
||||
GetRefAnglesID(refList,v.v.text,ang);
|
||||
center.s2t = ang[0];
|
||||
center.om = ang[1];
|
||||
center.chi = ang[2];
|
||||
center.phi = ang[3];
|
||||
|
||||
SICSHdbGetPar(obj,pCon,"target",&v);
|
||||
target.h = v.v.floatArray[0];
|
||||
target.k = v.v.floatArray[1];
|
||||
target.l = v.v.floatArray[2];
|
||||
openingAngle = angleBetweenReflections(B,center,target);
|
||||
|
||||
/*
|
||||
* calculate conversion matrix from cone system to PSI system
|
||||
*/
|
||||
csToPsi = makeCsToPsiMatrix(center,self->ubi->hkl->fLambda);
|
||||
csToPsi = makeCsToPsiMatrix(center,SXGetLambda());
|
||||
if(csToPsi == NULL){
|
||||
SCWrite(pCon,"ERROR: bad parameters: failed to generate conversion matrix",
|
||||
eError);
|
||||
@ -129,7 +158,16 @@ static long ConeSetValue(void *pData, SConnection *pCon, float fVal){
|
||||
* calculate scattering vector on cone and make its length
|
||||
* match the length of the apropriate scattering vector
|
||||
*/
|
||||
length = scatteringVectorLength(B,self->target) * self->qScale;
|
||||
SICSHdbGetPar(obj,pCon,"target",&v);
|
||||
target.h = v.v.floatArray[0];
|
||||
target.k = v.v.floatArray[1];
|
||||
target.l = v.v.floatArray[2];
|
||||
SICSHdbGetPar(obj,pCon,"qscale",&v);
|
||||
/*
|
||||
* calculate scattering vector on cone and make its length
|
||||
* match the length of the apropriate scattering vector
|
||||
*/
|
||||
length = scatteringVectorLength(B,target) * v.v.doubleValue;
|
||||
newScat = calcConeVector(openingAngle, fVal, length, csToPsi);
|
||||
if(newScat == NULL){
|
||||
SCWrite(pCon,"ERROR: fails to calculate cone vector",eError);
|
||||
@ -139,7 +177,7 @@ static long ConeSetValue(void *pData, SConnection *pCon, float fVal){
|
||||
/*
|
||||
* try to find setting angles for this vector
|
||||
*/
|
||||
status = findAllowedBisecting(self->pHkl->fLambda,newScat, fSet,
|
||||
status = findAllowedBisecting(SXGetLambda(),newScat, fSet,
|
||||
hklInRange, self->pHkl);
|
||||
/*
|
||||
* clean up matrices
|
||||
@ -157,201 +195,119 @@ static long ConeSetValue(void *pData, SConnection *pCon, float fVal){
|
||||
/*
|
||||
* start motors
|
||||
*/
|
||||
return startHKLMotors(self->pHkl, pCon,fSet);
|
||||
for(i = 0; i < 4; i++){
|
||||
ffSet[i] = fSet[i];
|
||||
}
|
||||
return startHKLMotors(self->pHkl, pCon,ffSet);
|
||||
}
|
||||
/*---------------------------------------------------------------------------------------------------*/
|
||||
static int checkMotors(pConeData self, SConnection *pCon){
|
||||
int status;
|
||||
|
||||
status = self->pHkl->pTheta->pDrivInt->CheckStatus(self->pHkl->pTheta, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
}
|
||||
status = self->pHkl->pOmega->pDrivInt->CheckStatus(self->pHkl->pOmega, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
}
|
||||
status = self->pHkl->pChi->pDrivInt->CheckStatus(self->pHkl->pChi, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
}
|
||||
status = self->pHkl->pPhi->pDrivInt->CheckStatus(self->pHkl->pPhi, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
int status, i;
|
||||
pMotor pMot = NULL;
|
||||
MotorFunction mots[] = {TwoTheta, Omega, Chi, Phi};
|
||||
|
||||
for(i = 0; i < 4; i++){
|
||||
pMot = SXGetMotor(mots[i]);
|
||||
if(pMot != NULL){
|
||||
status = pMot->pDrivInt->CheckStatus(pMot, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
return HWIdle;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------------------------*/
|
||||
static int ConeCheckStatus(void *pData, SConnection *pCon){
|
||||
pSICSOBJ obj = pData;
|
||||
pConeData self = NULL;
|
||||
int status;
|
||||
|
||||
self = (pConeData)pData;
|
||||
self = (pConeData)obj->pPrivate;
|
||||
assert(self != NULL);
|
||||
return checkMotors(self,pCon);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------------------------*/
|
||||
static float ConeGetValue(void *pData, SConnection *pCon){
|
||||
pSICSOBJ obj = pData;
|
||||
pConeData self = NULL;
|
||||
float fVal[3];
|
||||
int status;
|
||||
|
||||
self = (pConeData)pData;
|
||||
self = (pConeData)obj->pPrivate;
|
||||
assert(self != NULL);
|
||||
|
||||
return self->lastConeAngle;
|
||||
}
|
||||
/*=============================== Live and Death ====================================*/
|
||||
static pConeData MakeConeMot(pUBCALC u){
|
||||
static pConeData MakeConeMot(){
|
||||
pConeData self = NULL;
|
||||
|
||||
assert(u != NULL);
|
||||
|
||||
self = (pConeData)malloc(sizeof(coneData));
|
||||
if(self == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(self,0,sizeof(coneData));
|
||||
self->pDes = CreateDescriptor("Cone");
|
||||
self->pDriv = CreateDrivableInterface();
|
||||
if(self->pDes == NULL || self->pDriv == NULL){
|
||||
if(self->pDriv == NULL){
|
||||
free(self);
|
||||
return NULL;
|
||||
}
|
||||
self->pDes->GetInterface = ConeGetInterface;
|
||||
|
||||
self->pDriv->Halt = ConeHalt;
|
||||
self->pDriv->CheckLimits = ConeCheckLimits;
|
||||
self->pDriv->SetValue = ConeSetValue;
|
||||
self->pDriv->CheckStatus = ConeCheckStatus;
|
||||
self->pDriv->GetValue = ConeGetValue;
|
||||
self->ubi = u;
|
||||
self->pHkl = u->hkl;
|
||||
self->qScale = 1.0;
|
||||
return self;
|
||||
}
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
static void KillConeMot(void *pData){
|
||||
pConeData self = NULL;
|
||||
|
||||
self = (pConeData)pData;
|
||||
if(self == NULL){
|
||||
return;
|
||||
}
|
||||
if(self->pDes != NULL){
|
||||
DeleteDescriptor(self->pDes);
|
||||
}
|
||||
if(self->pDriv){
|
||||
free(self->pDriv);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*=============================== Interpreter Interface ============================*/
|
||||
int ConeAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){
|
||||
pConeData self = NULL;
|
||||
float value;
|
||||
int id;
|
||||
char pBuffer[132];
|
||||
|
||||
self = (pConeData)pData;
|
||||
assert(self != NULL);
|
||||
|
||||
if(argc > 1) {
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"center") == 0){
|
||||
if(argc > 2){
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
id = atoi(argv[2]);
|
||||
if(id < 0 || id > 2 ){
|
||||
SCWrite(pCon,"ERROR: id must be between 0 - 3",eError);
|
||||
return 0;
|
||||
}
|
||||
self->center = id;
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBuffer,131,"%s.center = %d", argv[0], self->center);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else if(strcmp(argv[1],"qscale") == 0){
|
||||
if(argc > 2){
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
self->qScale = atof(argv[2]);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBuffer,131,"%s.qscale = %f", argv[0], self->qScale);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(argv[1],"target") == 0){
|
||||
if(argc >= 5){
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
self->target.h = atof(argv[2]);
|
||||
self->target.k = atof(argv[3]);
|
||||
self->target.l = atof(argv[4]);
|
||||
self->qScale = 1.;
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBuffer,131,"%s.target = %f %f %f", argv[0],
|
||||
self->target.h, self->target.k, self->target.l);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
SCWrite(pCon,"ERROR: subcommand to cone not known",eError);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* default: print value
|
||||
*/
|
||||
value = self->pDriv->GetValue(self,pCon);
|
||||
if(value < -9000.){
|
||||
snprintf(pBuffer,131,"ERROR: failed to read %s",argv[0]);
|
||||
SCWrite(pCon,pBuffer,eError);
|
||||
return 0;
|
||||
}
|
||||
snprintf(pBuffer,131,"%s = %f", argv[0], value);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------------------------*/
|
||||
int MakeCone(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){
|
||||
pUBCALC ubi = NULL;
|
||||
pSICSOBJ pNew = NULL;
|
||||
pConeData pMot = NULL;
|
||||
char pBuffer[131];
|
||||
char pBuffer[131], pName[80];
|
||||
int status;
|
||||
pHdb cmd;
|
||||
|
||||
if(argc > 1){
|
||||
strcpy(pName,argv[1]);
|
||||
} else {
|
||||
strcpy(pName,"cone");
|
||||
}
|
||||
|
||||
if(argc < 3){
|
||||
SCWrite(pCon,"ERROR: insuffient number of arguments to MakeCone",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ubi = FindCommandData(pSics,argv[2],"UBcalc");
|
||||
if(ubi == NULL){
|
||||
snprintf(pBuffer,131,"ERROR: %s is no UBcalc object" , argv[2]);
|
||||
SCWrite(pCon,pBuffer,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pMot = MakeConeMot(ubi);
|
||||
if(pMot == NULL){
|
||||
pNew = MakeSICSOBJ(pName,"Cone");
|
||||
pMot = MakeConeMot();
|
||||
if(pNew == NULL || pMot == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating cone virtual motor",eError);
|
||||
return 0;
|
||||
}
|
||||
status = AddCommand(pSics,argv[1],ConeAction,KillConeMot,pMot);
|
||||
|
||||
pNew->pDes->GetInterface = ConeGetInterface;
|
||||
pNew->pPrivate = pMot;
|
||||
pNew->KillPrivate = DefaultFree;
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"target", usUser, makeHdbValue(HIPFLOATAR,3));
|
||||
SetHdbProperty(cmd,"__save", "true");
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"qscale", usUser, MakeHdbFloat(1.));
|
||||
SetHdbProperty(cmd,"__save", "true");
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"center", usUser, MakeHdbText("unknown"));
|
||||
SetHdbProperty(cmd,"__save", "true");
|
||||
|
||||
|
||||
if(argc > 2){
|
||||
pMot->pHkl = FindCommandData(pSics,argv[2],"4-Circle-Calculus");
|
||||
} else {
|
||||
pMot->pHkl = FindCommandData(pSics,"hkl","4-Circle-Calculus");
|
||||
}
|
||||
if(pMot->pHkl == NULL){
|
||||
snprintf(pBuffer,131,"ERROR: %s is no hkl object" , argv[2]);
|
||||
SCWrite(pCon,pBuffer,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = AddCommand(pSics,pName,InterInvokeSICSOBJ,KillSICSOBJ,pNew);
|
||||
if(status != 1){
|
||||
SCWrite(pCon,"ERROR: failed to create duplicate cone motor",eError);
|
||||
}
|
||||
return status;
|
||||
|
||||
}
|
||||
|
11
cone.h
11
cone.h
@ -13,21 +13,12 @@
|
||||
#include "ubcalc.h"
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
typedef struct {
|
||||
pObjectDescriptor pDes;
|
||||
pIDrivable pDriv;
|
||||
reflection target;
|
||||
float lastConeAngle;
|
||||
float qScale;
|
||||
pUBCALC ubi;
|
||||
int center;
|
||||
pHKL pHkl;
|
||||
pHKL pHkl;
|
||||
} coneData, *pConeData;
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
int MakeCone(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int ConeAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
#endif
|
||||
|
@ -241,15 +241,19 @@ static int ConfCheckLimits(void *pData, float fVal, char *error, int errLen){
|
||||
{
|
||||
free(self->pName);
|
||||
}
|
||||
if(self->pCon)
|
||||
{
|
||||
SCDeleteConnection(self->pCon);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*------------------- The CallBack function for interest ------------------
|
||||
* iEvent: Event ID, see event.h for SICS events
|
||||
* pEvent: May contain data from event generating object
|
||||
* pUser: Data available when registering interest, see RegisteredInfo struct
|
||||
* defined above for available info */
|
||||
static int InterestCallback(int iEvent, void *pEvent, void *pUser,
|
||||
commandContext cc)
|
||||
* defined above for available info
|
||||
--------------------------------------------------------------------------*/
|
||||
static int InterestCallback(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
pRegisteredInfo pInfo = NULL;
|
||||
char pBueffel[80];
|
||||
@ -257,7 +261,11 @@ static int ConfCheckLimits(void *pData, float fVal, char *error, int errLen){
|
||||
|
||||
assert(pEvent);
|
||||
assert(pUser);
|
||||
|
||||
|
||||
if(!SCisConnected(pInfo->pCon)){
|
||||
return -1;
|
||||
}
|
||||
|
||||
pEventData = (EventInfo *)pEvent;
|
||||
pInfo = (RegisteredInfo *)pUser;
|
||||
|
||||
@ -265,7 +273,7 @@ static int ConfCheckLimits(void *pData, float fVal, char *error, int errLen){
|
||||
pInfo->lastValue = pEventData->fVal;
|
||||
(pInfo->pCon)->conEventType=POSITION;
|
||||
sprintf(pBueffel,"%s.position = %f ", pInfo->pName, pInfo->lastValue);
|
||||
SCWriteInContext(pInfo->pCon,pBueffel,eEvent,cc);
|
||||
SCWrite(pInfo->pCon,pBueffel,eEvent);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -552,7 +560,7 @@ int ConfigurableVirtualMotorAction(SConnection *pCon, SicsInterp *pSics,
|
||||
return 0;
|
||||
}
|
||||
pRegInfo->pName = strdup(argv[0]);
|
||||
pRegInfo->pCon = pCon;
|
||||
pRegInfo->pCon = SCCopyConnection(pCon);
|
||||
value = ConfGetValue(self,pCon);
|
||||
if(!iRet)
|
||||
{
|
||||
@ -562,8 +570,8 @@ int ConfigurableVirtualMotorAction(SConnection *pCon, SicsInterp *pSics,
|
||||
}
|
||||
pRegInfo->lastValue = value;
|
||||
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),MOTDRIVE, InterestCallback, pRegInfo, KillInfo);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
lID = RegisterCallback(self->pCall, MOTDRIVE,
|
||||
InterestCallback, pRegInfo, KillInfo);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
|
166
conman.h
166
conman.h
@ -1,4 +1,3 @@
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
C O N N E C T I O N O B J E C T
|
||||
|
||||
@ -15,6 +14,10 @@
|
||||
Mark Koennecke, December 2004
|
||||
|
||||
copyright: see copyright.h
|
||||
|
||||
substantially for the new asynchronous I/O system
|
||||
|
||||
Mark Koennecke, January 2009
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef SICSCONNECT
|
||||
#define SICSCONNECT
|
||||
@ -22,6 +25,7 @@
|
||||
#include "costa.h"
|
||||
#include "SCinter.h"
|
||||
#include "network.h"
|
||||
#include "asynnet.h"
|
||||
#include "obdes.h"
|
||||
#include "commandcontext.h"
|
||||
#include "dynstring.h"
|
||||
@ -32,80 +36,57 @@ typedef int (*writeFunc)(struct __SConnection *pCon,
|
||||
char *pMessage, int iCode);
|
||||
|
||||
typedef struct __SConnection {
|
||||
/* object basics */
|
||||
pObjectDescriptor pDes;
|
||||
long lMagic;
|
||||
long ident;
|
||||
struct __SConnection *next;
|
||||
|
||||
/* I/O control */
|
||||
/* our socket */
|
||||
mkChannel *pSock;
|
||||
|
||||
/* per connection log files */
|
||||
FILE *pFiles[MAXLOGFILES];
|
||||
int iFiles;
|
||||
|
||||
int iMacro; /* suppress I/O in macro*/
|
||||
/* Copy Object Fields*/
|
||||
pObjectDescriptor pDes; /* must be here */
|
||||
long lMagic; /* connection object ID */
|
||||
long ident; /* connection idetification */
|
||||
struct __SConnection *next; /* pointer for freeConnection managenment */
|
||||
int sockHandle; /* socket handle */
|
||||
int iTelnet; /* telnet flag */
|
||||
int iOutput;
|
||||
writeFunc write; /* function doing
|
||||
writing */
|
||||
int listening; /* for listening to commandlog or other data */
|
||||
|
||||
/* execution context */
|
||||
int eInterrupt;
|
||||
int iUserRights;
|
||||
int inUse;
|
||||
int iGrab; /* grab flag for token*/
|
||||
int sicsError;
|
||||
|
||||
/*
|
||||
* for I/O Buffering
|
||||
*/
|
||||
pDynString data;
|
||||
writeFunc oldWriteFunc;
|
||||
|
||||
/*
|
||||
stuff supporting the sycamore protocol and a
|
||||
command context
|
||||
*/
|
||||
long iCmdCtr;
|
||||
int conEventType;
|
||||
int iMacro; /* suppress I/O in macro */
|
||||
writeFunc write; /* function doing writing */
|
||||
int sicsError; /* Tcl interpreter requirement */
|
||||
pDynString data; /* for I/O buffering */
|
||||
writeFunc oldWriteFunc; /* saved write function used in I/O buffering */
|
||||
long iCmdCtr; /* sycamore protocol used */
|
||||
int conEventType; /* sycamore protocol support */
|
||||
int conStatus; /* should use status enum ffr */
|
||||
int iProtocolID;
|
||||
int contextStack;
|
||||
|
||||
/* a FIFO */
|
||||
pCosta pStack;
|
||||
|
||||
/* callback registry */
|
||||
int iList;
|
||||
|
||||
/* Tasking Stuff */
|
||||
int iEnd;
|
||||
/* for keeping track of the login
|
||||
process on a non telnet connection.
|
||||
Should only be used in SCTaskFunction
|
||||
*/
|
||||
int iLogin;
|
||||
time_t conStart;
|
||||
int transID; /* transaction ID */
|
||||
char deviceID[256]; /* transaction device ID */
|
||||
int iUserRights; /* user rights of the connection */
|
||||
|
||||
/* master connection object fields */
|
||||
int iList; /* callback registry, may go? */
|
||||
int iEnd; /* flag to end connection task */
|
||||
int iLogin; /* flag for successful login process */
|
||||
time_t conStart; /* time when connection was built: used during login */
|
||||
int iOutput; /* output filter flag */
|
||||
int listening; /* for listening to commandlog or other data */
|
||||
int eInterrupt; /* interrupts */
|
||||
int inUse; /* usage counter for the connection */
|
||||
int iGrab; /* grab flag for token*/
|
||||
int iProtocolID; /* ID of the protocol on this connection */
|
||||
pCosta pStack; /* stack of pending commands */
|
||||
int contextStack; /* context stack: may go? */
|
||||
mkChannel *pSock; /* for temporary backwards compatability */
|
||||
} SConnection;
|
||||
|
||||
#include "nserver.h"
|
||||
|
||||
/*------------------------------ live & death ----------------------------*/
|
||||
SConnection *SCreateConnection(SicsInterp *pSics, mkChannel *pSock,
|
||||
SConnection *SCreateConnection(SicsInterp *pSics, int sockHandle,
|
||||
int iUserRights);
|
||||
SConnection *SCCreateDummyConnection(SicsInterp *pSics);
|
||||
void SCDeleteConnection(void *pVictim);
|
||||
|
||||
SConnection *SCCopyConnection(SConnection *pCon);
|
||||
SConnection *SCfindMaster(SConnection *pCon);
|
||||
int SCisConnected(SConnection *pCon);
|
||||
int VerifyConnection(SConnection *pCon);
|
||||
int SCVerifyConnection(SConnection *self);
|
||||
/*------------------------------- tasking --------------------------------*/
|
||||
int SCTaskFunction(void *pCon);
|
||||
void SCSignalFunction(void *pCon, int iSignal, void *pSigData);
|
||||
/* ***************************** I/O ************************************** */
|
||||
int SCAddLogFile(SConnection *self, char *name);
|
||||
int SCDelLogFile(SConnection *pCon, int iFile);
|
||||
void SCSetOutputClass(SConnection *self, int iClass);
|
||||
int SCWrite(SConnection *self, char *pBuffer, int iOut);
|
||||
int SCPrintf(SConnection *self, int iOut, char *fmt, ...);
|
||||
@ -126,21 +107,6 @@ typedef int (*writeFunc)(struct __SConnection *pCon,
|
||||
/*********************** I/O Buffering ***********************************/
|
||||
int SCStartBuffering(SConnection *pCon);
|
||||
pDynString SCEndBuffering(SConnection *pCon);
|
||||
/************************* CallBack *********************************** */
|
||||
int SCRegister(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pInter, long lID);
|
||||
int SCUnregister(SConnection *pCon, void *pInter);
|
||||
/**
|
||||
* delete a callback with the given ID
|
||||
*/
|
||||
int SCUnregisterID(SConnection *pCon, long ID);
|
||||
/**
|
||||
* retrieve the ID of a callback on the callback interface
|
||||
* given in pData. This, together with SCUnregisterID allows to
|
||||
* ceanly remove all callbacks on a connection
|
||||
* returns -1 if no ID can be found.
|
||||
*/
|
||||
long SCgetCallbackID(SConnection *pCon, void *pData);
|
||||
/******************************* Error **************************************/
|
||||
void SCSetInterrupt(SConnection *self, int eCode);
|
||||
int SCGetInterrupt(SConnection *self);
|
||||
@ -156,9 +122,6 @@ typedef int (*writeFunc)(struct __SConnection *pCon,
|
||||
int SCGetOutClass(SConnection *self);
|
||||
int SCGetGrab(SConnection *pCon);
|
||||
int SCActive(SConnection *pCon);
|
||||
/********************* simulation mode ************************************/
|
||||
void SCSetSimMode(SConnection *pCon, int value);
|
||||
int SCinSimMode(SConnection *pCon);
|
||||
/* **************************** Invocation ******************************** */
|
||||
int SCInvoke(SConnection *self,SicsInterp *pInter,char *pCommand);
|
||||
|
||||
@ -167,6 +130,23 @@ typedef int (*writeFunc)(struct __SConnection *pCon,
|
||||
int argc, char *argv[]);
|
||||
int ConSicsAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
int SCDoSockWrite(SConnection *self, char *buffer);
|
||||
int SCWriteInContext(SConnection *pCon, char *buffer, int code, commandContext cc);
|
||||
|
||||
|
||||
/* ================== =====================================================
|
||||
* These routines are obsolete and may not even work anymore.
|
||||
* Mark Koennecke, January 2009
|
||||
* ==========================================================================*/
|
||||
void SCWriteToLogFiles(SConnection *self, char *buffer);
|
||||
long SCTagContext(SConnection *self, char *tagName);
|
||||
long SCAdvanceContext(SConnection *self, char *tagName);
|
||||
int SCPushContext(SConnection *pCon, int ID, char *deviceID);
|
||||
int SCPushContext2(SConnection *pCon, commandContext cc);
|
||||
int SCPopContext(SConnection *pCon);
|
||||
commandContext SCGetContext(SConnection *pCon);
|
||||
/******************************** Store ************************************/
|
||||
typedef struct SCStore SCStore;
|
||||
|
||||
@ -189,18 +169,20 @@ void SCStoreFree(SCStore *conStore);
|
||||
/* free an SCStore */
|
||||
|
||||
void KillFreeConnections(void);
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
int SCVerifyConnection(SConnection *self);
|
||||
void SCWriteToLogFiles(SConnection *self, char *buffer);
|
||||
int SCDoSockWrite(SConnection *self, char *buffer);
|
||||
int SCWriteInContext(SConnection *pCon, char *buffer, int code, commandContext cc);
|
||||
|
||||
long SCTagContext(SConnection *self, char *tagName);
|
||||
long SCAdvanceContext(SConnection *self, char *tagName);
|
||||
int SCPushContext(SConnection *pCon, int ID, char *deviceID);
|
||||
int SCPushContext2(SConnection *pCon, commandContext cc);
|
||||
int SCPopContext(SConnection *pCon);
|
||||
commandContext SCGetContext(SConnection *pCon);
|
||||
/************************* CallBack *********************************** */
|
||||
int SCRegister(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pInter, long lID);
|
||||
int SCUnregister(SConnection *pCon, void *pInter);
|
||||
/**
|
||||
* delete a callback with the given ID
|
||||
*/
|
||||
int SCUnregisterID(SConnection *pCon, long ID);
|
||||
/**
|
||||
* retrieve the ID of a callback on the callback interface
|
||||
* given in pData. This, together with SCUnregisterID allows to
|
||||
* ceanly remove all callbacks on a connection
|
||||
* returns -1 if no ID can be found.
|
||||
*/
|
||||
long SCgetCallbackID(SConnection *pCon, void *pData);
|
||||
#endif
|
||||
|
||||
|
57
counter.c
57
counter.c
@ -96,6 +96,10 @@
|
||||
self = (pCounter)pData;
|
||||
assert(self);
|
||||
|
||||
if(!GetCountLock(self->pCountInt, pCon)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* try at least three times to do it */
|
||||
for(i = 0; i < 3; i++)
|
||||
{
|
||||
@ -118,12 +122,14 @@
|
||||
{
|
||||
SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
|
||||
SCSetInterrupt(pCon,eAbortBatch);
|
||||
ReleaseCountLock(self->pCountInt);
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
}
|
||||
SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
|
||||
SCSetInterrupt(pCon,eAbortBatch);
|
||||
ReleaseCountLock(self->pCountInt);
|
||||
return HWFault;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@ -235,6 +241,7 @@
|
||||
SCWrite(pCon,"ERROR: Cannot fix counter problem, aborting",eError);
|
||||
SCSetInterrupt(pCon,eAbortBatch);
|
||||
InvokeCallBack(self->pCall,COUNTEND,NULL);
|
||||
ReleaseCountLock(self->pCountInt);
|
||||
return eCt;
|
||||
}
|
||||
else
|
||||
@ -267,6 +274,7 @@
|
||||
if(eCt == HWIdle)
|
||||
{
|
||||
InvokeCallBack(self->pCall,COUNTEND,NULL);
|
||||
ReleaseCountLock(self->pCountInt);
|
||||
}
|
||||
return eCt;
|
||||
}
|
||||
@ -462,7 +470,7 @@
|
||||
if(!iRet)
|
||||
{
|
||||
SetStatus(eOld);
|
||||
SCWrite(pCon,"Counting aborted",eStatus);
|
||||
SCWrite(pCon,"Counting aborted",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -476,16 +484,16 @@
|
||||
iRet = Wait4Success(GetExecutor());
|
||||
if(iRet == DEVINT)
|
||||
{
|
||||
SCWrite(pCon,"Counting aborted due to Interrupt",eStatus);
|
||||
SCWrite(pCon,"Counting aborted due to Interrupt",eError);
|
||||
}
|
||||
else if(iRet == DEVERROR)
|
||||
{
|
||||
SCWrite(pCon,"Counting finished with Problems",eStatus);
|
||||
SCWrite(pCon,"Counting finished with Problems",eError);
|
||||
iRet = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
SCWrite(pCon,"Counting finished",eStatus);
|
||||
SCWrite(pCon,"Counting finished",eValue);
|
||||
iRet = 1;
|
||||
}
|
||||
SetStatus(eOld);
|
||||
@ -715,15 +723,18 @@
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int CounterInterest(int iEvent, void *pEvent, void *pUser,
|
||||
commandContext cc)
|
||||
static int CounterInterest(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
SConnection *pCon = NULL;
|
||||
pMonEvent pMon = NULL;
|
||||
char pBueffel[512];
|
||||
int rights;
|
||||
|
||||
if(iEvent != MONITOR)
|
||||
if(pCon == NULL || !SCisConnected(pCon)){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(iEvent != MONITOR || pCon == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -737,10 +748,8 @@
|
||||
/**
|
||||
* prevent this to be written to log files
|
||||
*/
|
||||
rights = SCGetRights(pCon);
|
||||
SCSetRights(pCon,usSpy);
|
||||
SCWriteInContext(pCon,pBueffel,eWarning,cc);
|
||||
SCSetRights(pCon,rights);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@ -817,6 +826,10 @@
|
||||
return 1;
|
||||
break;
|
||||
case 2: /* Set Preset */
|
||||
if(isRunning(self->pCountInt)){
|
||||
SCWrite(pCon,"ERROR: cannot change preset while counting", eError);
|
||||
return 0;
|
||||
}
|
||||
if(isAuthorised(pCon,usUser))
|
||||
{
|
||||
iRet2 = SetCounterPreset(self,PaRes.Arg[0].fVal);
|
||||
@ -844,6 +857,10 @@
|
||||
return 1;
|
||||
break;
|
||||
case 4: /* Set Mode */
|
||||
if(isRunning(self->pCountInt)){
|
||||
SCWrite(pCon,"ERROR: cannot change mode while counting", eError);
|
||||
return 0;
|
||||
}
|
||||
if(isAuthorised(pCon,usUser))
|
||||
{
|
||||
if(strcmp(PaRes.Arg[0].text,"timer") == 0)
|
||||
@ -905,13 +922,13 @@
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
case 9: /* interest */
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon), MONITOR, CounterInterest,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
lID = RegisterCallback(self->pCall, MONITOR, CounterInterest,
|
||||
SCCopyConnection(pCon),
|
||||
SCDeleteConnection);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
case 10: /* uninterest */
|
||||
RemoveCallback2(self->pCall,pCon);
|
||||
RemoveCallbackCon(self->pCall,pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
case 11: /* status */
|
||||
@ -1008,6 +1025,10 @@
|
||||
/* mode */
|
||||
if(PaRes.Arg[0].iVal) /* set case */
|
||||
{
|
||||
if(isRunning(self->pCountInt)){
|
||||
SCWrite(pCon,"ERROR: cannot change mode while counting",eError);
|
||||
return 0;
|
||||
}
|
||||
if(isAuthorised(pCon,usUser))
|
||||
{
|
||||
if(strcmp(PaRes.Arg[0].text,"timer") == 0)
|
||||
@ -1053,6 +1074,10 @@
|
||||
case 18: /* preset */
|
||||
if(PaRes.Arg[0].iVal) /* set case */
|
||||
{
|
||||
if(isRunning(self->pCountInt)){
|
||||
SCWrite(pCon,"ERROR: cannot set preset while counting", eError);
|
||||
return 0;
|
||||
}
|
||||
if(isAuthorised(pCon,usUser))
|
||||
{
|
||||
iRet2 = SetCounterPreset(self,PaRes.Arg[0].fVal);
|
||||
@ -1095,6 +1120,10 @@
|
||||
}
|
||||
break;
|
||||
case 20: /* setpar*/
|
||||
if(isRunning(self->pCountInt)){
|
||||
SCWrite(pCon,"ERROR: cannot change parameters while counting", eError);
|
||||
return 0;
|
||||
}
|
||||
if(!SCMatchRights(pCon,usMugger))
|
||||
{
|
||||
return 0;
|
||||
|
20
danu.c
20
danu.c
@ -95,14 +95,19 @@ static int writeDataNumber(pDataNumber self, int iNum)
|
||||
return 1;
|
||||
}
|
||||
/*------------------- The CallBack function for interest ------------------*/
|
||||
static int InterestCallback(int iEvent, void *pEvent, void *pUser,
|
||||
commandContext cc)
|
||||
static int InterestCallback(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
pDataNumber self = NULL;
|
||||
SConnection *pCon = NULL;
|
||||
char pBueffel[132];
|
||||
int iNum;
|
||||
|
||||
pCon = (SConnection *)pUser;
|
||||
if(pCon == NULL || !SCisConnected(pCon))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(iEvent != VALUECHANGE)
|
||||
{
|
||||
return 1;
|
||||
@ -111,7 +116,6 @@ static int writeDataNumber(pDataNumber self, int iNum)
|
||||
assert(pEvent);
|
||||
assert(pUser);
|
||||
|
||||
pCon = (SConnection *)pUser;
|
||||
self = (pDataNumber)pEvent;
|
||||
|
||||
/*
|
||||
@ -121,7 +125,7 @@ static int writeDataNumber(pDataNumber self, int iNum)
|
||||
if(iNum > 0)
|
||||
{
|
||||
snprintf(pBueffel,131,"sicsdatanumber = %d", iNum);
|
||||
SCWriteInContext(pCon,pBueffel,eValue,cc);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -331,16 +335,16 @@ int NewThousand(pDataNumber self)
|
||||
}
|
||||
if(strcmp(argv[1],"interest") == 0)
|
||||
{
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),
|
||||
lID = RegisterCallback(self->pCall,
|
||||
VALUECHANGE, InterestCallback,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
SCCopyConnection(pCon),
|
||||
SCDeleteConnection);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
if(strcmp(argv[1],"uninterest") == 0)
|
||||
{
|
||||
RemoveCallback2(self->pCall,pCon);
|
||||
RemoveCallbackCon(self->pCall,pCon);
|
||||
SCSendOK(pCon);
|
||||
}
|
||||
|
||||
|
288
devexec.c
288
devexec.c
@ -12,6 +12,9 @@
|
||||
Refactored and instrumentation for instrument staticstics added.
|
||||
Mark Koennecke, July 2006
|
||||
|
||||
Reworked to use copied connection objects instead of context pushes.
|
||||
Mark Koennecke, January 2009
|
||||
|
||||
Copyright:
|
||||
|
||||
Labor fuer Neutronenstreuung
|
||||
@ -113,7 +116,7 @@ void DevexecLog(char *operation, char *device) {
|
||||
pObjectDescriptor pDescriptor;
|
||||
float fVal;
|
||||
char *name;
|
||||
commandContext comCon;
|
||||
SConnection *pCon;
|
||||
} DevEntry, *pDevEntry;
|
||||
/*------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
@ -123,7 +126,8 @@ typedef struct {
|
||||
pIDrivable pDrivInt;
|
||||
}checkContext, *pCheckContext;
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static pDevEntry CreateDevEntry(pObjectDescriptor pDes, void *pData,
|
||||
static pDevEntry CreateDevEntry(pObjectDescriptor pDes, SConnection *pCon,
|
||||
void *pData,
|
||||
float fVal, char *name)
|
||||
{
|
||||
pDevEntry pNew = NULL;
|
||||
@ -139,7 +143,7 @@ typedef struct {
|
||||
pNew->pData = pData;
|
||||
pNew->name = strdup(name);
|
||||
pNew->fVal = fVal;
|
||||
memset(&pNew->comCon,0,sizeof(commandContext));
|
||||
pNew->pCon = SCCopyConnection(pCon);
|
||||
return pNew;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -151,9 +155,11 @@ typedef struct {
|
||||
{
|
||||
free(self->name);
|
||||
}
|
||||
if(self->pCon){
|
||||
SCDeleteConnection(self->pCon);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
|
||||
/* ----------------- The Executor himself ---------------------------------*/
|
||||
typedef struct __EXELIST{
|
||||
pObjectDescriptor pDes;
|
||||
@ -242,6 +248,11 @@ typedef struct {
|
||||
if(self->pCall)
|
||||
DeleteCallBackInterface(self->pCall);
|
||||
|
||||
if(self->pOwner){
|
||||
SCDeleteConnection(self->pOwner);
|
||||
self->pOwner = NULL;
|
||||
}
|
||||
|
||||
free(self);
|
||||
pServ->pExecutor = NULL;
|
||||
if(devLog != NULL){
|
||||
@ -279,7 +290,7 @@ typedef struct {
|
||||
/* may we? */
|
||||
if(self->pOwner != NULL)
|
||||
{
|
||||
if(pCon != self->pOwner)
|
||||
if(pCon->ident != self->pOwner->ident)
|
||||
{
|
||||
/* this hack helps on rita2, when using the sendsics script
|
||||
which opens a client for every command */
|
||||
@ -288,7 +299,8 @@ typedef struct {
|
||||
overwriteOwner = overwriteOption && *overwriteOption != '0';
|
||||
}
|
||||
if (overwriteOwner) {
|
||||
self->pOwner = pCon;
|
||||
SCDeleteConnection(self->pOwner);
|
||||
self->pOwner = SCCopyConnection(pCon);
|
||||
} else {
|
||||
SCWrite(pCon,
|
||||
"ERROR: somebody else is still driving, Request rejected",eError);
|
||||
@ -298,7 +310,7 @@ typedef struct {
|
||||
}
|
||||
else
|
||||
{
|
||||
self->pOwner = pCon;
|
||||
self->pOwner = SCCopyConnection(pCon);
|
||||
}
|
||||
if(self->iLock == 1)
|
||||
{
|
||||
@ -308,14 +320,12 @@ typedef struct {
|
||||
|
||||
/* well create a new entry */
|
||||
self->iStop = 0;
|
||||
pNew = CreateDevEntry(pDes,pData,fNew,name);
|
||||
pNew = CreateDevEntry(pDes,pCon,pData,fNew,name);
|
||||
if(!pNew)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: memory exhausted in Device Executor ",eError);
|
||||
return 0;
|
||||
}
|
||||
pNew->comCon = SCGetContext(pCon);
|
||||
strncpy(pNew->comCon.deviceID,name,SCDEVIDLEN);
|
||||
|
||||
/* start it */
|
||||
pDrivInt = pDes->GetInterface(pData,DRIVEID);
|
||||
@ -328,7 +338,7 @@ typedef struct {
|
||||
oldVal = pDrivInt->GetValue(pData,pCon);
|
||||
snprintf(pBueffel,131,"Driving %s from %8.3f to %8.3f",
|
||||
name, oldVal, fNew);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
}
|
||||
else if(pCountInt)
|
||||
@ -346,9 +356,9 @@ typedef struct {
|
||||
{
|
||||
LLDnodeAppendFrom(self->iList,&pNew);
|
||||
sprintf(pBueffel,"started");
|
||||
if(NULL!=pNew->comCon.deviceID)
|
||||
if(NULL!=pNew->pCon->deviceID)
|
||||
{
|
||||
snprintf(pBueffel,130,"started (%s)",pNew->comCon.deviceID);
|
||||
snprintf(pBueffel,130,"started (%s)",pNew->pCon->deviceID);
|
||||
}
|
||||
ExeInterest(self, pNew, pBueffel);
|
||||
self->iRun = 1;
|
||||
@ -375,13 +385,15 @@ typedef struct {
|
||||
DeleteDevEntry(pNew);
|
||||
if(LLDcheck(self->iList) >= LIST_EMPTY)
|
||||
{
|
||||
if(self->pOwner != NULL){
|
||||
SCDeleteConnection(self->pOwner);
|
||||
}
|
||||
self->pOwner = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int StartMotor(pExeList self, SicsInterp *pSics, SConnection *pCon,
|
||||
char *name, float fVal)
|
||||
@ -467,183 +479,10 @@ typedef struct {
|
||||
return StartDevice(self,name,pCter->pDes,(void *)pCter,
|
||||
pCon,pCter->pDriv->fPreset);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int CheckExeListOld(pExeList self)
|
||||
{
|
||||
int iRet;
|
||||
pDevEntry pDev = NULL;
|
||||
pICountable pCountInt = NULL;
|
||||
pIDrivable pDrivInt = NULL;
|
||||
int eCode;
|
||||
int isCounting=0, isDriving=0;
|
||||
char pBueffel[512];
|
||||
SConnection *pCon;
|
||||
pCon = self->pOwner;
|
||||
|
||||
assert(self);
|
||||
|
||||
/* Sometimes this gets called, though nothing is running. There are
|
||||
cases where this is feasible for maintainance, but in some cases it
|
||||
is pure rubbish, because nothing runs. This will be checked here.
|
||||
*/
|
||||
if((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY))
|
||||
{
|
||||
self->iRun = 0;
|
||||
self->iEnd = 1;
|
||||
self->iStop = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
check the status of all registered devices. Remove when finished
|
||||
*/
|
||||
iRet = LLDnodePtr2First(self->iList);
|
||||
while(iRet != 0)
|
||||
{
|
||||
LLDnodeDataTo(self->iList,&pDev);
|
||||
if(pDev)
|
||||
{
|
||||
SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID);
|
||||
|
||||
pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID);
|
||||
pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
|
||||
|
||||
if(pDrivInt)
|
||||
{
|
||||
eCode = pDrivInt->CheckStatus(pDev->pData,self->pOwner);
|
||||
}
|
||||
else if(pCountInt)
|
||||
{
|
||||
eCode = pCountInt->CheckCountStatus(pDev->pData,self->pOwner);
|
||||
}
|
||||
switch(eCode)
|
||||
{
|
||||
case HWIdle:
|
||||
case OKOK:
|
||||
if(pCountInt)
|
||||
{
|
||||
pCountInt->TransferData(pDev->pData,self->pOwner);
|
||||
}
|
||||
else if(pDrivInt)
|
||||
{
|
||||
pDrivInt->iErrorCount = 0;
|
||||
}
|
||||
ExeInterest(self, pDev, "finished");
|
||||
DeleteDevEntry(pDev);
|
||||
LLDnodeDelete(self->iList);
|
||||
SCWrite(pCon, "", eFinish);
|
||||
iRet = LLDnodePtr2Prev(self->iList);
|
||||
if(SCGetInterrupt(self->pOwner) != eContinue)
|
||||
{
|
||||
self->iStatus = DEVINT;
|
||||
SCPopContext(self->pOwner);
|
||||
return -1;
|
||||
}
|
||||
self->iStatus = DEVDONE;
|
||||
break;
|
||||
case HWFault: /* real HW error: burning, no net etc.. */
|
||||
ExeInterest(self, pDev, "finished with problem");
|
||||
DeleteDevEntry(pDev);
|
||||
pDev = NULL;
|
||||
SCWrite(pCon, "", eFinish);
|
||||
LLDnodeDataTo(self->iList,&pDev);
|
||||
LLDnodeDelete(self->iList);
|
||||
iRet = LLDnodePtr2Prev(self->iList);
|
||||
self->iStatus = DEVERROR;
|
||||
if(pDrivInt)
|
||||
{
|
||||
pDrivInt->iErrorCount++;
|
||||
}
|
||||
if(SCGetInterrupt(self->pOwner) != eContinue)
|
||||
{
|
||||
self->iStatus = DEVINT;
|
||||
SCPopContext(self->pOwner);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case HWNoBeam:
|
||||
SetStatus(eOutOfBeam);
|
||||
if(SCGetInterrupt(self->pOwner) != eContinue)
|
||||
{
|
||||
SetStatus(eEager);
|
||||
self->iStatus = DEVINT;
|
||||
SCPopContext(self->pOwner);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case HWPause:
|
||||
SetStatus(ePaused);
|
||||
if(SCGetInterrupt(self->pOwner) != eContinue)
|
||||
{
|
||||
ContinueExecution(self);
|
||||
self->iStatus = DEVINT;
|
||||
SCPopContext(self->pOwner);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case HWBusy:
|
||||
if(pDrivInt != NULL)
|
||||
{
|
||||
isDriving = 1;
|
||||
}
|
||||
else if(pCountInt != NULL)
|
||||
{
|
||||
isCounting = 1;
|
||||
}
|
||||
self->iStatus = DEVBUSY;
|
||||
break;
|
||||
case HWPosFault: /* cannot get somewhere... */
|
||||
ExeInterest(self, pDev, "finished with problem");
|
||||
DeleteDevEntry(pDev);
|
||||
LLDnodeDelete(self->iList);
|
||||
SCWrite(pCon, "", eFinish);
|
||||
self->iStatus = DEVERROR;
|
||||
if(pDrivInt)
|
||||
{
|
||||
pDrivInt->iErrorCount++;
|
||||
}
|
||||
if(SCGetInterrupt(self->pOwner) != eContinue)
|
||||
{
|
||||
self->iStatus = DEVINT;
|
||||
SCPopContext(self->pOwner);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
SCPopContext(self->pOwner);
|
||||
}
|
||||
iRet = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
|
||||
if (isCounting) {
|
||||
if (isDriving) {
|
||||
SetStatus(eCountDrive);
|
||||
} else {
|
||||
SetStatus(eCounting);
|
||||
}
|
||||
} else if (isDriving) {
|
||||
SetStatus(eDriving);
|
||||
}
|
||||
|
||||
iRet = LLDnodePtr2First(self->iList);
|
||||
if(LLDcheck(self->iList) == LIST_EMPTY)
|
||||
{
|
||||
self->pOwner = NULL;
|
||||
self->iEnd = 1;
|
||||
self->iRun = 0;
|
||||
self->lTask = -1;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int checkInterrupt(pCheckContext pCheck, int targetStatus){
|
||||
if(SCGetInterrupt(pCheck->self->pOwner) != eContinue) {
|
||||
pCheck->self->iStatus = DEVINT;
|
||||
SCPopContext(pCheck->self->pOwner);
|
||||
SetStatus(eEager);
|
||||
return -1;
|
||||
} else {
|
||||
@ -654,15 +493,13 @@ static int checkInterrupt(pCheckContext pCheck, int targetStatus){
|
||||
static int initializeCheck(pCheckContext pCheck, pDevEntry pDev){
|
||||
int eCode = HWFault;
|
||||
|
||||
SCPushContext(pCheck->self->pOwner,
|
||||
pDev->comCon.transID, pDev->comCon.deviceID);
|
||||
pCheck->pDev = pDev;
|
||||
pCheck->pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData,DRIVEID);
|
||||
pCheck->pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
|
||||
if(pCheck->pDrivInt != NULL){
|
||||
eCode = pCheck->pDrivInt->CheckStatus(pDev->pData,pCheck->self->pOwner);
|
||||
eCode = pCheck->pDrivInt->CheckStatus(pDev->pData,pDev->pCon);
|
||||
} else if(pCheck->pCountInt != NULL) {
|
||||
eCode = pCheck->pCountInt->CheckCountStatus(pDev->pData,pCheck->self->pOwner);
|
||||
eCode = pCheck->pCountInt->CheckCountStatus(pDev->pData,pDev->pCon);
|
||||
}
|
||||
return eCode;
|
||||
}
|
||||
@ -671,7 +508,7 @@ static int finishDevice(pCheckContext pCheck){
|
||||
int status;
|
||||
|
||||
if(pCheck->pCountInt != NULL) {
|
||||
pCheck->pCountInt->TransferData(pCheck->pDev->pData,pCheck->self->pOwner);
|
||||
pCheck->pCountInt->TransferData(pCheck->pDev->pData,pCheck->pDev->pCon);
|
||||
} else if(pCheck->pDrivInt != NULL) {
|
||||
pCheck->pDrivInt->iErrorCount = 0;
|
||||
}
|
||||
@ -704,6 +541,9 @@ static int errorDevice(pCheckContext pCheck){
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int testFinish(pExeList self){
|
||||
if((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY)) {
|
||||
if(self->pOwner != NULL){
|
||||
SCDeleteConnection(self->pOwner);
|
||||
}
|
||||
self->pOwner = NULL;
|
||||
self->iRun = 0;
|
||||
self->iEnd = 1;
|
||||
@ -725,8 +565,6 @@ static int testFinish(pExeList self){
|
||||
int eCode;
|
||||
int isCounting=0, isDriving=0;
|
||||
char pBueffel[512];
|
||||
SConnection *pCon;
|
||||
pCon = self->pOwner;
|
||||
|
||||
assert(self);
|
||||
|
||||
@ -812,7 +650,6 @@ static int testFinish(pExeList self){
|
||||
}
|
||||
break;
|
||||
}
|
||||
SCPopContext(self->pOwner);
|
||||
}
|
||||
status = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
@ -866,12 +703,12 @@ static int testFinish(pExeList self){
|
||||
iRet = CheckExeList(self);
|
||||
if(iRet == 1) /* nothing to do! */
|
||||
{
|
||||
SCWrite(pCon,"Machine idle",eStatus);
|
||||
SCWrite(pCon,"Machine idle",eValue);
|
||||
return 1;
|
||||
}
|
||||
else if(iRet == -1)
|
||||
{
|
||||
SCWrite(pCon,"Handling Interrupt",eStatus);
|
||||
SCWrite(pCon,"Handling Interrupt",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -884,7 +721,7 @@ static int testFinish(pExeList self){
|
||||
if(pDev)
|
||||
{
|
||||
sprintf(pBueffel,"\t%s %f",pDev->name,pDev->fVal);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
iRet = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
@ -949,9 +786,7 @@ static int testFinish(pExeList self){
|
||||
}
|
||||
iRet = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
SCPushContext(self->pOwner,0,"system");
|
||||
SCWrite(self->pOwner,"ERROR: Full Stop called!!",eError);
|
||||
SCPopContext(self->pOwner);
|
||||
if(SCGetInterrupt(self->pOwner) > eContinue)
|
||||
{
|
||||
self->iStatus = DEVINT;
|
||||
@ -1009,12 +844,10 @@ static int testFinish(pExeList self){
|
||||
pDev = (pDevEntry)LLDnodePtr(self->iList);
|
||||
if(pDev)
|
||||
{
|
||||
SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID);
|
||||
|
||||
pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
|
||||
if(pCountInt)
|
||||
{
|
||||
iRet = pCountInt->Pause(pDev->pData,self->pOwner);
|
||||
iRet = pCountInt->Pause(pDev->pData,pDev->pCon);
|
||||
if(!iRet)
|
||||
{
|
||||
iRes = 0;
|
||||
@ -1022,7 +855,6 @@ static int testFinish(pExeList self){
|
||||
}
|
||||
|
||||
}
|
||||
SCPopContext(self->pOwner);
|
||||
iRet = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
SetStatus(ePaused);
|
||||
@ -1072,13 +904,11 @@ static int testFinish(pExeList self){
|
||||
pCountInt = pDev->pDescriptor->GetInterface(pDev->pData,COUNTID);
|
||||
if(pCountInt)
|
||||
{
|
||||
SCPushContext(self->pOwner, pDev->comCon.transID, pDev->comCon.deviceID);
|
||||
iRet = pCountInt->Continue(pDev->pData,self->pOwner);
|
||||
iRet = pCountInt->Continue(pDev->pData,pDev->pCon);
|
||||
if(!iRet)
|
||||
{
|
||||
iRes = 0;
|
||||
}
|
||||
SCPopContext(self->pOwner);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1113,6 +943,7 @@ static int testFinish(pExeList self){
|
||||
{
|
||||
self->iStatus = DEVINT;
|
||||
}
|
||||
SCDeleteConnection(self->pOwner);
|
||||
}
|
||||
self->pOwner = NULL;
|
||||
self->iEnd = 1;
|
||||
@ -1156,15 +987,17 @@ static int testFinish(pExeList self){
|
||||
return iRet;
|
||||
}
|
||||
/*------------------- The CallBack function for interest ------------------*/
|
||||
static int DrivStatCallback(int iEvent, void *text, void *pCon,
|
||||
commandContext cc)
|
||||
static int DrivStatCallback(int iEvent, void *text, void *pCon)
|
||||
{
|
||||
assert(pCon);
|
||||
assert(text);
|
||||
|
||||
SCPushContext2(pCon,cc);
|
||||
SCWrite(pCon, text, eValue);
|
||||
SCPopContext(pCon);
|
||||
SConnection *con = (SConnection *)pCon;
|
||||
|
||||
if(con == NULL || !SCisConnected(con))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
SCWrite(pCon, text, eLog);
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -1183,17 +1016,15 @@ static int testFinish(pExeList self){
|
||||
if (argc == 2) {
|
||||
if (strcmp(argv[1], "interest") == 0)
|
||||
{
|
||||
list = RegisterCallback(self->pCall, SCGetContext(pCon),
|
||||
list = RegisterCallback(self->pCall,
|
||||
DRIVSTAT, DrivStatCallback,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon, pSics, self->pCall,list);
|
||||
SCCopyConnection(pCon), NULL);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(argv[1], "uninterest") == 0)
|
||||
{
|
||||
RemoveCallback2(self->pCall, pCon);
|
||||
SCUnregister(pCon, self->pCall);
|
||||
{
|
||||
RemoveCallbackCon(self->pCall,pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
@ -1240,12 +1071,12 @@ static int testFinish(pExeList self){
|
||||
}
|
||||
else if(iRet == DEVDONE)
|
||||
{
|
||||
SCWrite(pCon,"All done",eStatus);
|
||||
SCWrite(pCon,"All done",eValue);
|
||||
iRet = 1;
|
||||
}
|
||||
else if(iRet == DEVERROR)
|
||||
{
|
||||
SCWrite(pCon,"Finished with Problems",eStatus);
|
||||
SCWrite(pCon,"Finished with Problems",eValue);
|
||||
iRet = 1;
|
||||
}
|
||||
SetStatus(eEager);
|
||||
@ -1422,6 +1253,7 @@ static int testFinish(pExeList self){
|
||||
{
|
||||
int *iInt;
|
||||
pExeList self = NULL;
|
||||
SConnection *pCon = NULL;
|
||||
|
||||
self = (pExeList)pEL;
|
||||
assert(self);
|
||||
@ -1433,12 +1265,16 @@ static int testFinish(pExeList self){
|
||||
{
|
||||
if(self->pOwner)
|
||||
{
|
||||
SCPushContext(self->pOwner,0,"system");
|
||||
SCWrite(self->pOwner,
|
||||
pCon = SCCopyConnection(self->pOwner);
|
||||
if(pCon != NULL){
|
||||
pCon->transID = 0;
|
||||
strcpy(pCon->deviceID,"system");
|
||||
SCWrite(pCon,
|
||||
"ERROR: Interrupting Current Hardware Operation",
|
||||
eError);
|
||||
SCSetInterrupt(self->pOwner,*iInt);
|
||||
SCPopContext(self->pOwner);
|
||||
SCSetInterrupt(pCon,*iInt);
|
||||
SCDeleteConnection(pCon);
|
||||
}
|
||||
}
|
||||
StopExe(self,"all");
|
||||
}
|
||||
@ -1456,7 +1292,7 @@ void UnlockDeviceExecutor(pExeList self)
|
||||
assert(self);
|
||||
self->iLock = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
11
devser.c
11
devser.c
@ -217,7 +217,13 @@ void DevKill(DevSer *devser) {
|
||||
}
|
||||
}
|
||||
|
||||
void DevQueue(DevSer *devser, void *actionData, DevPrio prio,
|
||||
void DevDisconnect(DevSer *devser){
|
||||
if(devser->asyncConn){
|
||||
AsconDisconnect(devser->asyncConn);
|
||||
}
|
||||
}
|
||||
|
||||
int DevQueue(DevSer *devser, void *actionData, DevPrio prio,
|
||||
DevActionHandler hdl, DevActionMatch *matchFunc,
|
||||
DevKillActionData *killFunc) {
|
||||
DevAction *action, **ptr2Last;
|
||||
@ -228,13 +234,14 @@ void DevQueue(DevSer *devser, void *actionData, DevPrio prio,
|
||||
ptr2Last = &devser->actions;
|
||||
for (action = devser->actions; action != NULL && action->prio >= prio; action = action->next) {
|
||||
if (action->hdl == hdl && matchFunc(actionData, action->data)) {
|
||||
return; /* there is already an identical action */
|
||||
return 0; /* there is already an identical action */
|
||||
}
|
||||
ptr2Last = &action->next;
|
||||
}
|
||||
new = DevNewAction(actionData, hdl, killFunc, prio);
|
||||
new->next = action;
|
||||
*ptr2Last = new;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int DevUnschedule(DevSer *devser, void *actionData,
|
||||
|
8
devser.h
8
devser.h
@ -54,6 +54,10 @@ void DevDebugMode(DevSer *devser, int steps);
|
||||
* \param devser the device serializer
|
||||
*/
|
||||
void DevKill(DevSer *devser);
|
||||
/** \brief Disconnect
|
||||
* \param devser The device serializer to disconnect
|
||||
*/
|
||||
void DevDisconnect(DevSer *devser);
|
||||
|
||||
/** \brief Queue an action
|
||||
*
|
||||
@ -67,8 +71,10 @@ void DevKill(DevSer *devser);
|
||||
* \param killFunc the action data kill function (called from DevKill and
|
||||
* after the action has finished, i.e. when hdl returned NULL)
|
||||
* or NULL if no kill function is needed.
|
||||
* \return 0 when not queued because a similar action is already on the queue,
|
||||
* 1 on success.
|
||||
*/
|
||||
void DevQueue(DevSer *devser, void *actionData, DevPrio prio,
|
||||
int DevQueue(DevSer *devser, void *actionData, DevPrio prio,
|
||||
DevActionHandler hdl, DevActionMatch *matchFunc,
|
||||
DevKillActionData *killFunc) ;
|
||||
|
||||
|
@ -312,7 +312,7 @@ static int DiffScanTask(void *pData){
|
||||
if(data->Monitors[self->scaleMonitor -1] -
|
||||
self->last.Monitors[self->scaleMonitor-1] < 5) {
|
||||
SCWrite(self->scanObject->pCon,
|
||||
"WARNING: low count rate",eWarning);
|
||||
"WARNING: low count rate",eLog);
|
||||
}
|
||||
rawCount = data->lCount;
|
||||
rawMon = data->Monitors[self->scaleMonitor-1];
|
||||
@ -329,7 +329,7 @@ static int DiffScanTask(void *pData){
|
||||
self->scanObject->iCounts -1,
|
||||
fPos, countValue, rawCount,
|
||||
rawMon);
|
||||
SCWrite(self->scanObject->pCon,pBueffel,eWarning);
|
||||
SCWrite(self->scanObject->pCon,pBueffel,eLog);
|
||||
InvokeCallBack(self->scanObject->pCall,SCANPOINT,self->scanObject);
|
||||
|
||||
/*
|
||||
|
8
drive.c
8
drive.c
@ -131,21 +131,21 @@
|
||||
{
|
||||
SCSetInterrupt(pCon,eContinue);
|
||||
sprintf(pBueffel,"Driving %s aborted at %9.3f",name, fPos);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if(iRet == DEVDONE)
|
||||
{
|
||||
sprintf(pBueffel,"Driving %s to %9.3f done", name, fPos);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,
|
||||
"Driving %s finished with problems, position: %9.3f",name,fPos);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -393,7 +393,7 @@
|
||||
SetStatus(eOld);
|
||||
return 0;
|
||||
}
|
||||
SCWrite(pCon,"Driving finished sucessfully",eStatus);
|
||||
SCWrite(pCon,"Driving finished sucessfully",eValue);
|
||||
SetStatus(eOld);
|
||||
return 1;
|
||||
}
|
||||
|
13
dynstring.c
13
dynstring.c
@ -254,6 +254,19 @@
|
||||
|
||||
return self->iTextLen;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int DynStringBackspace(pDynString self)
|
||||
{
|
||||
assert(self);
|
||||
assert(self->iMAGIC == DYNMAGIC);
|
||||
|
||||
if(self->iTextLen > 0)
|
||||
{
|
||||
self->pBuffer[self->iTextLen - 1] = '\0';
|
||||
self->iTextLen--;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -87,6 +87,10 @@
|
||||
|
||||
int DynStringClear(pDynString self);
|
||||
/*
|
||||
removes all old dat from the dynstring
|
||||
removes all old data from the dynstring
|
||||
*/
|
||||
int DynStringBackspace(pDynString self);
|
||||
/*
|
||||
removes one character at the end from the dynstring
|
||||
*/
|
||||
#endif
|
||||
|
@ -100,7 +100,14 @@
|
||||
self->start = time(NULL);
|
||||
self->lastt = 0;
|
||||
self->iWarned = 0;
|
||||
self->conn = SCSave(pCon, self->conn);
|
||||
if(self->conn != NULL){
|
||||
SCDeleteConnection(self->conn);
|
||||
}
|
||||
self->conn = SCCopyConnection(pCon);
|
||||
if(self->conn == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory in EVIDrive", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* try at least three times to do it */
|
||||
for(i = 0; i < 3; i++)
|
||||
@ -302,7 +309,7 @@
|
||||
{
|
||||
sprintf(pBueffel,"%s inside tolerance, wait %.2f sec to settle",
|
||||
self->pName, (self->lastt + tmo - now)*1.0);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
}
|
||||
notifyStatus(self, pCon, HWBusy);
|
||||
return HWBusy;
|
||||
@ -322,7 +329,7 @@
|
||||
if (tmo > 0) {
|
||||
sprintf(pBueffel,"%s outside tolerance, settling time suspended",
|
||||
self->pName);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
}
|
||||
self->lastt -= now;
|
||||
}
|
||||
@ -376,7 +383,7 @@
|
||||
}
|
||||
|
||||
/*---------------------------- Error Handlers --------------------------------*/
|
||||
static void ErrWrite(char *txt, SCStore *conn)
|
||||
static void ErrWrite(char *txt, SConnection *conn)
|
||||
{
|
||||
pExeList pExe;
|
||||
SConnection *pCon = NULL;
|
||||
@ -386,13 +393,11 @@ static void ErrWrite(char *txt, SCStore *conn)
|
||||
|
||||
if (pCon)
|
||||
{
|
||||
SCWrite(pCon,txt,eWarning);
|
||||
SCWrite(pCon,txt,eLog);
|
||||
}
|
||||
else
|
||||
{
|
||||
pCon = SCStorePush(conn);
|
||||
SCWrite(pCon, txt, eWarning);
|
||||
SCStorePop(conn);
|
||||
SCWrite(conn, txt, eLog);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@ -436,7 +441,7 @@ static void ErrReport(pEVControl self)
|
||||
pExe = GetExecutor();
|
||||
if(IsCounting(pExe))
|
||||
{
|
||||
SCWrite(GetExeOwner(pExe),"Pausing till OK",eError);
|
||||
SCWrite(GetExeOwner(pExe),"Pausing till OK",eLogError);
|
||||
PauseExecution(pExe);
|
||||
|
||||
/* wait till OK */
|
||||
@ -796,7 +801,10 @@ static void ErrReport(pEVControl self)
|
||||
pRes->pName = strdup(pName);
|
||||
pRes->eMode = EVIdle;
|
||||
pRes->iWarned = 0;
|
||||
pRes->conn = NULL;
|
||||
if(pRes->conn != NULL){
|
||||
SCDeleteConnection(pRes->conn);
|
||||
pRes->conn = NULL;
|
||||
}
|
||||
|
||||
/* a terminal error gives a -1 in iRet */
|
||||
if(iRet < 0)
|
||||
@ -871,7 +879,7 @@ static void ErrReport(pEVControl self)
|
||||
}
|
||||
if (self->conn != NULL)
|
||||
{
|
||||
SCStoreFree(self->conn);
|
||||
SCDeleteConnection(self->conn);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
@ -1064,17 +1072,21 @@ static void ErrReport(pEVControl self)
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int EVCallBack(int iEvent, void *pEventData, void *pUserData,
|
||||
commandContext cc)
|
||||
static int EVCallBack(int iEvent, void *pEventData, void *pUserData)
|
||||
{
|
||||
char *pBuf = (char *)pEventData;
|
||||
SConnection *pCon = (SConnection *)pUserData;
|
||||
char pBueffel[132];
|
||||
|
||||
if(pCon == NULL || !SCisConnected(pCon))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(iEvent == VALUECHANGE)
|
||||
if(iEvent == VALUECHANGE && pCon != NULL)
|
||||
{
|
||||
pCon->conEventType=POSITION;
|
||||
SCWriteInContext(pCon,pBuf,eEvent,cc);
|
||||
SCWrite(pCon,pBuf,eEvent);
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
@ -1135,16 +1147,15 @@ static void ErrReport(pEVControl self)
|
||||
/* install automatic notification */
|
||||
else if(strcmp(argv[1],"interest") == 0)
|
||||
{
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),
|
||||
lID = RegisterCallback(self->pCall,
|
||||
VALUECHANGE, EVCallBack,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
SCCopyConnection(pCon), SCDeleteConnection);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
else if(strcmp(argv[1],"uninterest") == 0)
|
||||
{
|
||||
RemoveCallback2(self->pCall,pCon);
|
||||
RemoveCallbackCon(self->pCall,pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@
|
||||
int iWarned;
|
||||
int iTcl;
|
||||
int iStop;
|
||||
SCStore *conn;
|
||||
SConnection *conn;
|
||||
char *creationArgs;
|
||||
char *runScript;
|
||||
void *pPrivate;
|
||||
|
@ -52,7 +52,7 @@ $\langle$evdata {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ int iWarned;@\\
|
||||
\mbox{}\verb@ int iTcl;@\\
|
||||
\mbox{}\verb@ int iStop;@\\
|
||||
\mbox{}\verb@ SCStore *conn;@\\
|
||||
\mbox{}\verb@ SConnection *conn;@\\
|
||||
\mbox{}\verb@ char *creationArgs;@\\
|
||||
\mbox{}\verb@ char *runScript;@\\
|
||||
\mbox{}\verb@ void *pPrivate;@\\
|
||||
|
@ -47,7 +47,7 @@ used by EVControl:
|
||||
int iWarned;
|
||||
int iTcl;
|
||||
int iStop;
|
||||
SCStore *conn;
|
||||
SConnection *conn;
|
||||
char *creationArgs;
|
||||
char *runScript;
|
||||
void *pPrivate;
|
||||
|
1
exe.w
1
exe.w
@ -159,6 +159,7 @@ typedef struct __EXEMAN{
|
||||
int runList;
|
||||
pExeBuf uploadBuffer;
|
||||
int echo;
|
||||
SConnection *runCon;
|
||||
}ExeMan, *pExeMan;
|
||||
@}
|
||||
The fields:
|
||||
|
11
exebuf.c
11
exebuf.c
@ -197,7 +197,10 @@ int exeBufProcess(pExeBuf self, SicsInterp *pSics,
|
||||
cmdName[l] = '\0';
|
||||
if (FindCommand(pSics, cmdName) != NULL) {
|
||||
/* print only SICS commands */
|
||||
SCPrintf(pCon, eValue, "%s:%d>> %s",self->name,self->lineno,cmd);
|
||||
SCPrintf(pCon, eLog, "%s:%d>> %s",self->name,self->lineno,cmd);
|
||||
} else {
|
||||
/* debugging */
|
||||
/* SCPrintf(pCon, eValue, "%s:%d>> %s",self->name,self->lineno,cmd); */
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -209,11 +212,11 @@ int exeBufProcess(pExeBuf self, SicsInterp *pSics,
|
||||
Tcl Error
|
||||
*/
|
||||
if(strlen(pTcl->result) >= 2){
|
||||
SCWrite(pCon,pTcl->result,eError);
|
||||
SCPrintf(pCon,eLogError,"ERROR: Tcl reported: %s", pTcl->result);
|
||||
}
|
||||
SCWrite(pCon,"ERROR: Tcl error in block:",eError);
|
||||
SCWrite(pCon,"ERROR: Tcl error in block:",eLogError);
|
||||
SCWrite(pCon,GetCharArray(command),eError);
|
||||
SCWrite(pCon,"ERROR: end of Tcl error block",eError);
|
||||
SCWrite(pCon,"ERROR: end of Tcl error block",eLogError);
|
||||
} else {
|
||||
/*
|
||||
SICS error: has already been reported
|
||||
|
4
exebuf.h
4
exebuf.h
@ -1,5 +1,5 @@
|
||||
|
||||
#line 226 "exe.w"
|
||||
#line 227 "exe.w"
|
||||
|
||||
/**
|
||||
* Buffer handling code for the Exe Buffer batch file processing
|
||||
@ -102,7 +102,7 @@
|
||||
*/
|
||||
char *exeBufName(pExeBuf self);
|
||||
|
||||
#line 239 "exe.w"
|
||||
#line 240 "exe.w"
|
||||
|
||||
|
||||
#endif
|
||||
|
4
exebuf.i
4
exebuf.i
@ -1,5 +1,5 @@
|
||||
|
||||
#line 217 "exe.w"
|
||||
#line 218 "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 222 "exe.w"
|
||||
#line 223 "exe.w"
|
||||
|
||||
|
||||
|
104
exeman.c
104
exeman.c
@ -1,3 +1,4 @@
|
||||
|
||||
/**
|
||||
* Implementation file for the exe buffer buffer manager.
|
||||
*
|
||||
@ -225,6 +226,12 @@ static int runBatchBuffer(pExeMan self, SConnection *pCon,
|
||||
if(!SCMatchRights(pCon,usUser)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(self->runCon != NULL && self->runCon != pCon){
|
||||
SCWrite(pCon,"ERROR: another batch buffer is already runnig", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
filePath = locateBatchBuffer(self,name);
|
||||
if(filePath == NULL){
|
||||
snprintf(pBueffel,255,"ERROR: batch buffer %s not found in path",
|
||||
@ -320,9 +327,8 @@ int exeHdbNode(pHdb exeNode, SConnection *pCon){
|
||||
pExeBuf buffer = NULL;
|
||||
hdbValue v;
|
||||
int status;
|
||||
commandContext cc;
|
||||
writeFunc oldWrite;
|
||||
|
||||
SConnection *conCon = NULL;
|
||||
|
||||
/*
|
||||
* clear log buffer
|
||||
*/
|
||||
@ -337,8 +343,12 @@ int exeHdbNode(pHdb exeNode, SConnection *pCon){
|
||||
* prepare context
|
||||
*/
|
||||
name = GetHipadabaPath(log);
|
||||
cc = SCGetContext(pCon);
|
||||
strncpy(cc.deviceID, name,255);
|
||||
conCon = SCCopyConnection(pCon);
|
||||
if(conCon == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory in exehdbNode", eError);
|
||||
return 0;
|
||||
}
|
||||
strncpy(conCon->deviceID, name,255);
|
||||
strncpy(bufferNode,name,511);
|
||||
|
||||
/*
|
||||
@ -365,12 +375,9 @@ int exeHdbNode(pHdb exeNode, SConnection *pCon){
|
||||
exeBufAppend(buffer,v.v.text);
|
||||
|
||||
strncpy(bufferNode,name,511);
|
||||
oldWrite = SCGetWriteFunc(pCon);
|
||||
SCSetWriteFunc(pCon,SCHdbWrite);
|
||||
SCPushContext2(pCon,cc);
|
||||
status = exeBufProcess(buffer,pServ->pSics,pCon,NULL,0);
|
||||
SCSetWriteFunc(pCon,oldWrite);
|
||||
SCPopContext(pCon);
|
||||
SCSetWriteFunc(conCon,SCHdbWrite);
|
||||
status = exeBufProcess(buffer,pServ->pSics,conCon,NULL,0);
|
||||
SCDeleteConnection(conCon);
|
||||
exeBufDelete(buffer);
|
||||
free(name);
|
||||
if(strlen(log->value.v.text) < 2){
|
||||
@ -388,13 +395,16 @@ static int runHdbBuffer(pExeMan self, SConnection *pCon,
|
||||
pHdb node = NULL;
|
||||
hdbValue v;
|
||||
int status;
|
||||
commandContext cc;
|
||||
writeFunc oldWrite;
|
||||
|
||||
SConnection *conCon = NULL;
|
||||
|
||||
if(!SCMatchRights(pCon,usUser)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(self->runCon != NULL && self->runCon != pCon){
|
||||
SCWrite(pCon,"ERROR: another bacth buffer is still running", eError);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* clear log buffer
|
||||
*/
|
||||
@ -409,8 +419,8 @@ static int runHdbBuffer(pExeMan self, SConnection *pCon,
|
||||
/*
|
||||
* prepare context
|
||||
*/
|
||||
cc = SCGetContext(pCon);
|
||||
strcpy(cc.deviceID, pBueffel);
|
||||
conCon = SCCopyConnection(pCon);
|
||||
strcpy(conCon->deviceID, pBueffel);
|
||||
|
||||
/*
|
||||
* load commands into buffer
|
||||
@ -437,15 +447,14 @@ static int runHdbBuffer(pExeMan self, SConnection *pCon,
|
||||
exeBufAppend(buffer,v.v.text);
|
||||
|
||||
strncpy(bufferNode,name,511);
|
||||
oldWrite = SCGetWriteFunc(pCon);
|
||||
SCSetWriteFunc(pCon,SCHdbWrite);
|
||||
SCPushContext2(pCon,cc);
|
||||
SCSetWriteFunc(conCon,SCHdbWrite);
|
||||
self->exeStackPtr++;
|
||||
self->runCon = conCon;
|
||||
DynarPut(self->exeStack,self->exeStackPtr,buffer);
|
||||
status = exeBufProcess(buffer,pSics,pCon,self->pCall,self->echo);
|
||||
status = exeBufProcess(buffer,pSics,conCon,self->pCall,self->echo);
|
||||
self->exeStackPtr--;
|
||||
SCSetWriteFunc(pCon,oldWrite);
|
||||
SCPopContext(pCon);
|
||||
self->runCon = NULL;
|
||||
SCDeleteConnection(conCon);
|
||||
return status;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
@ -519,6 +528,9 @@ typedef struct {
|
||||
/*------------------------------------------------------------------*/
|
||||
static void killExeInfo(void *pData){
|
||||
pExeInfo self = (pExeInfo)pData;
|
||||
if(self->pCon != NULL){
|
||||
SCDeleteConnection(self->pCon);
|
||||
}
|
||||
if(self != NULL){
|
||||
free(self);
|
||||
}
|
||||
@ -533,32 +545,41 @@ static pExeInfo makeExeInfo(SConnection *pCon, pExeMan self){
|
||||
eError);
|
||||
return NULL;
|
||||
}
|
||||
pNew->pCon = pCon;
|
||||
memset(pNew,0,sizeof(exeInfo));
|
||||
pNew->pCon = SCCopyConnection(pCon);
|
||||
if(pNew->pCon == NULL){
|
||||
SCWrite(pCon,
|
||||
"ERROR: failed to allocate info structure for registering callbacks",
|
||||
eError);
|
||||
return NULL;
|
||||
}
|
||||
pNew->exe = self;
|
||||
return pNew;
|
||||
}
|
||||
/*------------------------------------------------------------------*/
|
||||
static int BufferCallback(int iEvent, void *pEvent, void *pUser,
|
||||
commandContext cc){
|
||||
static int BufferCallback(int iEvent, void *pEvent, void *pUser){
|
||||
pExeInfo self = (pExeInfo)pUser;
|
||||
char *name = (char *)pEvent;
|
||||
char pBueffel[132];
|
||||
|
||||
if(!SCisConnected(self->pCon)){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(iEvent == BATCHSTART){
|
||||
snprintf(pBueffel,131,"BATCHSTART=%s",name);
|
||||
SCWriteInContext(self->pCon,pBueffel,eWarning,cc);
|
||||
SCWrite(self->pCon,pBueffel,eLog);
|
||||
return 1;
|
||||
}
|
||||
if(iEvent == BATCHEND){
|
||||
snprintf(pBueffel,131,"BATCHEND=%s",name);
|
||||
SCWriteInContext(self->pCon,pBueffel,eWarning,cc);
|
||||
SCWrite(self->pCon,pBueffel,eLog);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
static int LineCallBack(int iEvent, void *pEvent, void *pUser,
|
||||
commandContext cc){
|
||||
static int LineCallBack(int iEvent, void *pEvent, void *pUser){
|
||||
pExeInfo self = (pExeInfo)pUser;
|
||||
char pBueffel[256];
|
||||
int start, end, lineno;
|
||||
@ -566,6 +587,11 @@ static int LineCallBack(int iEvent, void *pEvent, void *pUser,
|
||||
pExeBuf buf = NULL;
|
||||
|
||||
assert(self);
|
||||
|
||||
if(!SCisConnected(self->pCon)){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(iEvent == BATCHAREA){
|
||||
DynarGet(self->exe->exeStack,self->exe->exeStackPtr,&pPtr);
|
||||
buf = (pExeBuf)pPtr;
|
||||
@ -573,7 +599,7 @@ static int LineCallBack(int iEvent, void *pEvent, void *pUser,
|
||||
exeBufRange(buf,&start,&end,&lineno);
|
||||
snprintf(pBueffel,255,"%s.range = %d = %d",exeBufName(buf),
|
||||
start,end);
|
||||
SCWriteInContext(self->pCon,pBueffel,eWarning,cc);
|
||||
SCWrite(self->pCon,pBueffel,eLog);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -588,15 +614,12 @@ static void registerCallbacks(SConnection *pCon, SicsInterp *pSics,
|
||||
if(info == NULL){
|
||||
return;
|
||||
}
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),BATCHSTART, BufferCallback,
|
||||
lID = RegisterCallback(self->pCall,BATCHSTART, BufferCallback,
|
||||
info, killExeInfo);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),BATCHEND, BufferCallback,
|
||||
lID = RegisterCallback(self->pCall, BATCHEND, BufferCallback,
|
||||
info, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),BATCHAREA, LineCallBack,
|
||||
lID = RegisterCallback(self->pCall, BATCHAREA, LineCallBack,
|
||||
info, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static void unregisterCallbacks(SConnection *pCon, pExeMan self){
|
||||
@ -607,7 +630,6 @@ static void unregisterCallbacks(SConnection *pCon, pExeMan self){
|
||||
lID = SCgetCallbackID(pCon,self->pCall);
|
||||
if(lID >= 0){
|
||||
RemoveCallback(self->pCall,lID);
|
||||
SCUnregisterID(pCon,lID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1148,7 +1170,7 @@ static int execQueue(pExeMan self, SConnection *pCon, SicsInterp *pSics){
|
||||
pExeBuf buf = NULL;
|
||||
int status;
|
||||
|
||||
if(self->exeStackPtr >= 0){
|
||||
if(self->exeStackPtr >= 0 || (self->runCon != NULL && self->runCon != pCon) ){
|
||||
SCWrite(pCon,
|
||||
"ERROR: cannot start queue while batch buffers are still running",eError);
|
||||
return 0;
|
||||
@ -1157,6 +1179,7 @@ static int execQueue(pExeMan self, SConnection *pCon, SicsInterp *pSics){
|
||||
return 0;
|
||||
}
|
||||
|
||||
self->runCon = pCon;
|
||||
while(LLDnodePtr2First(self->runList) != 0){
|
||||
LLDnodeDataTo(self->runList,&buf);
|
||||
LLDnodeDelete(self->runList);
|
||||
@ -1164,6 +1187,7 @@ static int execQueue(pExeMan self, SConnection *pCon, SicsInterp *pSics){
|
||||
if(buf == NULL){
|
||||
SCWrite(pCon,
|
||||
"ERROR: serious trouble, buffer not in queue, inform programmer",eError);
|
||||
self->runCon = NULL;
|
||||
return 0;
|
||||
}
|
||||
DynarPut(self->exeStack,self->exeStackPtr,buf);
|
||||
@ -1171,9 +1195,11 @@ static int execQueue(pExeMan self, SConnection *pCon, SicsInterp *pSics){
|
||||
self->exeStackPtr--;
|
||||
if(SCGetInterrupt(pCon) >= eAbortBatch){
|
||||
SCWrite(pCon,"ERROR: queue processing interrupted",eError);
|
||||
self->runCon = NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
self->runCon = 0;
|
||||
return 1;
|
||||
}
|
||||
/*========================== interpreter action =======================*/
|
||||
@ -1280,7 +1306,7 @@ int ExeManagerWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
}else if(strcmp(argv[1],"clear") == 0){
|
||||
clearQueue(self);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
return 1;
|
||||
}else if(strcmp(argv[1],"queue") == 0){
|
||||
printQueue(self,pCon);
|
||||
SCSendOK(pCon);
|
||||
|
5
exeman.i
5
exeman.i
@ -1,5 +1,5 @@
|
||||
|
||||
#line 195 "exe.w"
|
||||
#line 196 "exe.w"
|
||||
|
||||
/*-------------------------------------------------------------------
|
||||
Internal header file for the exe manager module. Do not edit. This
|
||||
@ -18,7 +18,8 @@ typedef struct __EXEMAN{
|
||||
int runList;
|
||||
pExeBuf uploadBuffer;
|
||||
int echo;
|
||||
SConnection *runCon;
|
||||
}ExeMan, *pExeMan;
|
||||
|
||||
#line 200 "exe.w"
|
||||
#line 201 "exe.w"
|
||||
|
||||
|
@ -322,12 +322,12 @@
|
||||
if(SCGetInterrupt(pCon) == eAbortOperation)
|
||||
{
|
||||
SCSetInterrupt(pCon,eContinue);
|
||||
SCWrite(pCon,"Driving Aborted",eStatus);
|
||||
SCWrite(pCon,"Driving Aborted",eError);
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
case DEVDONE:
|
||||
SCWrite(pCon,"Driving to center done",eStatus);
|
||||
SCWrite(pCon,"Driving to center done",eValue);
|
||||
break;
|
||||
default:
|
||||
SCWrite(pCon,
|
||||
|
@ -608,11 +608,11 @@ void z1FromAllAngles(double lambda, double omega , double gamma,
|
||||
mat_free(z3);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4],
|
||||
int findAllowedBisecting(double lambda, MATRIX z1, double *fSet,
|
||||
inRange testFunc, void *userData){
|
||||
int status, i, mask[4];
|
||||
double stt, om, chi, phi, psi, ompsi, chipsi, phipsi;
|
||||
float fTest[4];
|
||||
double fTest[4];
|
||||
|
||||
status = z1mToBisecting(lambda,z1, &stt, &om, &chi, &phi);
|
||||
chi = circlify(chi);
|
||||
|
@ -187,8 +187,8 @@ int calcTheta(double lambda, MATRIX z1, double *d, double *theta);
|
||||
* in testing the range.
|
||||
* @return 0 on failure, 1 on success.
|
||||
*/
|
||||
typedef int (*inRange)(void *userData, float dSet[4], int mask[4]);
|
||||
int findAllowedBisecting(double lambda, MATRIX z1, float fSet[4],
|
||||
typedef int (*inRange)(void *userData, double dSet[4], int mask[4]);
|
||||
int findAllowedBisecting(double lambda, MATRIX z1, double fSet[4],
|
||||
inRange testFunc, void *userData);
|
||||
|
||||
#endif
|
||||
|
778
fourmess.c
Normal file
778
fourmess.c
Normal file
@ -0,0 +1,778 @@
|
||||
/**
|
||||
* This is a new version of the four circle reflection measurement module. Its task is
|
||||
* to provide functionality required for measuring a list of reflections. This is done
|
||||
* with the help of some scripts binding things together. This module provides:
|
||||
* - a table of scan parameters for measuring reflections at different angles.
|
||||
* - the functions required to produce the scan data files for single detector
|
||||
* mode.
|
||||
* - a list of reflections to measure.
|
||||
*
|
||||
* In contrast to the old mesure module, this only provides some help to
|
||||
* scripts. Thus, through scripts, a more flexible measurement is possible.
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, July 2008
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "singlex.h"
|
||||
#include "sicsobj.h"
|
||||
#include "fourtable.h"
|
||||
#include "sicshipadaba.h"
|
||||
#include "sicsvar.h"
|
||||
#include <sics.h>
|
||||
#include "scan.h"
|
||||
#include "stdscan.h"
|
||||
#include "evcontroller.h"
|
||||
#include "integrate.h"
|
||||
#include "sginfo.h"
|
||||
#include "matrix/matrix.h"
|
||||
#include "cell.h"
|
||||
#include "fourlib.h"
|
||||
|
||||
extern void SNXFormatTime(char *pBueffel, int iLen);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
FILE *profFile; /* file with reflection profiles, ccl */
|
||||
FILE *hklFile; /* file with integrated intensities */
|
||||
int stepTable; /* table with the scan parameters */
|
||||
char *currentFileRoot;
|
||||
pSICSOBJ messList;
|
||||
pHdb currentRefl; /* the current reflection being measured */
|
||||
int count;
|
||||
pScanData pScanner;
|
||||
int masterCount; /* the number of master reflection as craeted by indgen */
|
||||
}FourMess, *pFourMess;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void KillFourMess(void *data){
|
||||
pFourMess priv = (pFourMess)data;
|
||||
if(priv == NULL){
|
||||
return;
|
||||
}
|
||||
if(priv->profFile != NULL){
|
||||
fclose(priv->profFile);
|
||||
}
|
||||
if(priv->hklFile != NULL){
|
||||
fclose(priv->hklFile);
|
||||
}
|
||||
if(priv->currentFileRoot != NULL){
|
||||
free(priv->currentFileRoot);
|
||||
}
|
||||
if(priv->stepTable >= 0){
|
||||
DeleteFourCircleTable(priv->stepTable);
|
||||
}
|
||||
free(priv);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int FourMessAction(SConnection *pCon, SicsInterp *pSics,
|
||||
void *data, int argc, char *argv[]){
|
||||
pFourMess priv = NULL;
|
||||
pSICSOBJ self = (pSICSOBJ)data;
|
||||
int err, status;
|
||||
|
||||
assert(self != NULL);
|
||||
priv = self->pPrivate;
|
||||
assert(priv != NULL);
|
||||
|
||||
if(argc < 2){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to fmess",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(strcmp(argv[1],"table") == 0){
|
||||
return HandleFourCircleCommands(&priv->stepTable,pCon,
|
||||
argc,argv,&err);
|
||||
}
|
||||
|
||||
status = InvokeSICSOBJ(pCon,pSics,data,argc,argv);
|
||||
if(status < 0){
|
||||
SCPrintf(pCon,eError, "ERROR: %s no subcommand or parameter",
|
||||
argv[1]);
|
||||
return 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
static int FourMessClose(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar){
|
||||
pFourMess priv = NULL;
|
||||
|
||||
priv = self->pPrivate;
|
||||
if(priv->hklFile != NULL){
|
||||
fclose(priv->hklFile);
|
||||
priv->hklFile = NULL;
|
||||
}
|
||||
if(priv->profFile != NULL){
|
||||
fclose(priv->profFile);
|
||||
priv->profFile = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
static int FourMessStart(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar){
|
||||
pFourMess priv = NULL;
|
||||
char pFilename[512], pRoot[512];
|
||||
char pBueffel[1024];
|
||||
double lambda;
|
||||
const double *dUB;
|
||||
pSicsVariable pVar = NULL;
|
||||
char *pFile = NULL, *pPtr;
|
||||
FILE *temp = NULL;
|
||||
pHdb node;
|
||||
hdbValue v;
|
||||
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
priv = self->pPrivate;
|
||||
|
||||
if(nPar < 1){
|
||||
SCWrite(pCon,"ERROR: need file name parameter to start",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* close open files if so */
|
||||
if(priv->hklFile != NULL){
|
||||
FourMessClose(self,pCon,commandNode,par,nPar);
|
||||
}
|
||||
|
||||
/* create filename root */
|
||||
GetHipadabaPar(par[0],&v, pCon);
|
||||
pFile = strdup(v.v.text);
|
||||
pPtr = strrchr(pFile,(int)'.');
|
||||
pPtr++;
|
||||
*pPtr = '\0';
|
||||
if(priv->currentFileRoot != NULL){
|
||||
free(priv->currentFileRoot);
|
||||
}
|
||||
priv->currentFileRoot = strdup(pFile);
|
||||
free(pFile);
|
||||
strncpy(pRoot,priv->currentFileRoot,511);
|
||||
|
||||
|
||||
/* open the reflection file */
|
||||
sprintf(pBueffel,"Writing to %s.ccl, .rfl",pRoot);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
strcpy(pFilename,pRoot);
|
||||
strcat(pFilename,"ccl");
|
||||
priv->profFile = fopen(pFilename,"w");
|
||||
if(!priv->profFile){
|
||||
sprintf(pBueffel,"ERROR: SERIOUS TROUBLE: cannot open %s!",
|
||||
pFilename);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
SCSetInterrupt(pCon,eAbortBatch);
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = GetHipadabaNode(self->objectNode,"template");
|
||||
assert(node != NULL);
|
||||
GetHipadabaPar(node,&v,pCon);
|
||||
temp = fopen(v.v.text,"r");
|
||||
if(temp == NULL)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: failed to open header template",eError);
|
||||
}
|
||||
if(temp != NULL )
|
||||
{
|
||||
WriteTemplate(priv->profFile, temp, pFilename, NULL,
|
||||
pCon, pServ->pSics);
|
||||
fclose(temp);
|
||||
}
|
||||
|
||||
/* open hkl-data file */
|
||||
strcpy(pFilename,pRoot);
|
||||
strcat(pFilename,"rfl");
|
||||
priv->hklFile = fopen(pFilename,"w");
|
||||
if(!priv->hklFile){
|
||||
sprintf(pBueffel,"ERROR: SERIOUS TROUBLE: cannot open %s!",
|
||||
pFilename);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
SCSetInterrupt(pCon,eAbortBatch);
|
||||
return 0;
|
||||
}
|
||||
fputs(pFilename,priv->hklFile);
|
||||
fputs("\n",priv->hklFile);
|
||||
|
||||
/* write some header data */
|
||||
SNXFormatTime(pBueffel,1024);
|
||||
fprintf(priv->hklFile,"filetime = %s\n",pBueffel);
|
||||
lambda = SXGetLambda();
|
||||
fprintf(priv->hklFile,"lambda = %f Angstroem\n",lambda);
|
||||
dUB = SXGetUB();
|
||||
fprintf(priv->hklFile,
|
||||
"UB = %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f %7.6f\n",
|
||||
dUB[0], dUB[1],dUB[2],dUB[3],dUB[4],dUB[5],dUB[6],dUB[7],dUB[8]);
|
||||
|
||||
/* write sample & user info */
|
||||
strcpy(pBueffel,"CCL, Instr=TRICS, ");
|
||||
pVar = FindVariable(pServ->pSics,"sample");
|
||||
if(pVar){
|
||||
fprintf(priv->hklFile,"sample = %s\n",pVar->text);
|
||||
}
|
||||
pVar = FindVariable(pServ->pSics,"user");
|
||||
if(pVar){
|
||||
fprintf(priv->hklFile,"user = %s \n",pVar->text);
|
||||
}
|
||||
priv->count = 0;
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int FourMessScanPar(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar){
|
||||
pFourMess priv = self->pPrivate;
|
||||
char *scanvar;
|
||||
double stt, dVal;
|
||||
int np, preset;
|
||||
pDynString data;
|
||||
|
||||
assert(priv != NULL);
|
||||
if(nPar < 1){
|
||||
SCWrite(pCon,"ERROR: need two theta parameter to scanpar", eError);
|
||||
return 0;
|
||||
}
|
||||
stt = par[0]->value.v.doubleValue;
|
||||
|
||||
scanvar = GetFourCircleScanVar(priv->stepTable,stt);
|
||||
dVal = GetFourCircleStep(priv->stepTable,stt);
|
||||
np = GetFourCircleScanNP(priv->stepTable,stt);
|
||||
preset = GetFourCirclePreset(priv->stepTable,stt);
|
||||
if(strcmp(scanvar,"NOT FOUND") == 0){
|
||||
SCPrintf(pCon,eValue,"%s,%f,%d,%d","om", dVal,np,preset);
|
||||
} else {
|
||||
SCPrintf(pCon,eValue,"%s,%f,%d,%d",scanvar,dVal,np,preset);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static hdbCallbackReturn SetScannerCB(pHdb node, void *userData,
|
||||
pHdbMessage mm){
|
||||
pHdbDataMessage set = NULL;
|
||||
pFourMess priv = (pFourMess)userData;
|
||||
SConnection *pCon = NULL;
|
||||
pScanData old;
|
||||
|
||||
if((set = GetHdbSetMessage(mm)) != NULL){
|
||||
old = priv->pScanner;
|
||||
priv->pScanner = FindCommandData(pServ->pSics,set->v->v.text,"ScanObject");
|
||||
if(priv->pScanner == NULL){
|
||||
priv->pScanner = old;
|
||||
pCon = set->callData;
|
||||
if(pCon != NULL){
|
||||
SCWrite(pCon,"ERROR: scan object not found", eError);
|
||||
}
|
||||
return hdbAbort;
|
||||
}
|
||||
}
|
||||
return hdbContinue;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static double getProtonAverage(pFourMess self){
|
||||
int np, i;
|
||||
long *lData = NULL, lSum = 0;
|
||||
|
||||
np = GetScanNP(self->pScanner);
|
||||
lData = (long *)malloc((np+1)*sizeof(long));
|
||||
if(lData == NULL || np == 0){
|
||||
return 0.;
|
||||
}
|
||||
memset(lData,0,(np+1)*sizeof(long));
|
||||
GetScanMonitor(self->pScanner,2,lData, np);
|
||||
for(i = 0; i < np; i++){
|
||||
lSum += lData[i];
|
||||
}
|
||||
free(lData);
|
||||
return (double)lSum/(double)np;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int FourMessStoreIntern(pSICSOBJ self, SConnection *pCon,
|
||||
double fHkl[3], double fPosition[4]){
|
||||
pFourMess priv = self->pPrivate;
|
||||
float fSum, fSigma, fTemp, fStep, fPreset;
|
||||
int i, iLF, iRet, iNP,ii;
|
||||
long *lCounts = NULL;
|
||||
pEVControl pEva = NULL;
|
||||
pDummy pPtr = NULL;
|
||||
pIDrivable pDriv = NULL;
|
||||
char pBueffel[512], pTime[512], pNum[10];
|
||||
double prot;
|
||||
|
||||
if(priv->pScanner == NULL){
|
||||
SCWrite(pCon,"ERROR: store: scan not configured", eLogError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(priv->hklFile == NULL){
|
||||
SCWrite(pCon,"ERROR: store: no files open", eLogError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* get necessary data */
|
||||
fSum = 0.;
|
||||
fSigma = 0.;
|
||||
iRet = ScanIntegrate(priv->pScanner,&fSum, &fSigma);
|
||||
if(iRet != 1){
|
||||
switch(iRet){
|
||||
case INTEGLEFT:
|
||||
sprintf(pBueffel,
|
||||
"WARNING: integration failed --> no left side to: %f %f %f",
|
||||
fHkl[0], fHkl[1],fHkl[2]);
|
||||
break;
|
||||
case INTEGRIGHT:
|
||||
sprintf(pBueffel,
|
||||
"WARNING: integration failed -->no right side to: %f %f %f",
|
||||
fHkl[0], fHkl[1],fHkl[2]);
|
||||
break;
|
||||
case INTEGNOPEAK:
|
||||
sprintf(pBueffel,
|
||||
"WARNING: integration failed -->no peak found: %f %f %f",
|
||||
fHkl[0], fHkl[1],fHkl[2]);
|
||||
break;
|
||||
case INTEGFUNNYBACK:
|
||||
sprintf(pBueffel,
|
||||
"WARNING: integration problem, asymmetric background: %f %f %f",
|
||||
fHkl[0], fHkl[1],fHkl[2]);
|
||||
break;
|
||||
}
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
}
|
||||
iNP = GetScanNP(priv->pScanner);
|
||||
lCounts = malloc(iNP*sizeof(long));
|
||||
if(lCounts == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory in store", eLogError);
|
||||
return 0;
|
||||
}
|
||||
GetScanCounts(priv->pScanner,lCounts,iNP);
|
||||
|
||||
/* write it */
|
||||
if(priv->profFile){
|
||||
fprintf(priv->profFile,"%4d %7.3f %7.3f %7.3f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n",
|
||||
priv->count, fHkl[0],fHkl[1],fHkl[2],
|
||||
fPosition[0], fPosition[1],
|
||||
fPosition[2], fPosition[3],
|
||||
fSum,fSigma);
|
||||
}
|
||||
if(priv->hklFile){
|
||||
fprintf(priv->hklFile,"%5d %6.2f %6.2f %6.2f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n",
|
||||
priv->count, fHkl[0],fHkl[1],fHkl[2],
|
||||
fPosition[0], fPosition[1],
|
||||
fPosition[2],fPosition[3],
|
||||
fSum,fSigma);
|
||||
}
|
||||
sprintf(pBueffel,"%5d %6.2f %6.2f %6.2f %7.2f %7.2f %7.2f %7.2f %7.0f %7.2f\n",
|
||||
priv->count, fHkl[0],fHkl[1],fHkl[2],
|
||||
fPosition[0], fPosition[1],
|
||||
fPosition[2], fPosition[3],
|
||||
fSum,fSigma);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
|
||||
/* get temperature */
|
||||
fTemp = -777.77;
|
||||
pEva = (pEVControl)FindCommandData(pServ->pSics,"temperature",
|
||||
"Environment Controller");
|
||||
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);
|
||||
}
|
||||
|
||||
/* write profile */
|
||||
if(priv->profFile){
|
||||
/* collect data */
|
||||
SNXFormatTime(pBueffel,512);
|
||||
GetScanVarStep(priv->pScanner,0,&fStep);
|
||||
fPreset = GetScanPreset(priv->pScanner);
|
||||
prot = getProtonAverage(priv);
|
||||
fprintf(priv->profFile,"%3d %7.4f %9.0f %7.3f %12f %s\n",iNP,fStep,
|
||||
fPreset,fTemp,prot, pBueffel);
|
||||
for(i = 0; i < iNP; i++){
|
||||
for(ii = 0; ii < 10 && i < iNP; ii++){
|
||||
fprintf(priv->profFile," %7ld",lCounts[i]);
|
||||
iLF = 1;
|
||||
i++;
|
||||
}
|
||||
fprintf(priv->profFile,"\n");
|
||||
i--;
|
||||
iLF = 0;
|
||||
}
|
||||
if(iLF){
|
||||
fprintf(priv->profFile,"\n");
|
||||
}
|
||||
fflush(priv->profFile);
|
||||
}
|
||||
|
||||
strcpy(pTime,pBueffel);
|
||||
sprintf(pBueffel,"%3d%8.4f%10.0f%8.3f %s\n",iNP,fStep,
|
||||
fPreset,fTemp,pTime);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
pBueffel[0] = '\0';
|
||||
for(i = 0; i < iNP; i++){
|
||||
for(ii = 0; ii < 10 && i < iNP; ii++){
|
||||
sprintf(pNum," %6ld",lCounts[i]);
|
||||
strcat(pBueffel,pNum);
|
||||
iLF = 1;
|
||||
i++;
|
||||
}
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
pBueffel[0] = '\0';
|
||||
i--;
|
||||
iLF = 0;
|
||||
}
|
||||
if(iLF){
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
}
|
||||
free(lCounts);
|
||||
return 1;
|
||||
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int FourMessStore(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar){
|
||||
double fHkl[3], fPosition[4];
|
||||
int i;
|
||||
|
||||
if(nPar < 7) {
|
||||
SCWrite(pCon,"ERROR: not enough arguments for store",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* load hkl */
|
||||
for(i = 0; i < 3; i++){
|
||||
fHkl[i] = par[i]->value.v.doubleValue;
|
||||
}
|
||||
|
||||
/* load positions */
|
||||
for(i = 0; i < 4; i++){
|
||||
fPosition[i] = par[i+3]->value.v.doubleValue;
|
||||
}
|
||||
|
||||
return FourMessStoreIntern(self, pCon,fHkl, fPosition);
|
||||
}
|
||||
/*------------------------------------------------------------------*/
|
||||
static int weakScan(pSICSOBJ self, SConnection *pCon){
|
||||
int i, np;
|
||||
long low = 99999, high = -99999, *lCounts = NULL;
|
||||
pFourMess priv = self->pPrivate;
|
||||
hdbValue v;
|
||||
|
||||
/*
|
||||
the scan is always OK if we do not test for weak conditions or we are in psd mode
|
||||
*/
|
||||
SICSHdbGetPar(self,pCon,"weak",&v);
|
||||
if(v.v.intValue == 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
np = GetScanNP(priv->pScanner);
|
||||
lCounts = malloc(np*sizeof(long));
|
||||
if(lCounts == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory in weakScan test", eLogError);
|
||||
return 0;
|
||||
}
|
||||
GetScanCounts(priv->pScanner,lCounts,np);
|
||||
for(i = 0; i < np; i++){
|
||||
if(lCounts[i] < low){
|
||||
low = lCounts[i];
|
||||
}
|
||||
if(lCounts[i] > high){
|
||||
high = lCounts[i];
|
||||
}
|
||||
}
|
||||
/*
|
||||
I am using the weakest point here as a rough estimate of
|
||||
the background
|
||||
*/
|
||||
SICSHdbGetPar(self,pCon,"weakthreshold",&v);
|
||||
if(high - 2 * low > v.v.intValue){
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int FourMessWeak(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar){
|
||||
int weak;
|
||||
|
||||
weak = weakScan(self,pCon);
|
||||
SCPrintf(pCon,eLog,"weak = %d", weak);
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int GenIndex(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar){
|
||||
double lambda = SXGetLambda(), d, om, hkl[3];
|
||||
int h, k, l, minh, mink, minl, suppress;
|
||||
hdbValue hkllim, sttlim;
|
||||
T_SgInfo *sginfo = SXGetSpaceGroup();
|
||||
pFourMess priv = self->pPrivate;
|
||||
int count = 0;
|
||||
MATRIX B, H, Z1;
|
||||
const double *cell;
|
||||
lattice direct;
|
||||
|
||||
if(nPar < 1) {
|
||||
SCWrite(pCon,"ERROR: need a suppression flag for indgen",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
SICSHdbGetPar(self,pCon,"hkllim",&hkllim);
|
||||
SICSHdbGetPar(self,pCon,"sttlim",&sttlim);
|
||||
suppress = par[0]->value.v.intValue;
|
||||
|
||||
minh = hkllim.v.intArray[3];
|
||||
mink = hkllim.v.intArray[4];
|
||||
minl = hkllim.v.intArray[5];
|
||||
|
||||
SetListMin_hkl(sginfo,hkllim.v.intArray[1], hkllim.v.intArray[2],
|
||||
&minh, &mink, &minl);
|
||||
ClearReflectionList(priv->messList);
|
||||
cell = SXGetCell();
|
||||
direct.a = cell[0];
|
||||
direct.b = cell[1];
|
||||
direct.c = cell[2];
|
||||
direct.alpha = cell[3];
|
||||
direct.beta = cell[4];
|
||||
direct.gamma = cell[5];
|
||||
B = mat_creat(3,3,UNIT_MATRIX);
|
||||
if(!calculateBMatrix(direct,B)){
|
||||
SCWrite(pCon,"ERROR: invalid cell", eError);
|
||||
return 0;
|
||||
}
|
||||
H = mat_creat(3,1,ZERO_MATRIX);
|
||||
|
||||
|
||||
for(h = hkllim.v.intArray[0]; h < hkllim.v.intArray[3]; h++){
|
||||
for(k = hkllim.v.intArray[1]; k < hkllim.v.intArray[4]; k++){
|
||||
for(l = hkllim.v.intArray[2]; l < hkllim.v.intArray[5]; l++){
|
||||
/* first test: extinct */
|
||||
if(IsSysAbsent_hkl(sginfo,h,k,l,NULL) != 0 ){
|
||||
continue;
|
||||
}
|
||||
/* second test: a symmetrically equivalent already seen */
|
||||
if((suppress != 0) && IsSuppressed_hkl(sginfo,minh,mink,minl,
|
||||
hkllim.v.intArray[1],hkllim.v.intArray[2],h,k,l ) != 0){
|
||||
continue;
|
||||
}
|
||||
/* third test: within stt limits */
|
||||
H[0][0] = (double)h;
|
||||
H[1][0] = (double)k;
|
||||
H[2][0] = (double)l;
|
||||
Z1 = mat_mul(B,H);
|
||||
calcTheta(lambda,Z1,&d,&om);
|
||||
om *= 2.;
|
||||
mat_free(Z1);
|
||||
if(om > sttlim.v.floatArray[0] && om < sttlim.v.floatArray[1]){
|
||||
hkl[0] = (double)h;
|
||||
hkl[1] = (double)k;
|
||||
hkl[2] = (double)l;
|
||||
AddRefIdx(priv->messList,hkl);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mat_free(B);
|
||||
mat_free(H);
|
||||
priv->masterCount = count;
|
||||
SCPrintf(pCon,eValue,"%d reflections generated", count);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
static int GenInconsumerate(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar){
|
||||
double hkl[3], qvec[3];
|
||||
pFourMess priv = self->pPrivate;
|
||||
int i, j;
|
||||
|
||||
if(nPar < 3) {
|
||||
SCWrite(pCon,
|
||||
"ERROR: need q displacement vector with three compononts",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
qvec[0] = par[0]->value.v.doubleValue;
|
||||
qvec[1] = par[1]->value.v.doubleValue;
|
||||
qvec[2] = par[2]->value.v.doubleValue;
|
||||
|
||||
for(i = 0; i < priv->masterCount; i++){
|
||||
GetRefIndex(priv->messList,i,hkl);
|
||||
for(j = 0; j < 3; j++){
|
||||
hkl[j] += qvec[j];
|
||||
}
|
||||
AddRefIdx(priv->messList, hkl);
|
||||
}
|
||||
SCPrintf(pCon,eValue,"%d additional inconsumerate reflections generated",
|
||||
priv->masterCount);
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int hklCompare(const void *h1, const void *h2){
|
||||
const double *hkl1 = h1, *hkl2 = h2;
|
||||
|
||||
if(hkl1[3] < hkl2[3]){
|
||||
return -1;
|
||||
} else if (hkl1[3] == hkl2[3]) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int SortRef(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar){
|
||||
double *sortlist, d, lambda, om, hkl[4], ang[4];
|
||||
const double *cell;
|
||||
int nRefl, i, j;
|
||||
MATRIX B, H, Z1;
|
||||
lattice direct;
|
||||
pFourMess priv = self->pPrivate;
|
||||
|
||||
lambda = SXGetLambda();
|
||||
cell = SXGetCell();
|
||||
direct.a = cell[0];
|
||||
direct.b = cell[1];
|
||||
direct.c = cell[2];
|
||||
direct.alpha = cell[3];
|
||||
direct.beta = cell[4];
|
||||
direct.gamma = cell[5];
|
||||
B = mat_creat(3,3,UNIT_MATRIX);
|
||||
if(!calculateBMatrix(direct,B)){
|
||||
SCWrite(pCon,"ERROR: invalid cell", eError);
|
||||
return 0;
|
||||
}
|
||||
H = mat_creat(3,1,ZERO_MATRIX);
|
||||
|
||||
nRefl = ReflectionListCount(priv->messList);
|
||||
sortlist = malloc(nRefl*4*sizeof(double));
|
||||
if(sortlist == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory in SortRef",eError);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* I am using hkl[3] for storing the theta value to sort for! */
|
||||
for(i = 0; i < nRefl; i++){
|
||||
GetRefIndex(priv->messList,i,hkl);
|
||||
for(j = 0; j < 3; j++){
|
||||
H[j][0] = hkl[j];
|
||||
}
|
||||
Z1 = mat_mul(B,H);
|
||||
calcTheta(lambda,Z1,&d, &om);
|
||||
mat_free(Z1);
|
||||
hkl[3] = om;
|
||||
memcpy(sortlist + i*4, hkl, 4*sizeof(double));
|
||||
}
|
||||
|
||||
qsort(sortlist,nRefl,4*sizeof(double),hklCompare);
|
||||
|
||||
ClearReflectionList(priv->messList);
|
||||
for(i = 0; i < nRefl; i++){
|
||||
ang[1] = sortlist[i*4+3];
|
||||
ang[0] = 2.*ang[1];
|
||||
ang[2] = .0;
|
||||
ang[3] = .0;
|
||||
/* AddRefIdxAng(priv->messList, sortlist+i*4,ang); */
|
||||
AddRefIdx(priv->messList, sortlist+i*4);
|
||||
}
|
||||
free(sortlist);
|
||||
mat_free(B);
|
||||
mat_free(H);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
static int FourMessSave(void *data, char *name, FILE *fd){
|
||||
pSICSOBJ self = data;
|
||||
pFourMess priv = self->pPrivate;
|
||||
|
||||
SaveSICSOBJ(data,name,fd);
|
||||
SaveFourCircleTable(priv->stepTable, name, fd);
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void InstallFourMess(SConnection *pCon, SicsInterp *pSics){
|
||||
pFourMess priv = NULL;
|
||||
pSICSOBJ pNew = NULL;
|
||||
pHdb cmd = NULL;
|
||||
int hkl[] = {-10,-10,10,10,10,10};
|
||||
double sttlim[] = {5.0, 180};
|
||||
|
||||
pNew = MakeSICSOBJ("fmess","FourMess");
|
||||
priv = calloc(1,sizeof(FourMess));
|
||||
if(pNew == NULL || priv == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating fourmess", eError);
|
||||
}
|
||||
pNew->pDes->SaveStatus = FourMessSave;
|
||||
pNew->pPrivate = priv;
|
||||
pNew->KillPrivate = KillFourMess;
|
||||
|
||||
priv->stepTable = MakeFourCircleTable();
|
||||
priv->messList = CreateReflectionList(pCon,pSics,"messref");
|
||||
if(priv->stepTable < 0 || priv->messList == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating fourmess", eError);
|
||||
}
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"weak", usUser, MakeHdbInt(0));
|
||||
SetHdbProperty(cmd,"__save","true");
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"weakthreshold", usUser,
|
||||
MakeHdbInt(20));
|
||||
SetHdbProperty(cmd,"__save","true");
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"mode", usUser, MakeHdbText("Monitor"));
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"hkllim", usUser, MakeHdbIntArray(6,hkl));
|
||||
SetHdbProperty(cmd,"__save","true");
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"sttlim", usUser, MakeHdbFloatArray(2,sttlim));
|
||||
SetHdbProperty(cmd,"__save","true");
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"start", usUser, MakeSICSFunc(FourMessStart));
|
||||
cmd = AddSICSHdbPar(cmd,"filename", usUser, MakeHdbText("Unknown"));
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"close", usUser, MakeSICSFunc(FourMessClose));
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"scanpar", usUser, MakeSICSFunc(FourMessScanPar));
|
||||
cmd = AddSICSHdbPar(cmd,"twotheta", usUser, MakeHdbFloat(.0));
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"store", usUser, MakeSICSFunc(FourMessStore));
|
||||
AddSICSHdbPar(cmd,"h", usUser, MakeHdbFloat(.0));
|
||||
AddSICSHdbPar(cmd,"k", usUser, MakeHdbFloat(.0));
|
||||
AddSICSHdbPar(cmd,"l", usUser, MakeHdbFloat(.0));
|
||||
AddSICSHdbPar(cmd,"stt", usUser, MakeHdbFloat(.0));
|
||||
AddSICSHdbPar(cmd,"om", usUser, MakeHdbFloat(.0));
|
||||
AddSICSHdbPar(cmd,"chi", usUser, MakeHdbFloat(.0));
|
||||
AddSICSHdbPar(cmd,"phi", usUser, MakeHdbFloat(.0));
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"weak", usUser, MakeSICSFunc(FourMessWeak));
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"indgen", usUser, MakeSICSFunc(GenIndex));
|
||||
AddSICSHdbPar(cmd,"sup", usUser, MakeHdbInt(1));
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"genw", usUser, MakeSICSFunc(GenInconsumerate));
|
||||
AddSICSHdbPar(cmd,"hw", usUser, MakeHdbFloat(.0));
|
||||
AddSICSHdbPar(cmd,"kw", usUser, MakeHdbFloat(.0));
|
||||
AddSICSHdbPar(cmd,"lw", usUser, MakeHdbFloat(.0));
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"indsort", usUser, MakeSICSFunc(SortRef));
|
||||
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"template", usMugger, MakeHdbText("Unknown"));
|
||||
cmd = AddSICSHdbPar(pNew->objectNode,"scanobj", usMugger, MakeHdbText("xxxscan"));
|
||||
PrependHipadabaCallback(cmd,
|
||||
MakeHipadabaCallback(SetScannerCB, priv,NULL));
|
||||
|
||||
priv->pScanner = FindCommandData(pSics,"xxxscan","ScanObject");
|
||||
|
||||
AddCommand(pSics,
|
||||
"fmess",
|
||||
FourMessAction,
|
||||
KillSICSOBJ,
|
||||
pNew);
|
||||
}
|
||||
|
25
fourmess.h
Normal file
25
fourmess.h
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* This is a new version of the four circle reflection measurement module. Its task is
|
||||
* to provide functionality required for measuring a list of reflections. This is done
|
||||
* with the help of some scripts bind things together. This module provides:
|
||||
* - a table of scan parameters for measuring reflections at different angles.
|
||||
* - the functions required to produce the scan data files for single detector
|
||||
* mode.
|
||||
* - a list of reflections to measure.
|
||||
*
|
||||
* In contrast to the old mesure module, this module is more flexible and
|
||||
* allows for reflection list processing in all modes and for all detectors.
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, July 2008
|
||||
*/
|
||||
|
||||
#ifndef _FOURMESS
|
||||
#define _FOURMESS
|
||||
#include <sics.h>
|
||||
|
||||
void InstallFourMess(SConnection *pCon, SicsInterp *pSics);
|
||||
|
||||
#endif
|
||||
|
@ -125,7 +125,7 @@ static int addToList(int handle, SConnection *pCon, int argc, char *argv[]){
|
||||
}
|
||||
strncpy(entry.scanVar,argv[4],29);
|
||||
strtolower(entry.scanVar);
|
||||
if(strcmp(entry.scanVar,"om") != 0 && strcmp(entry.scanVar,"o2t") != 0){
|
||||
if(strcmp(entry.scanVar,"om") != 0 && strstr(entry.scanVar,"o2t") == NULL){
|
||||
SCWrite(pCon,"ERROR: Invalied scan variable specified, only om, o2t allowed",eError);
|
||||
return 0;
|
||||
}
|
||||
|
@ -236,7 +236,6 @@ static int MakeGenPar(pSICSOBJ self, SConnection *pCon,
|
||||
pGenController priv;
|
||||
pAsyncUnit assi;
|
||||
pAsyncTxn trans;
|
||||
commandContext comCon;
|
||||
char replyCommand[2048];
|
||||
} GenContext, *pGenContext;
|
||||
/*--------------------------------------------------------------------------
|
||||
@ -266,14 +265,11 @@ static int MakeGenPar(pSICSOBJ self, SConnection *pCon,
|
||||
break;
|
||||
}
|
||||
|
||||
if(genCon->pCon != NULL){
|
||||
SCPushContext2(genCon->pCon, genCon->comCon);
|
||||
}
|
||||
genCon->priv->replyCallback(genCon->obj, genCon->pCon,
|
||||
genCon->node, genCon->replyCommand, reply, strlen(reply));
|
||||
if(genCon->pCon != NULL){
|
||||
SCPopContext(genCon->pCon);
|
||||
}
|
||||
SCDeleteConnection(genCon->pCon);
|
||||
}
|
||||
free(genCon);
|
||||
|
||||
return 1;
|
||||
@ -362,9 +358,8 @@ static pGenContext PrepareToEnque(pSICSOBJ self, SConnection *pCon, pHdb node){
|
||||
result->node = node;
|
||||
result->priv = priv;
|
||||
result->obj = self;
|
||||
result->pCon = pCon;
|
||||
result->pCon = SCCopyConnection(pCon);
|
||||
priv->comError = GCOK;
|
||||
result->comCon = SCGetContext(pCon);
|
||||
free(command);
|
||||
|
||||
return result;
|
||||
|
97
histmem.c
97
histmem.c
@ -167,6 +167,10 @@ extern pHistDriver MakeHMSlaveHM(pStringDict pOpt);
|
||||
self = (pHistMem)pData;
|
||||
assert(self);
|
||||
|
||||
if(!GetCountLock(self->pCountInt, pCon)){
|
||||
return HWFault;
|
||||
}
|
||||
|
||||
if(!self->iInit)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
|
||||
@ -195,6 +199,7 @@ extern pHistDriver MakeHMSlaveHM(pStringDict pOpt);
|
||||
SCWrite(pCon,"ERROR: failed to fix histogram memory problem",
|
||||
eError);
|
||||
SCSetInterrupt(pCon,eAbortBatch);
|
||||
ReleaseCountLock(self->pCountInt);
|
||||
return HWFault;
|
||||
}
|
||||
}
|
||||
@ -321,6 +326,7 @@ extern pHistDriver MakeHMSlaveHM(pStringDict pOpt);
|
||||
SCWrite(pCon,"ERROR: failed to fix histogram memory problem",eError);
|
||||
SCSetInterrupt(pCon,eAbortBatch);
|
||||
InvokeCallBack(self->pCall,COUNTEND,NULL);
|
||||
ReleaseCountLock(self->pCountInt);
|
||||
return eCt;
|
||||
}
|
||||
else
|
||||
@ -339,6 +345,7 @@ extern pHistDriver MakeHMSlaveHM(pStringDict pOpt);
|
||||
*/
|
||||
updateHMData(self->pDriv->data);
|
||||
InvokeCallBack(self->pCall,COUNTEND,NULL);
|
||||
ReleaseCountLock(self->pCountInt);
|
||||
}
|
||||
|
||||
return eCt;
|
||||
@ -595,6 +602,11 @@ extern pHistDriver MakeHMSlaveHM(pStringDict pOpt);
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
if(isRunning(self->pCountInt)){
|
||||
SCWrite(pCon,"ERROR: cannot configure histogram memory while counting", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iRet = HistDriverConfig(self->pDriv,self->pDriv->pOption,pCon);
|
||||
if(!iRet)
|
||||
{
|
||||
@ -766,16 +778,16 @@ void HistDirty(pHistMem self)
|
||||
iRet = Wait4Success(GetExecutor());
|
||||
if(iRet == DEVINT)
|
||||
{
|
||||
SCWrite(pCon,"Counting aborted due to Interrupt",eStatus);
|
||||
SCWrite(pCon,"Counting aborted due to Interrupt",eError);
|
||||
}
|
||||
else if(iRet == DEVERROR)
|
||||
{
|
||||
SCWrite(pCon,"Counting finished with Problems",eStatus);
|
||||
SCWrite(pCon,"Counting finished with Problems",eValue);
|
||||
iRet = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
SCWrite(pCon,"Counting finished",eStatus);
|
||||
SCWrite(pCon,"Counting finished",eValue);
|
||||
iRet = 1;
|
||||
}
|
||||
|
||||
@ -791,7 +803,7 @@ void HistDirty(pHistMem self)
|
||||
char pBueffel[512], pError[80];
|
||||
|
||||
assert(self);
|
||||
|
||||
|
||||
if(!self->iInit)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: histogram memory not initialised",eError);
|
||||
@ -934,24 +946,29 @@ void HistDirty(pHistMem self)
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int HMCountInterest(int iEvent, void *pEvent, void *pUser,
|
||||
commandContext cc)
|
||||
static int HMCountInterest(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
SConnection *pCon = NULL;
|
||||
char pBueffel[512];
|
||||
|
||||
if(iEvent == COUNTSTART)
|
||||
pCon = (SConnection *)pUser;
|
||||
|
||||
if(pCon == NULL || !SCisConnected(pCon))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(iEvent == COUNTSTART && pUser != NULL)
|
||||
{
|
||||
pCon = (SConnection *)pUser;
|
||||
assert(pCon);
|
||||
SCWriteInContext(pCon,"HMCOUNTSTART",eWarning,cc);
|
||||
SCWrite(pCon,"HMCOUNTSTART",eWarning);
|
||||
return 1;
|
||||
}
|
||||
else if(iEvent == COUNTEND)
|
||||
{
|
||||
pCon = (SConnection *)pUser;
|
||||
assert(pCon);
|
||||
SCWriteInContext(pCon,"HMCOUNTEND",eWarning,cc);
|
||||
SCWrite(pCon,"HMCOUNTEND",eWarning);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -982,11 +999,13 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
int i,iRet,iLen,iRank,iDiscard,tofMode;
|
||||
float fVal;
|
||||
char *pMode[] = {"timer","monitor",NULL};
|
||||
pDynString buf = NULL;
|
||||
|
||||
memset(pBuffer, 0, sizeof(pBuffer));
|
||||
memset(pValue, 0, sizeof(pValue));
|
||||
memset(name, 0, sizeof(name));
|
||||
|
||||
|
||||
SCStartBuffering(pCon);
|
||||
iRet = StringDictGet(self->pDriv->pOption,"name",name,19);
|
||||
if(0==iRet) {
|
||||
strcpy(name,"*");
|
||||
@ -994,7 +1013,7 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
iRet = StringDictGet(self->pDriv->pOption,"driver",pValue,sizeof(pValue)-1);
|
||||
if(0<iRet) {
|
||||
sprintf(pBuffer,"%s.driver = %s",name,pValue);
|
||||
SCWrite(pCon,pBuffer,eStatus);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
}
|
||||
|
||||
iRet = StringDictGetAsNumber(self->pDriv->pOption,"update",&fVal);
|
||||
@ -1003,13 +1022,13 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
} else {
|
||||
sprintf(pBuffer,"%s.update = 0 (no buffering)",name);
|
||||
}
|
||||
SCWrite(pCon,pBuffer,eStatus);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
|
||||
iRet = StringDictGetAsNumber(self->pDriv->pOption,"rank",&fVal);
|
||||
if(0<iRet) {
|
||||
iRank = (int)rint(fVal);
|
||||
sprintf(pBuffer,"%s.rank = %d",name,iRank);
|
||||
SCWrite(pCon,pBuffer,eStatus);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
} else {
|
||||
iRank = 0;
|
||||
}
|
||||
@ -1018,7 +1037,7 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
iRet = StringDictGetAsNumber(self->pDriv->pOption,pValue,&fVal);
|
||||
if(0<iRet){
|
||||
sprintf(pBuffer,"%s.dim%1.1d = %d",name,i,(int)rint(fVal));
|
||||
SCWrite(pCon,pBuffer,eStatus);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1032,18 +1051,18 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
if(NULL!=strstr(pKey,"dim")) iDiscard=1;
|
||||
if(0==iDiscard) {
|
||||
snprintf(pBuffer,511,"%s.%s = %s",name,pKey,pValue);
|
||||
SCWrite(pCon,pBuffer,eStatus);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
}
|
||||
pKey = StringDictGetNext(self->pDriv->pOption,pValue,sizeof(pValue)-1);
|
||||
}
|
||||
|
||||
/* Display Count Mode */
|
||||
sprintf(pBuffer,"%s.CountMode = %s",name,pMode[self->pDriv->eCount]);
|
||||
SCWrite(pCon,pBuffer,eStatus);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
|
||||
/* Display Preset */
|
||||
sprintf(pBuffer,"%s.preset = %f",name,self->pDriv->fCountPreset);
|
||||
SCWrite(pCon,pBuffer,eStatus);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
|
||||
if(self->pDriv->data->nTimeChan > 2) {
|
||||
tofMode = 1;
|
||||
@ -1051,7 +1070,11 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
tofMode = 0;
|
||||
}
|
||||
sprintf(pBuffer,"%s.tofMode = %d",name,tofMode);
|
||||
SCWrite(pCon,pBuffer,eStatus);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
buf = SCEndBuffering(pCon);
|
||||
if(buf != NULL){
|
||||
SCWrite(pCon,GetCharArray(buf), eValue);
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
@ -1098,14 +1121,12 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"interest") == 0)
|
||||
{
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),
|
||||
lID = RegisterCallback(self->pCall,
|
||||
COUNTSTART, HMCountInterest,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),
|
||||
SCCopyConnection(pCon), SCDeleteConnection);
|
||||
lID = RegisterCallback(self->pCall,
|
||||
COUNTEND, HMCountInterest,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
SCCopyConnection(pCon), SCDeleteConnection);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
@ -1178,6 +1199,10 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
}
|
||||
else /* set case */
|
||||
{
|
||||
if(isRunning(self->pCountInt)){
|
||||
SCWrite(pCon,"ERROR: cannot change preset while counting", eError);
|
||||
return 0;
|
||||
}
|
||||
fVal = atof(argv[2]);
|
||||
if(!SCMatchRights(pCon,self->iAccess))
|
||||
{
|
||||
@ -1221,6 +1246,10 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
else /* set case */
|
||||
{
|
||||
strtolower(argv[2]);
|
||||
if(isRunning(self->pCountInt)){
|
||||
SCWrite(pCon,"ERROR: cannot change countmode while counting", eError);
|
||||
return 0;
|
||||
}
|
||||
if(!SCMatchRights(pCon,self->iAccess))
|
||||
{
|
||||
return 0;
|
||||
@ -1638,16 +1667,14 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
/* generate time binning */
|
||||
else if(strcmp(argv[1],"genbin") == 0)
|
||||
{
|
||||
if(isRunning(self->pCountInt)){
|
||||
SCWrite(pCon,"ERROR: cannot change time binning while counting", eError);
|
||||
return 0;
|
||||
}
|
||||
if(!SCMatchRights(pCon,usMugger))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if(GetStatus() == eCounting)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: cannot modify timebinning while counting",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
if(argc < 5)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: not enough aguments to genbin",eError);
|
||||
@ -1695,6 +1722,10 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
/* set a time bin */
|
||||
else if(strcmp(argv[1],"setbin") == 0)
|
||||
{
|
||||
if(isRunning(self->pCountInt)){
|
||||
SCWrite(pCon,"ERROR: cannot change time binning while counting", eError);
|
||||
return 0;
|
||||
}
|
||||
if(!SCMatchRights(pCon,usMugger))
|
||||
{
|
||||
return 0;
|
||||
@ -1732,6 +1763,10 @@ static int checkHMEnd(pHistMem self, char *text){
|
||||
/* clear time bin info */
|
||||
else if(strcmp(argv[1],"clearbin") == 0)
|
||||
{
|
||||
if(isRunning(self->pCountInt)){
|
||||
SCWrite(pCon,"ERROR: cannot change time binning while counting", eError);
|
||||
return 0;
|
||||
}
|
||||
clearTimeBinning(self->pDriv->data);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
|
8
hkl.h
8
hkl.h
@ -19,15 +19,12 @@
|
||||
|
||||
typedef struct __HKL *pHKL;
|
||||
/*-------------------------------------------------------------------------*/
|
||||
pHKL CreateHKL(pMotor pTheta, pMotor pOmega,
|
||||
pMotor pChi, pMotor pPhi, pMotor pNu);
|
||||
pHKL CreateHKL();
|
||||
void DeleteHKL(void *pData);
|
||||
|
||||
int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/*------------------------------------------------------------------------*/
|
||||
int SetWavelengthVariable(SConnection *pCon, pHKL self, pSelVar pVar);
|
||||
int SetWavelengthManual(pHKL self, float fVal);
|
||||
void SetHKLScanTolerance(pHKL self, float value);
|
||||
int SetUB(pHKL self, float fUB[9]);
|
||||
int GetUB(pHKL self, float fUB[9]);
|
||||
@ -48,7 +45,8 @@
|
||||
|
||||
int HKLAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
int hklInRange(void *data, float fSet[4], int mask[4]);
|
||||
int hklInRange(void *data, double fSet[4], int mask[4]);
|
||||
int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]);
|
||||
void stopHKLMotors(pHKL self);
|
||||
|
||||
#endif
|
||||
|
9
hkl.i
9
hkl.i
@ -9,24 +9,17 @@
|
||||
|
||||
typedef struct __HKL {
|
||||
pObjectDescriptor pDes;
|
||||
double fUB[9];
|
||||
MATRIX UBinv;
|
||||
double fLambda;
|
||||
int iManual;
|
||||
double fLastHKL[5];
|
||||
int iNOR;
|
||||
int iQuad;
|
||||
int iHM;
|
||||
pMotor pTheta;
|
||||
pMotor pOmega;
|
||||
pMotor pChi;
|
||||
pMotor pPhi;
|
||||
pMotor pNu;
|
||||
pSelVar pMono;
|
||||
long lID;
|
||||
float scanTolerance;
|
||||
float targetHKL[3];
|
||||
int targetDirty;
|
||||
pIDrivable pMotDriv;
|
||||
} HKL;
|
||||
|
||||
|
||||
|
38
hkl.tex
38
hkl.tex
@ -20,26 +20,19 @@ $\langle$hkldat {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __HKL {@\\
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ double fUB[9];@\\
|
||||
\mbox{}\verb@ MATRIX UBinv;@\\
|
||||
\mbox{}\verb@ double fLambda;@\\
|
||||
\mbox{}\verb@ int iManual;@\\
|
||||
\mbox{}\verb@ double fLastHKL[5];@\\
|
||||
\mbox{}\verb@ int iNOR;@\\
|
||||
\mbox{}\verb@ int iQuad;@\\
|
||||
\mbox{}\verb@ int iHM;@\\
|
||||
\mbox{}\verb@ pMotor pTheta;@\\
|
||||
\mbox{}\verb@ pMotor pOmega;@\\
|
||||
\mbox{}\verb@ pMotor pChi;@\\
|
||||
\mbox{}\verb@ pMotor pPhi;@\\
|
||||
\mbox{}\verb@ pMotor pNu;@\\
|
||||
\mbox{}\verb@ pSelVar pMono;@\\
|
||||
\mbox{}\verb@ long lID;@\\
|
||||
\mbox{}\verb@ float scanTolerance;@\\
|
||||
\mbox{}\verb@ float targetHKL[3];@\\
|
||||
\mbox{}\verb@ int targetDirty;@\\
|
||||
\mbox{}\verb@ pIDrivable pMotDriv;@\\
|
||||
\mbox{}\verb@ } HKL;@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
@ -51,23 +44,12 @@ $\langle$hkldat {\footnotesize ?}$\rangle\equiv$
|
||||
The fields are more or less self explaining:
|
||||
\begin{description}
|
||||
\item[pDes] The standard object descriptor.
|
||||
\item[fUB] The UB matrix.
|
||||
\item[iUB] is a flag which spcifies if a UB is specified.
|
||||
\item[fLambda] The wavelength of the neutrons.
|
||||
\item[iManual] A flag which defines if the wavelength has been set manually
|
||||
or is updated automatically from a wavelength variable.
|
||||
\item[fLastHKL] the HKL of the last reflection calculated.
|
||||
\item[iNor] a flag for normal beam calculation mode.
|
||||
\item[iHM] a flag for histogram memory mode. In this mode two theta
|
||||
limits are checked alos for detector 2 and 3.
|
||||
\item[pTheta] The two theta motor. All motor are needed for boundary
|
||||
checking.
|
||||
\item[pOmega] The omega axis motor.
|
||||
\item[pChi] The chi axis motor.
|
||||
\item[pPhi] the phi axis motor.
|
||||
\item[pNu] the nu axis motor for normal beam geometry.
|
||||
This is detector tilt.
|
||||
\item[pMono] The selector variable doing the wavelength.
|
||||
\item[scanTolerance] The hkl module refuses to position a reflection if it is
|
||||
to close to omega limits for scanning. This is the tolerance to use.
|
||||
\item[targetHKL] The target HKL values to support the H, K, L virtual motors
|
||||
@ -95,15 +77,12 @@ $\langle$hklint {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct __HKL *pHKL;@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ pHKL CreateHKL(pMotor pTheta, pMotor pOmega, @\\
|
||||
\mbox{}\verb@ pMotor pChi, pMotor pPhi, pMotor pNu);@\\
|
||||
\mbox{}\verb@ pHKL CreateHKL();@\\
|
||||
\mbox{}\verb@ void DeleteHKL(void *pData);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@/*------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int SetWavelengthVariable(SConnection *pCon, pHKL self, pSelVar pVar);@\\
|
||||
\mbox{}\verb@ int SetWavelengthManual(pHKL self, float fVal);@\\
|
||||
\mbox{}\verb@ void SetHKLScanTolerance(pHKL self, float value);@\\
|
||||
\mbox{}\verb@ int SetUB(pHKL self, float fUB[9]);@\\
|
||||
\mbox{}\verb@ int GetUB(pHKL self, float fUB[9]);@\\
|
||||
@ -126,7 +105,8 @@ $\langle$hklint {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ int argc, char *argv[]); @\\
|
||||
\mbox{}\verb@ int hklInRange(void *data, float fSet[4], int mask[4]);@\\
|
||||
\mbox{}\verb@ int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@ void stopHKLMotors(pHKL self);@\\
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
@ -197,7 +177,7 @@ drive properly.
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$hkldat {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
@ -227,7 +207,7 @@ drive properly.
|
||||
\mbox{}\verb@#include "selvar.h"@\\
|
||||
\mbox{}\verb@@$\langle$hklint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
@ -257,7 +237,7 @@ $\langle$hklmotdat {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ pIDrivable pDriv;@\\
|
||||
\mbox{}\verb@ int index;@\\
|
||||
\mbox{}\verb@ }HKLMot, *pHKLMot;@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
@ -303,7 +283,7 @@ functions. The interpreter interface is minimal: only a value request is support
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
|
26
hkl.w
26
hkl.w
@ -15,47 +15,29 @@ The object uses the following object data structure:
|
||||
@d hkldat @{
|
||||
typedef struct __HKL {
|
||||
pObjectDescriptor pDes;
|
||||
double fUB[9];
|
||||
MATRIX UBinv;
|
||||
double fLambda;
|
||||
int iManual;
|
||||
double fLastHKL[5];
|
||||
int iNOR;
|
||||
int iQuad;
|
||||
int iHM;
|
||||
pMotor pTheta;
|
||||
pMotor pOmega;
|
||||
pMotor pChi;
|
||||
pMotor pPhi;
|
||||
pMotor pNu;
|
||||
pSelVar pMono;
|
||||
long lID;
|
||||
float scanTolerance;
|
||||
float targetHKL[3];
|
||||
int targetDirty;
|
||||
pIDrivable pMotDriv;
|
||||
} HKL;
|
||||
@}
|
||||
|
||||
The fields are more or less self explaining:
|
||||
\begin{description}
|
||||
\item[pDes] The standard object descriptor.
|
||||
\item[fUB] The UB matrix.
|
||||
\item[iUB] is a flag which spcifies if a UB is specified.
|
||||
\item[fLambda] The wavelength of the neutrons.
|
||||
\item[iManual] A flag which defines if the wavelength has been set manually
|
||||
or is updated automatically from a wavelength variable.
|
||||
\item[fLastHKL] the HKL of the last reflection calculated.
|
||||
\item[iNor] a flag for normal beam calculation mode.
|
||||
\item[iHM] a flag for histogram memory mode. In this mode two theta
|
||||
limits are checked alos for detector 2 and 3.
|
||||
\item[pTheta] The two theta motor. All motor are needed for boundary
|
||||
checking.
|
||||
\item[pOmega] The omega axis motor.
|
||||
\item[pChi] The chi axis motor.
|
||||
\item[pPhi] the phi axis motor.
|
||||
\item[pNu] the nu axis motor for normal beam geometry.
|
||||
This is detector tilt.
|
||||
\item[pMono] The selector variable doing the wavelength.
|
||||
\item[scanTolerance] The hkl module refuses to position a reflection if it is
|
||||
to close to omega limits for scanning. This is the tolerance to use.
|
||||
\item[targetHKL] The target HKL values to support the H, K, L virtual motors
|
||||
@ -78,15 +60,12 @@ module:
|
||||
@d hklint @{
|
||||
typedef struct __HKL *pHKL;
|
||||
/*-------------------------------------------------------------------------*/
|
||||
pHKL CreateHKL(pMotor pTheta, pMotor pOmega,
|
||||
pMotor pChi, pMotor pPhi, pMotor pNu);
|
||||
pHKL CreateHKL();
|
||||
void DeleteHKL(void *pData);
|
||||
|
||||
int HKLFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
/*------------------------------------------------------------------------*/
|
||||
int SetWavelengthVariable(SConnection *pCon, pHKL self, pSelVar pVar);
|
||||
int SetWavelengthManual(pHKL self, float fVal);
|
||||
void SetHKLScanTolerance(pHKL self, float value);
|
||||
int SetUB(pHKL self, float fUB[9]);
|
||||
int GetUB(pHKL self, float fUB[9]);
|
||||
@ -109,6 +88,7 @@ module:
|
||||
int argc, char *argv[]);
|
||||
int hklInRange(void *data, float fSet[4], int mask[4]);
|
||||
int startHKLMotors(pHKL self, SConnection *pCon, float fSet[4]);
|
||||
void stopHKLMotors(pHKL self);
|
||||
@}
|
||||
All functions return 0 on failure, 1 on success if not stated otherwise.
|
||||
Most functions take a pointer to a HKL data structure as first parameter.
|
||||
|
59
hklmot.c
59
hklmot.c
@ -15,6 +15,7 @@
|
||||
#include "hkl.h"
|
||||
#include "hkl.i"
|
||||
#include "hklmot.h"
|
||||
#include "singlex.h"
|
||||
/*=================== Object Descriptor Interface ===================================================*/
|
||||
static void *HKLGetInterface(void *pData, int iID){
|
||||
pHKLMot self = NULL;
|
||||
@ -28,21 +29,15 @@ static void *HKLGetInterface(void *pData, int iID){
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*--------------------------------------------------------------------------------------------------*/
|
||||
extern void stopHKLMotors(pHKL hkl);
|
||||
/*=================== Drivable Interface ============================================================*/
|
||||
static int HKLHalt(void *pData){
|
||||
pHKLMot self = NULL;
|
||||
|
||||
self = (pHKLMot)pData;
|
||||
assert(self != NULL);
|
||||
|
||||
self->pHkl->pTheta->pDrivInt->Halt(self->pHkl->pTheta);
|
||||
self->pHkl->pOmega->pDrivInt->Halt(self->pHkl->pOmega);
|
||||
if(self->pHkl->iNOR == 1){
|
||||
self->pHkl->pNu->pDrivInt->Halt(self->pHkl->pNu);
|
||||
} else {
|
||||
self->pHkl->pChi->pDrivInt->Halt(self->pHkl->pChi);
|
||||
self->pHkl->pPhi->pDrivInt->Halt(self->pHkl->pPhi);
|
||||
}
|
||||
stopHKLMotors(self->pHkl);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------------------------*/
|
||||
@ -72,26 +67,52 @@ static long HKLSetValue(void *pData, SConnection *pCon, float fVal){
|
||||
/*---------------------------------------------------------------------------------------------------*/
|
||||
static int checkMotors(pHKLMot self, SConnection *pCon){
|
||||
int status;
|
||||
pMotor pTheta, pOmega, pChi, pPhi, pNu;
|
||||
|
||||
pTheta = SXGetMotor(TwoTheta);
|
||||
pOmega = SXGetMotor(Omega);
|
||||
pChi = SXGetMotor(Chi);
|
||||
pPhi = SXGetMotor(Phi);
|
||||
if(pTheta == NULL || pOmega == NULL){
|
||||
SCWrite(pCon,"ERROR: configuration problem, stt,om motors not found,",
|
||||
eError);
|
||||
return HWFault;
|
||||
}
|
||||
|
||||
status = self->pHkl->pTheta->pDrivInt->CheckStatus(self->pHkl->pTheta, pCon);
|
||||
|
||||
status = pTheta->pDrivInt->CheckStatus(pTheta, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
}
|
||||
status = self->pHkl->pOmega->pDrivInt->CheckStatus(self->pHkl->pOmega, pCon);
|
||||
status = pOmega->pDrivInt->CheckStatus(pOmega, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
}
|
||||
if(self->pHkl->iNOR == 1){
|
||||
status = self->pHkl->pNu->pDrivInt->CheckStatus(self->pHkl->pNu, pCon);
|
||||
if(SXGetMode() == NB){
|
||||
pNu = SXGetMotor(Nu);
|
||||
if(pNu == NULL){
|
||||
SCWrite(pCon,"ERROR: configuration problem, nu motor not found,",
|
||||
eError);
|
||||
return HWFault;
|
||||
|
||||
}
|
||||
status = pNu->pDrivInt->CheckStatus(pNu, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
}
|
||||
} else {
|
||||
status = self->pHkl->pChi->pDrivInt->CheckStatus(self->pHkl->pChi, pCon);
|
||||
pChi = SXGetMotor(Chi);
|
||||
pPhi = SXGetMotor(Phi);
|
||||
if(pTheta == NULL || pOmega == NULL){
|
||||
SCWrite(pCon,"ERROR: configuration problem, chi, phi motors not found,",
|
||||
eError);
|
||||
return HWFault;
|
||||
}
|
||||
status = pChi->pDrivInt->CheckStatus(pChi, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
}
|
||||
status = self->pHkl->pPhi->pDrivInt->CheckStatus(self->pHkl->pPhi, pCon);
|
||||
status = pPhi->pDrivInt->CheckStatus(pPhi, pCon);
|
||||
if(status != HWIdle && status != OKOK){
|
||||
return status;
|
||||
}
|
||||
@ -204,11 +225,11 @@ int HKLMotInstall(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, c
|
||||
char pBuffer[131];
|
||||
|
||||
if(argc < 2){
|
||||
SCWrite(pCon,"ERROR: Insifficient number of arguments to HKLMotInstall",eError);
|
||||
return 0;
|
||||
pHkl = (pHKL)FindCommandData(pSics,"hkl","4-Circle-Calculus");
|
||||
} else {
|
||||
strtolower(argv[1]);
|
||||
pHkl = (pHKL)FindCommandData(pSics,argv[1],"4-Circle-Calculus");
|
||||
}
|
||||
strtolower(argv[1]);
|
||||
pHkl = (pHKL)FindCommandData(pSics,argv[1],"4-Circle-Calculus");
|
||||
if(pHkl == NULL){
|
||||
snprintf(pBuffer,131,"ERROR: %s is not present or no HKL object",argv[1]);
|
||||
SCWrite(pCon,pBuffer,eError);
|
||||
|
@ -45,9 +45,11 @@ static int HMCHalt(void *pData)
|
||||
for(i = 0; i < self->nSlaves; i++)
|
||||
{
|
||||
status = self->slaves[i]->Halt(self->slaveData[i]);
|
||||
ReleaseCountLock(self->slaves[i]);
|
||||
if(status != OKOK)
|
||||
retVal = status;
|
||||
}
|
||||
ReleaseCountLock(self->pCount);
|
||||
return retVal;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@ -59,8 +61,13 @@ static int HMCStart(void *pData, SConnection *pCon)
|
||||
self = (pHMcontrol)pData;
|
||||
assert(self);
|
||||
|
||||
if(!GetCountLock(self->pCount, pCon)){
|
||||
return HWFault;
|
||||
}
|
||||
|
||||
for(i = 0; i < self->nSlaves; i++)
|
||||
{
|
||||
ReleaseCountLock(self->slaves[i]);
|
||||
status = self->slaves[i]->StartCount(self->slaveData[i],pCon);
|
||||
if(status != OKOK)
|
||||
{
|
||||
|
@ -92,9 +92,9 @@ static int DriverList(SConnection *con, SicsInterp *sics,
|
||||
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);
|
||||
SCPrintf(con, eValue, "%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);
|
||||
SCPrintf(con, eValue, "%s %s", p->name, p->desc);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
24
interface.c
24
interface.c
@ -167,6 +167,30 @@ int GetDrivablePosition(void *pObject, SConnection *pCon, float *fPos)
|
||||
{
|
||||
return (pICountable)FindInterface(pObject,COUNTID);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int GetCountLock(pICountable self, SConnection *pCon)
|
||||
{
|
||||
if(self->running == 1)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: someone else is already counting!", eError);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->running = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void ReleaseCountLock(pICountable self)
|
||||
{
|
||||
self->running = 0;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int isRunning(pICountable self)
|
||||
{
|
||||
return self->running;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pICallBack GetCallbackInterface(void *pObject)
|
||||
{
|
||||
|
36
interface.h
36
interface.h
@ -1,5 +1,5 @@
|
||||
|
||||
#line 379 "interface.w"
|
||||
#line 399 "interface.w"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
I N T E R F A C E S
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
/* ----------------------- The drivable interface -----------------------*/
|
||||
|
||||
#line 119 "interface.w"
|
||||
#line 121 "interface.w"
|
||||
|
||||
|
||||
typedef struct {
|
||||
@ -48,17 +48,18 @@
|
||||
float *fPos);
|
||||
|
||||
|
||||
#line 405 "interface.w"
|
||||
#line 425 "interface.w"
|
||||
|
||||
|
||||
pIDrivable CreateDrivableInterface(void);
|
||||
|
||||
/* ------------------------ The countable interface ---------------------*/
|
||||
|
||||
#line 186 "interface.w"
|
||||
#line 188 "interface.w"
|
||||
|
||||
typedef struct {
|
||||
int ID;
|
||||
int running;
|
||||
int (*Halt)(void *self);
|
||||
void (*SetCountParameters)(void *self, float fPreset,
|
||||
CounterMode eMode);\
|
||||
@ -70,25 +71,27 @@
|
||||
} ICountable, *pICountable;
|
||||
|
||||
pICountable GetCountableInterface(void *pObject);
|
||||
int GetCountLock(pICountable self, SConnection *pCon);
|
||||
void ReleaseCountLock(pICountable self);
|
||||
int isRunning(pICountable self);
|
||||
|
||||
|
||||
#line 410 "interface.w"
|
||||
#line 430 "interface.w"
|
||||
|
||||
|
||||
pICountable CreateCountableInterface(void);
|
||||
|
||||
/* ------------------------- The CallBack Interface --------------------*/
|
||||
|
||||
#line 239 "interface.w"
|
||||
#line 253 "interface.w"
|
||||
|
||||
typedef void (*KillFuncIT)(void *pData);
|
||||
typedef int (*SICSCallBack)(int iEvent, void *pEventData,
|
||||
void *pUserData, commandContext cc);
|
||||
void *pUserData);
|
||||
|
||||
#line 415 "interface.w"
|
||||
#line 435 "interface.w"
|
||||
|
||||
|
||||
#line 261 "interface.w"
|
||||
#line 275 "interface.w"
|
||||
|
||||
typedef struct __ICallBack *pICallBack;
|
||||
|
||||
@ -98,22 +101,23 @@
|
||||
int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData);
|
||||
|
||||
/* callback client side */
|
||||
long RegisterCallback(pICallBack pInterface, commandContext comCon,
|
||||
long RegisterCallback(pICallBack pInterface,
|
||||
int iEvent, SICSCallBack pFunc,
|
||||
void *pUserData, KillFuncIT pKill);
|
||||
int RemoveCallback(pICallBack pInterface, long iID);
|
||||
int RemoveCallback2(pICallBack pInterface, void *pUserData);
|
||||
int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon);
|
||||
|
||||
int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
pICallBack GetCallbackInterface(void *pData);
|
||||
|
||||
#line 416 "interface.w"
|
||||
#line 436 "interface.w"
|
||||
|
||||
/*---------------------- The Environment Interface --------------------*/
|
||||
|
||||
#line 333 "interface.w"
|
||||
#line 353 "interface.w"
|
||||
|
||||
typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode;
|
||||
typedef struct {
|
||||
@ -123,13 +127,13 @@
|
||||
int (*HandleError)(void *self);
|
||||
} EVInterface, *pEVInterface;
|
||||
|
||||
#line 418 "interface.w"
|
||||
#line 438 "interface.w"
|
||||
|
||||
|
||||
#line 359 "interface.w"
|
||||
#line 379 "interface.w"
|
||||
|
||||
pEVInterface CreateEVInterface(void);
|
||||
|
||||
#line 419 "interface.w"
|
||||
#line 439 "interface.w"
|
||||
|
||||
#endif
|
||||
|
@ -51,12 +51,14 @@ $\langle$obdes {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@#define SICSDESCRIPTOR@\\
|
||||
\mbox{}\verb@#include <stdio.h>@\\
|
||||
\mbox{}\verb@#include <ifile.h>@\\
|
||||
\mbox{}\verb@#include <hipadaba.h>@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ char *name;@\\
|
||||
\mbox{}\verb@ int (*SaveStatus)(void *self, char *name,FILE *fd);@\\
|
||||
\mbox{}\verb@ void *(*GetInterface)(void *self, int iInterfaceID);@\\
|
||||
\mbox{}\verb@ IPair *pKeys;@\\
|
||||
\mbox{}\verb@ pHdb parNode;@\\
|
||||
\mbox{}\verb@ } ObjectDescriptor, *pObjectDescriptor;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ /*---------------------------------------------------------------------------*/@\\
|
||||
@ -81,7 +83,7 @@ $\langle$obdes {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ int iHasType(void *pData, char *Type);@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@#endif @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
@ -152,7 +154,7 @@ $\langle$driv {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ int GetDrivablePosition(void *pObject, SConnection *pCon,@\\
|
||||
\mbox{}\verb@ float *fPos);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
@ -216,6 +218,7 @@ $\langle$count {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ int ID;@\\
|
||||
\mbox{}\verb@ int running;@\\
|
||||
\mbox{}\verb@ int (*Halt)(void *self);@\\
|
||||
\mbox{}\verb@ void (*SetCountParameters)(void *self, float fPreset,@\\
|
||||
\mbox{}\verb@ CounterMode eMode);\@\\
|
||||
@ -227,8 +230,10 @@ $\langle$count {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ } ICountable, *pICountable;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pICountable GetCountableInterface(void *pObject); @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@ int GetCountLock(pICountable self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ void ReleaseCountLock(pICountable self);@\\
|
||||
\mbox{}\verb@ int isRunning(pICountable self);@\\
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
@ -237,6 +242,8 @@ $\langle$count {\footnotesize ?}$\rangle\equiv$
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
{\bf running } Is a flag which says if the counter is operating or not.
|
||||
|
||||
{\bf Halt and StartCount} are self explaining, they just do what they say. Please
|
||||
note, that counting configuration must have happened before usage of this
|
||||
interface.
|
||||
@ -260,6 +267,13 @@ the existence of a countable interface. If it exists a pointer to it will be
|
||||
returned. NEVER free this pointer. If no countable interface exists, NULL
|
||||
will be returned.
|
||||
|
||||
{\bf GetCountLock} will try to set the running flag. If it is already running, an error
|
||||
is printed to pCon and 0 is returned.
|
||||
|
||||
{\bf ReleaseCountLock} release the count lock.
|
||||
|
||||
{\bf isRunning} returns the running flag.
|
||||
|
||||
\subsubsection{The Callback Interface}
|
||||
The Callback Interface is SICS suport for component behaviour for objects.
|
||||
Consider objects A and B. A now is able to generate certain events when it's
|
||||
@ -281,8 +295,8 @@ $\langle$callfunc {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ typedef void (*KillFuncIT)(void *pData);@\\
|
||||
\mbox{}\verb@ typedef int (*SICSCallBack)(int iEvent, void *pEventData, @\\
|
||||
\mbox{}\verb@ void *pUserData, commandContext cc);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@ void *pUserData);@\\
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
@ -321,17 +335,18 @@ $\langle$cifunc {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData); @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ /* callback client side */@\\
|
||||
\mbox{}\verb@ long RegisterCallback(pICallBack pInterface, commandContext comCon, @\\
|
||||
\mbox{}\verb@ long RegisterCallback(pICallBack pInterface, @\\
|
||||
\mbox{}\verb@ int iEvent, SICSCallBack pFunc,@\\
|
||||
\mbox{}\verb@ void *pUserData, KillFuncIT pKill);@\\
|
||||
\mbox{}\verb@ int RemoveCallback(pICallBack pInterface, long iID);@\\
|
||||
\mbox{}\verb@ int RemoveCallback2(pICallBack pInterface, void *pUserData);@\\
|
||||
\mbox{}\verb@ int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]); @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pICallBack GetCallbackInterface(void *pData); @\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
@ -378,6 +393,11 @@ RegisterCallBack.
|
||||
search key for deletion is the pointer to user data. All callbacks related
|
||||
to this user data in the interface specified will be removed.
|
||||
|
||||
{\bf RemoveCallbackCon} is another variant for removing callbacks. This time the
|
||||
search key for deletion is the pointer to user data which must be a connection object.
|
||||
All callbacks related to this connection in the interface specified will be removed. This is
|
||||
a convenience function for removing interest callbacks in SICS.
|
||||
|
||||
{\bf CallbackScript} allows to connect callbacks to scripts. Please
|
||||
note, that those scripts will have a dummy connection to clients only
|
||||
and will not be able to write to clients. All output occurring in
|
||||
@ -404,7 +424,7 @@ $\langle$envir {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ int (*IsInTolerance)(void *self);@\\
|
||||
\mbox{}\verb@ int (*HandleError)(void *self);@\\
|
||||
\mbox{}\verb@ } EVInterface, *pEVInterface;@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
@ -437,7 +457,7 @@ $\langle$envfunc {\footnotesize ?}$\rangle\equiv$
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pEVInterface CreateEVInterface(void);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
@ -465,7 +485,7 @@ $\langle$envfunc {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ char * GetDescriptorKey(pObjectDescriptor self, char *keyName);@\\
|
||||
\mbox{}\verb@ char * GetDescriptorGroup(pObjectDescriptor self);@\\
|
||||
\mbox{}\verb@ char * GetDescriptorDescription(pObjectDescriptor self);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
@ -517,7 +537,7 @@ $\langle$envfunc {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@@$\langle$envir {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@$\langle$envfunc {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
|
26
interface.w
26
interface.w
@ -46,12 +46,14 @@ Let's start with the objectdescriptor:
|
||||
#define SICSDESCRIPTOR
|
||||
#include <stdio.h>
|
||||
#include <ifile.h>
|
||||
#include <hipadaba.h>
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int (*SaveStatus)(void *self, char *name,FILE *fd);
|
||||
void *(*GetInterface)(void *self, int iInterfaceID);
|
||||
IPair *pKeys;
|
||||
pHdb parNode;
|
||||
} ObjectDescriptor, *pObjectDescriptor;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
@ -186,6 +188,7 @@ This is an interface for interacting with anything which counts.
|
||||
@d count @{
|
||||
typedef struct {
|
||||
int ID;
|
||||
int running;
|
||||
int (*Halt)(void *self);
|
||||
void (*SetCountParameters)(void *self, float fPreset,
|
||||
CounterMode eMode);\
|
||||
@ -197,9 +200,13 @@ This is an interface for interacting with anything which counts.
|
||||
} ICountable, *pICountable;
|
||||
|
||||
pICountable GetCountableInterface(void *pObject);
|
||||
|
||||
int GetCountLock(pICountable self, SConnection *pCon);
|
||||
void ReleaseCountLock(pICountable self);
|
||||
int isRunning(pICountable self);
|
||||
@}
|
||||
|
||||
{\bf running } Is a flag which says if the counter is operating or not.
|
||||
|
||||
{\bf Halt and StartCount} are self explaining, they just do what they say. Please
|
||||
note, that counting configuration must have happened before usage of this
|
||||
interface.
|
||||
@ -223,6 +230,13 @@ the existence of a countable interface. If it exists a pointer to it will be
|
||||
returned. NEVER free this pointer. If no countable interface exists, NULL
|
||||
will be returned.
|
||||
|
||||
{\bf GetCountLock} will try to set the running flag. If it is already running, an error
|
||||
is printed to pCon and 0 is returned.
|
||||
|
||||
{\bf ReleaseCountLock} release the count lock.
|
||||
|
||||
{\bf isRunning} returns the running flag.
|
||||
|
||||
\subsubsection{The Callback Interface}
|
||||
The Callback Interface is SICS suport for component behaviour for objects.
|
||||
Consider objects A and B. A now is able to generate certain events when it's
|
||||
@ -239,7 +253,7 @@ function:
|
||||
@d callfunc @{
|
||||
typedef void (*KillFuncIT)(void *pData);
|
||||
typedef int (*SICSCallBack)(int iEvent, void *pEventData,
|
||||
void *pUserData, commandContext cc);
|
||||
void *pUserData);
|
||||
@}
|
||||
|
||||
The callback function is meant to return 0 for failure or 1 for success.
|
||||
@ -267,11 +281,12 @@ interface:
|
||||
int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData);
|
||||
|
||||
/* callback client side */
|
||||
long RegisterCallback(pICallBack pInterface, commandContext comCon,
|
||||
long RegisterCallback(pICallBack pInterface,
|
||||
int iEvent, SICSCallBack pFunc,
|
||||
void *pUserData, KillFuncIT pKill);
|
||||
int RemoveCallback(pICallBack pInterface, long iID);
|
||||
int RemoveCallback2(pICallBack pInterface, void *pUserData);
|
||||
int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon);
|
||||
|
||||
int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
@ -317,6 +332,11 @@ RegisterCallBack.
|
||||
search key for deletion is the pointer to user data. All callbacks related
|
||||
to this user data in the interface specified will be removed.
|
||||
|
||||
{\bf RemoveCallbackCon} is another variant for removing callbacks. This time the
|
||||
search key for deletion is the pointer to user data which must be a connection object.
|
||||
All callbacks related to this connection in the interface specified will be removed. This is
|
||||
a convenience function for removing interest callbacks in SICS.
|
||||
|
||||
{\bf CallbackScript} allows to connect callbacks to scripts. Please
|
||||
note, that those scripts will have a dummy connection to clients only
|
||||
and will not be able to write to clients. All output occurring in
|
||||
|
86
macro.c
86
macro.c
@ -529,7 +529,7 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
if(FindCommand(pInter,pBueffel) != NULL)
|
||||
{
|
||||
sprintf(pBueffel,"%s:%d>> %s",pFile,iLine,pCom);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
if(pWhere != NULL)
|
||||
{
|
||||
free(pWhere);
|
||||
@ -627,21 +627,6 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
}
|
||||
SCnoSock(pIntern);
|
||||
|
||||
/* configure the log file */
|
||||
pFil = strdup(argv[1]);
|
||||
pExt = strrchr(pFil,(int)'.');
|
||||
if(!pExt)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: no extension found in InternalFileEval",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(pExt,".log");
|
||||
SCAddLogFile(pIntern,pFil);
|
||||
free(pFil);
|
||||
}
|
||||
|
||||
/* invoke the fileeval */
|
||||
MacroPush(pIntern);
|
||||
@ -664,9 +649,8 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
int ClientPut(SConnection *pCon, SicsInterp *pInter, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
OutCode eOut = eWarning;
|
||||
OutCode eOut = eLog;
|
||||
int i = 0, iCode, iLen;
|
||||
int iMacro;
|
||||
char *ppCode;
|
||||
char *pMessage = NULL;
|
||||
|
||||
@ -701,7 +685,7 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
}
|
||||
else
|
||||
{
|
||||
i = 10;
|
||||
i = eLog;
|
||||
iCode = argc;
|
||||
}
|
||||
|
||||
@ -740,8 +724,14 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
case 10:
|
||||
eOut = eError;
|
||||
break;
|
||||
case 11:
|
||||
eOut = eLog;
|
||||
break;
|
||||
case 12:
|
||||
eOut = eLogError;
|
||||
break;
|
||||
default:
|
||||
eOut = eWarning;
|
||||
eOut = eLog;
|
||||
iCode = argc;
|
||||
break;
|
||||
}
|
||||
@ -756,19 +746,13 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
pMessage = (char *)malloc((iLen+100)*sizeof(char));
|
||||
if(!pMessage)
|
||||
{
|
||||
SCWrite(pCon,"ERROR: out of memory in clientput",eError);
|
||||
SCWrite(pCon,"ERROR: out of memory in clientput",eLogError);
|
||||
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
|
||||
*/
|
||||
iMacro = SCinMacro(pCon);
|
||||
SCsetMacro(pCon,0);
|
||||
SCWrite(pCon,pMessage,eOut);
|
||||
SCsetMacro(pCon,iMacro);
|
||||
if(pMessage)
|
||||
{
|
||||
free(pMessage);
|
||||
@ -784,14 +768,14 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
int iMacro;
|
||||
char *ppCode;
|
||||
char *pMessage = NULL;
|
||||
commandContext cc;
|
||||
SConnection *conCon = NULL;
|
||||
|
||||
assert(pCon);
|
||||
assert(pInter);
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
SCWrite(pCon,"Insufficient arguments to ClientPut",eError);
|
||||
SCWrite(pCon,"Insufficient arguments to ClientPut",eLogError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -856,8 +840,14 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
case 10:
|
||||
eOut = eError;
|
||||
break;
|
||||
case 11:
|
||||
eOut = eLog;
|
||||
break;
|
||||
case 12:
|
||||
eOut = eLogError;
|
||||
break;
|
||||
default:
|
||||
eOut = eWarning;
|
||||
eOut = eLog;
|
||||
iCode = argc;
|
||||
break;
|
||||
}
|
||||
@ -882,14 +872,13 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
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);
|
||||
conCon = SCCopyConnection(pCon);
|
||||
if(conCon == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory in gumput", eError);
|
||||
}
|
||||
strcpy(conCon->deviceID,"gumput");
|
||||
SCWrite(conCon,pMessage,eOut);
|
||||
SCDeleteConnection(conCon);
|
||||
if(pMessage)
|
||||
{
|
||||
free(pMessage);
|
||||
@ -908,7 +897,7 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
SCWrite(pCon,"Insufficient arguments to Broadcast",eError);
|
||||
SCWrite(pCon,"Insufficient arguments to Broadcast",eLog);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -917,10 +906,7 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
write to client and not into interpreter
|
||||
*/
|
||||
Arg2Text(argc-1, &argv[1],pBueffel,255);
|
||||
iMacro = SCinMacro(pCon);
|
||||
SCsetMacro(pCon,0);
|
||||
ServerWriteGlobal(pBueffel,eWarning);
|
||||
SCsetMacro(pCon,iMacro);
|
||||
ServerWriteGlobal(pBueffel,eLog);
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------
|
||||
@ -1013,13 +999,14 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
SCWrite(pCon, "ERROR: no more memory", eError);
|
||||
return 0;
|
||||
}
|
||||
Tcl_ResetResult(pTcl);
|
||||
iRet = Tcl_Eval(pTcl,pCommand);
|
||||
if (pCommand != pBueffel) free(pCommand);
|
||||
if(iRet == TCL_OK)
|
||||
{
|
||||
if(strlen(pTcl->result) > 0){
|
||||
SCPrintf(pCon, eStatus, "%s", pTcl->result);
|
||||
SCPrintf(pCon, eValue, "%s", pTcl->result);
|
||||
}
|
||||
if (pCommand != pBueffel) free(pCommand);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
@ -1028,7 +1015,10 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
{
|
||||
Tcl_UnsetVar(pTcl,SICSERROR,TCL_GLOBAL_ONLY);
|
||||
}
|
||||
SCPrintf(pCon,eError,"%s",pTcl->result);
|
||||
if(strlen(pTcl->result) > 0){
|
||||
SCPrintf(pCon,eError,"ERROR: Tcl reported %s in %s",pTcl->result, pCommand);
|
||||
}
|
||||
if (pCommand != pBueffel) free(pCommand);
|
||||
return 0;
|
||||
}
|
||||
return 1; /* not reached */
|
||||
@ -1117,11 +1107,11 @@ extern int Nxinter_SafeInit(Tcl_Interp *pTcl); /* from Swig NeXus Tcl interface
|
||||
}
|
||||
strtolower(argv[0]);
|
||||
if(strcmp(argv[0],"fulltransact") == 0){
|
||||
SCPrintf(pCon,eError, "TRANSACTIONSTART %s",pCommand);
|
||||
SCPrintf(pCon,eLog, "TRANSACTIONSTART %s",pCommand);
|
||||
}
|
||||
iRet = InterpExecute(pSics,pCon,pCommand);
|
||||
if (pCommand != pBuffer) free(pCommand);
|
||||
SCWrite(pCon,"TRANSACTIONFINISHED",eError);
|
||||
SCWrite(pCon,"TRANSACTIONFINISHED",eLog);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
|
9
make_gen
9
make_gen
@ -21,7 +21,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||
mesure.o uubuffer.o commandlog.o udpquieck.o fourtable.o\
|
||||
rmtrail.o help.o nxupdate.o confvirtualmot.o vector.o\
|
||||
simchop.o choco.o chadapter.o trim.o scaldate.o tasub.o\
|
||||
hklscan.o xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\
|
||||
xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\
|
||||
circular.o maximize.o sicscron.o scanvar.o tasublib.o\
|
||||
d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o nxxml.o\
|
||||
synchronize.o definealias.o oscillate.o tasdrive.o \
|
||||
@ -37,7 +37,10 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||
sicshdbadapter.o polldriv.o sicspoll.o statemon.o hmslave.o \
|
||||
nwatch.o asyncqueue.o asyncprotocol.o sicsobj.o \
|
||||
nxcopy.o nxinterhelper.o nxinter_wrap.o genericcontroller.o nxstack.o \
|
||||
sctdriveadapter.o sctdriveobj.o uselect.o
|
||||
sctdriveadapter.o sctdriveobj.o reflist.o singlex.o fourmess.o \
|
||||
sgclib.o sgfind.o sgio.o sgsi.o sghkl.o singlediff.o singlebi.o \
|
||||
singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \
|
||||
rwpuffer.o asynnet.o background.o
|
||||
|
||||
MOTOROBJ = motor.o simdriv.o
|
||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||
@ -60,7 +63,7 @@ full: purge all
|
||||
SICServer: $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) \
|
||||
$(VELOOBJ) $(DIFIL) $(EXTRA) \
|
||||
$(SUBLIBS)
|
||||
$(CC) -g -pg -o SICServer \
|
||||
$(CC) -g -o SICServer \
|
||||
$(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) \
|
||||
$(VELOOBJ) $(DIFOBJ) $(EXTRA) $(LIBS)
|
||||
|
||||
|
10
maximize.c
10
maximize.c
@ -50,7 +50,7 @@
|
||||
#include "motor.h"
|
||||
|
||||
#define MAXPTS 100
|
||||
#define DEBUG 1
|
||||
#define DEBUG 0
|
||||
|
||||
typedef struct __MAXIMIZE {
|
||||
pObjectDescriptor pDes;
|
||||
@ -382,8 +382,14 @@
|
||||
fCent = x[i] +(fDisc -y[i])/fS;
|
||||
}
|
||||
/* finished ! */
|
||||
for(i = 0; i < iTop-1; i++){
|
||||
if(fCent >= x[i] && fCent < x[i+1] ){
|
||||
lCts = y[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
maxDrive(pVar,pVarName,fCent,pCon);
|
||||
sprintf(pBueffel,"Found peak center at %8.2f", fCent);
|
||||
sprintf(pBueffel,"Found peak center at %8.2f, Count = %ld", fCent, lCts);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
|
26
mesure.c
26
mesure.c
@ -423,7 +423,7 @@ static void ListMesure(pMesure self, char *name, SConnection *pCon)
|
||||
self->iCounts++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int getMesureNP(pMesure self, double twoTheta)
|
||||
{
|
||||
@ -671,7 +671,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
AddScanVar(self->pScanner, pServ->pSics,pCon,self->pCOmega,
|
||||
fStart, stepWidth);
|
||||
snprintf(pBueffel,131,"Scanning om from %f with step %f", fStart, stepWidth);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
/*
|
||||
Oksana does not want o2t scans to be tightly coupled, this is why we
|
||||
cannot use the normal o2t scan variable. Instead we calculate new limits and
|
||||
@ -688,7 +688,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
AddScanVar(self->pScanner, pServ->pSics,pCon,self->pC2Theta,
|
||||
fStart, stepWidth);
|
||||
snprintf(pBueffel,131,"Scanning 2theta from %f with step %f", fStart, stepWidth);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -744,7 +744,7 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
/*
|
||||
redo scan with preset * 5
|
||||
*/
|
||||
SCWrite(pCon,"Remeasuring weak reflection",eWarning);
|
||||
SCWrite(pCon,"Remeasuring weak reflection",eLog);
|
||||
iRet = SilentScan(self->pScanner,np,self->CountMode,
|
||||
fPreset*5.,pServ->pSics,pCon);
|
||||
|
||||
@ -811,7 +811,9 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
/* do the logfile */
|
||||
strcpy(pFilename,pRoot);
|
||||
strcat(pFilename,"log");
|
||||
/* TODO
|
||||
self->iLogFile = SCAddLogFile(pCon,pFilename);
|
||||
*/
|
||||
self->pCon = pCon;
|
||||
|
||||
/*
|
||||
@ -916,7 +918,9 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
strcat(pFile,"/");
|
||||
strcat(pFile,fileroot);
|
||||
strcat(pFile,".log");
|
||||
/* TODO:
|
||||
self->iLogFile = SCAddLogFile(pCon,pFile);
|
||||
*/
|
||||
self->pCon = pCon;
|
||||
|
||||
/*
|
||||
@ -960,7 +964,9 @@ static int ScanReflection(pMesure self, float twoTheta, SConnection *pCon)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
SCDelLogFile(self->pCon,self->iLogFile);
|
||||
/* TODO
|
||||
* SCDelLogFile(self->pCon,self->iLogFile);
|
||||
*/
|
||||
if(self->psd == 1)
|
||||
{
|
||||
self->pCon = NULL;
|
||||
@ -1094,7 +1100,7 @@ static double getProtonAverage(pMesure self){
|
||||
self->fPosition[0], self->fPosition[1],
|
||||
self->fPosition[2],self->fPosition[3],
|
||||
fSum,fSigma);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
|
||||
/* get temperature */
|
||||
fTemp = -777.77;
|
||||
@ -1218,7 +1224,7 @@ static double getProtonAverage(pMesure self){
|
||||
/* make a mark */
|
||||
SNXFormatTime(pTime,131);
|
||||
sprintf(pBueffel,"Starting at list %s at %s",pFile,pTime);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
|
||||
/* skippy! */
|
||||
for(i = 0; i < iSkip; i++)
|
||||
@ -1272,7 +1278,7 @@ static double getProtonAverage(pMesure self){
|
||||
/* we are done */
|
||||
SNXFormatTime(pTime,131);
|
||||
sprintf(pBueffel,"Finishing list %s at %s",pFile,pTime);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
|
||||
fclose(fd);
|
||||
return 1;
|
||||
@ -1366,7 +1372,7 @@ static double getProtonAverage(pMesure self){
|
||||
/* make a mark */
|
||||
SNXFormatTime(pTime,131);
|
||||
sprintf(pBueffel,"Starting at list %s at %s",pFile,pTime);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
|
||||
/* skippy! */
|
||||
for(i = 0; i < iSkip; i++)
|
||||
@ -1409,7 +1415,7 @@ static double getProtonAverage(pMesure self){
|
||||
/* we are done */
|
||||
SNXFormatTime(pTime,131);
|
||||
sprintf(pBueffel,"Finishing list %s at %s",pFile,pTime);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
|
||||
fclose(fd);
|
||||
return 1;
|
||||
|
@ -200,6 +200,12 @@ static int RGSetDriverPar(void *data, SConnection *pCon,
|
||||
} else if (strcmp(name,"recover") == 0){
|
||||
self->recover = (int)value;
|
||||
return 1;
|
||||
} else if(strcmp(name,"hardupperlim") == 0) {
|
||||
self->fUpper = value;
|
||||
return 1;
|
||||
} else if(strcmp(name,"hardlowerlim") == 0){
|
||||
self->fLower = value;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
649
motor.c
649
motor.c
@ -9,6 +9,10 @@
|
||||
callback added: Mark Koennecke, August 1997
|
||||
endscript facility added: Mark Koennecke, August 2002
|
||||
Modified to support driver parameters, Mark Koennecke, January 2003
|
||||
|
||||
Reworked to allow for multiple implementations of motors on the same
|
||||
interface in preparation for second generation motors.
|
||||
Mark Koennecke, December 2008
|
||||
|
||||
Copyright:
|
||||
|
||||
@ -115,7 +119,71 @@
|
||||
self->stopped = 1;
|
||||
return self->pDriver->Halt((void *)self->pDriver);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
MotorCheckBoundary checks for violation of boundary conditions and
|
||||
transforms from SoftCoordinates to hard coordinates.
|
||||
*/
|
||||
|
||||
static int MotorCheckBoundaryImpl(pMotor self, float fVal, float *fNew,
|
||||
char *pError, int iErrLen)
|
||||
{
|
||||
float fHard;
|
||||
float fZero;
|
||||
char pBueffel[512];
|
||||
|
||||
assert(self);
|
||||
|
||||
/* check for fixed */
|
||||
if(ObVal(self->ParArray,FIX) >= 0)
|
||||
{
|
||||
sprintf(pBueffel,"Motor %s is Fixed",self->name);
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0; /* is this an error? */
|
||||
}
|
||||
|
||||
/* check against software boundaries */
|
||||
if(fVal > ObVal(self->ParArray,SUPP))
|
||||
{
|
||||
sprintf(pBueffel,"%f violates upper software limit %f on %s",
|
||||
fVal, ObVal(self->ParArray,SUPP),self->name);
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0;
|
||||
}
|
||||
if(fVal < ObVal(self->ParArray,SLOW))
|
||||
{
|
||||
sprintf(pBueffel,"%f violates lower software limit %f on %s",
|
||||
fVal,ObVal(self->ParArray,SLOW),self->name );
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* correct for zero point */
|
||||
fZero = ObVal(self->ParArray,SZERO);
|
||||
fZero = -fZero;
|
||||
fHard = fVal - fZero;
|
||||
|
||||
/* apply sign */
|
||||
fHard = fHard*ObVal(self->ParArray,SIGN);
|
||||
|
||||
/* check for hardware limits */
|
||||
if(fHard > self->pDriver->fUpper)
|
||||
{
|
||||
sprintf(pBueffel,"%f violates upper hardware limit %f on %s",
|
||||
fVal,self->pDriver->fUpper,self->name);
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0;
|
||||
}
|
||||
if(fHard < self->pDriver->fLower)
|
||||
{
|
||||
sprintf(pBueffel,"%f violates lower hardware limit %f on %s",
|
||||
fVal,self->pDriver->fLower,self->name);
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*fNew = fHard;
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int MotorLimits(void *sulf, float fVal, char *error, int iErrLen)
|
||||
{
|
||||
@ -126,8 +194,42 @@
|
||||
|
||||
self = (pMotor)sulf;
|
||||
|
||||
return MotorCheckBoundary(self,fVal,&fHard,error,iErrLen);
|
||||
return MotorCheckBoundaryImpl(self,fVal,&fHard,error,iErrLen);
|
||||
}
|
||||
/* ------------------------------------------------------------------------*/
|
||||
static int MotorGetSoftPositionImpl(pMotor self, SConnection *pCon, float *fVal)
|
||||
{
|
||||
int iRet;
|
||||
float fValue;
|
||||
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
/* get the hard position */
|
||||
iRet = MotorGetHardPosition(self,pCon,&fValue);
|
||||
if(!iRet)
|
||||
{
|
||||
*fVal = fValue;
|
||||
return 0;
|
||||
}
|
||||
/* apply zeropoint */
|
||||
if(ObVal(self->ParArray,SIGN) < 0.)
|
||||
{
|
||||
fValue += ObVal(self->ParArray,SZERO);
|
||||
}
|
||||
else
|
||||
{
|
||||
fValue -= ObVal(self->ParArray,SZERO);
|
||||
}
|
||||
*fVal = fValue;
|
||||
|
||||
/* apply sign */
|
||||
/* *fVal = MotorHardToSoftPosition(self,fValue); */
|
||||
|
||||
*fVal = fValue*ObVal(self->ParArray,SIGN);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static float MotorGetValue(void *pData, SConnection *pCon)
|
||||
{
|
||||
@ -135,7 +237,7 @@
|
||||
float fVal = 0.;
|
||||
|
||||
assert(pData);
|
||||
iRet = MotorGetSoftPosition((pMotor)pData,pCon,&fVal);
|
||||
iRet = MotorGetSoftPositionImpl((pMotor)pData,pCon,&fVal);
|
||||
if(iRet != OKOK)
|
||||
{
|
||||
fVal = -9999999.99;
|
||||
@ -397,143 +499,22 @@ static void handleMoveCallback(pMotor self, SConnection *pCon)
|
||||
return status;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
pMotor MotorInit(char *drivername, char *name, MotorDriver *pDriv)
|
||||
{
|
||||
pMotor pM = NULL;
|
||||
|
||||
assert(drivername);
|
||||
assert(pDriv);
|
||||
assert(name);
|
||||
|
||||
/* get memory */
|
||||
pM = (pMotor)malloc(sizeof(Motor));
|
||||
if(!pM)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* create and initialize parameters */
|
||||
pM->ParArray = ObParCreate(MOTOBPARLENGTH);
|
||||
if(!pM->ParArray)
|
||||
{
|
||||
free(pM);
|
||||
return NULL;
|
||||
}
|
||||
ObParInit(pM->ParArray,SLOW,"softlowerlim",pDriv->fLower,usUser);
|
||||
ObParInit(pM->ParArray,SUPP,"softupperlim",pDriv->fUpper,usUser);
|
||||
ObParInit(pM->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser);
|
||||
ObParInit(pM->ParArray,FIX,"fixed",-1,usUser);
|
||||
ObParInit(pM->ParArray,INT,"interruptmode",INTCONT,usMugger);
|
||||
ObParInit(pM->ParArray,PREC,"precision",0.01,usMugger);
|
||||
ObParInit(pM->ParArray,USRIGHTS,"accesscode",(float)usUser,usMugger);
|
||||
ObParInit(pM->ParArray,SIGN,"sign",1.0,usMugger);
|
||||
ObParInit(pM->ParArray,ECOUNT,"failafter",3.0,usMugger);
|
||||
ObParInit(pM->ParArray,POSCOUNT,"maxretry",3.0,usMugger);
|
||||
ObParInit(pM->ParArray,IGNOREFAULT,"ignorefault",0.0,usMugger);
|
||||
ObParInit(pM->ParArray,MOVECOUNT,"movecount",10.0,usMugger);
|
||||
pDriv->GetPosition(pDriv,&(pM->fPosition));
|
||||
pM->fTarget = pM->fPosition;
|
||||
pM->endScriptID = 0;
|
||||
|
||||
/* copy arguments */
|
||||
pM->pDriver = pDriv;
|
||||
pM->drivername = strdup(drivername);
|
||||
pM->name = strdup(name);
|
||||
|
||||
|
||||
/* initialise object descriptor */
|
||||
pM->pDescriptor = CreateDescriptor("Motor");
|
||||
if(!pM->pDescriptor)
|
||||
{
|
||||
ObParDelete(pM->ParArray);
|
||||
free(pM);
|
||||
return NULL;
|
||||
}
|
||||
pM->pDescriptor->GetInterface = MotorGetInterface;
|
||||
pM->pDescriptor->SaveStatus = MotorSaveStatus;
|
||||
|
||||
/* initialise Drivable interface */
|
||||
pM->pDrivInt = CreateDrivableInterface();
|
||||
if(!pM->pDrivInt)
|
||||
{
|
||||
DeleteDescriptor(pM->pDescriptor);
|
||||
ObParDelete(pM->ParArray);
|
||||
free(pM);
|
||||
return NULL;
|
||||
}
|
||||
pM->pDrivInt->SetValue = MotorRun;
|
||||
pM->pDrivInt->CheckLimits = MotorLimits;
|
||||
pM->pDrivInt->CheckStatus = MotorStatus;
|
||||
pM->pDrivInt->GetValue = MotorGetValue;
|
||||
pM->pDrivInt->Halt = MotorHalt;
|
||||
|
||||
/* initialise callback interface */
|
||||
pM->pCall = CreateCallBackInterface();
|
||||
if(!pM->pCall)
|
||||
{
|
||||
MotorKill(pM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* done */
|
||||
return pM;
|
||||
}
|
||||
int MotorGetPar(pMotor self, char *name, float *fVal)
|
||||
{
|
||||
return self->MotorGetPar(self,name,fVal);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int MotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal)
|
||||
{
|
||||
return self->MotorSetPar(self,pCon,name,fVal);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int MotorGetHardPosition(pMotor self,SConnection *pCon, float *fVal)
|
||||
{
|
||||
return self->MotorGetHardPosition(self, pCon, fVal);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
extern void KillPiPiezo(void *pData);
|
||||
|
||||
void MotorKill(void *self)
|
||||
{
|
||||
pMotor pM;
|
||||
assert(self);
|
||||
|
||||
pM = (pMotor)self;
|
||||
|
||||
/* MotorHalt(pM); */
|
||||
|
||||
if(pM->name)
|
||||
free(pM->name);
|
||||
|
||||
if(pM->pDrivInt)
|
||||
{
|
||||
free(pM->pDrivInt);
|
||||
}
|
||||
|
||||
if(pM->pCall)
|
||||
{
|
||||
DeleteCallBackInterface(pM->pCall);
|
||||
}
|
||||
|
||||
/* kill driver */
|
||||
if(pM->drivername)
|
||||
{
|
||||
if(pM->pDriver->KillPrivate != NULL)
|
||||
{
|
||||
pM->pDriver->KillPrivate(pM->pDriver);
|
||||
if(pM->pDriver->name != NULL)
|
||||
{
|
||||
free(pM->pDriver->name);
|
||||
}
|
||||
free(pM->pDriver);
|
||||
}
|
||||
free(pM->drivername);
|
||||
}
|
||||
|
||||
/* get rid of parameter space */
|
||||
if(pM->ParArray)
|
||||
{
|
||||
ObParDelete(pM->ParArray);
|
||||
}
|
||||
|
||||
/* kill Descriptor */
|
||||
DeleteDescriptor(pM->pDescriptor);
|
||||
|
||||
free(pM);
|
||||
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int MotorGetPar(pMotor self, char *name, float *fVal)
|
||||
static int MotorGetParImpl(pMotor self, char *name, float *fVal)
|
||||
{
|
||||
ObPar *pPar = NULL;
|
||||
assert(self);
|
||||
@ -585,7 +566,7 @@ extern void KillPiPiezo(void *pData);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int MotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal)
|
||||
static int MotorSetParImpl(pMotor self, SConnection *pCon, char *name, float fVal)
|
||||
{
|
||||
ObPar *pPar = NULL;
|
||||
char pBueffel[512];
|
||||
@ -657,73 +638,61 @@ extern void KillPiPiezo(void *pData);
|
||||
|
||||
return iRet;
|
||||
}
|
||||
/*---------------------------------------------------------------------------
|
||||
MotorCheckBoundary checks for violation of boundary conditions and
|
||||
transforms from SoftCoordinates to hard coordinates.
|
||||
*/
|
||||
|
||||
int MotorCheckBoundary(pMotor self, float fVal, float *fNew,
|
||||
char *pError, int iErrLen)
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int MotorGetHardPositionImpl(pMotor self,SConnection *pCon, float *fHard)
|
||||
{
|
||||
float fHard;
|
||||
float fZero;
|
||||
char pBueffel[512];
|
||||
int iRet, iCode;
|
||||
float fVal;
|
||||
char pBueffel[512],pError[256];
|
||||
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
assert(self);
|
||||
|
||||
/* check for fixed */
|
||||
if(ObVal(self->ParArray,FIX) >= 0)
|
||||
iRet = self->pDriver->GetPosition(self->pDriver,&fVal);
|
||||
if(iRet == OKOK) /* all went well, the exception */
|
||||
{
|
||||
sprintf(pBueffel,"Motor %s is Fixed",self->name);
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0; /* is this an error? */
|
||||
*fHard = fVal;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* check against software boundaries */
|
||||
if(fVal > ObVal(self->ParArray,SUPP))
|
||||
{
|
||||
sprintf(pBueffel,"%f violates upper software limit %f on %s",
|
||||
fVal, ObVal(self->ParArray,SUPP),self->name);
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0;
|
||||
else /* a problem, the usual case: try fix the problem */
|
||||
{ /* no point in trying this three times */
|
||||
self->pDriver->GetError(self->pDriver,&iCode, pError,255);
|
||||
iRet = self->pDriver->TryAndFixIt(self->pDriver,iCode, fVal);
|
||||
sprintf(pBueffel,"WARNING: Trying to fix %s",pError);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
switch(iRet)
|
||||
{
|
||||
case MOTFAIL:
|
||||
sprintf(pBueffel,"ERROR: cannot fix motor %s",
|
||||
self->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT));
|
||||
*fHard = fVal;
|
||||
return 0;
|
||||
case MOTOK:
|
||||
case MOTREDO:
|
||||
iRet = self->pDriver->GetPosition(self->pDriver,&fVal);
|
||||
if(iRet)
|
||||
{
|
||||
*fHard = fVal*ObVal(self->ParArray,SIGN);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot fix motor %s",
|
||||
self->name);
|
||||
SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT));
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
*fHard = fVal;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(fVal < ObVal(self->ParArray,SLOW))
|
||||
{
|
||||
sprintf(pBueffel,"%f violates lower software limit %f on %s",
|
||||
fVal,ObVal(self->ParArray,SLOW),self->name );
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* correct for zero point */
|
||||
fZero = ObVal(self->ParArray,SZERO);
|
||||
fZero = -fZero;
|
||||
fHard = fVal - fZero;
|
||||
|
||||
/* apply sign */
|
||||
fHard = fHard*ObVal(self->ParArray,SIGN);
|
||||
|
||||
/* check for hardware limits */
|
||||
if(fHard > self->pDriver->fUpper)
|
||||
{
|
||||
sprintf(pBueffel,"%f violates upper hardware limit %f on %s",
|
||||
fVal,self->pDriver->fUpper,self->name);
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0;
|
||||
}
|
||||
if(fHard < self->pDriver->fLower)
|
||||
{
|
||||
sprintf(pBueffel,"%f violates lower hardware limit %f on %s",
|
||||
fVal,self->pDriver->fLower,self->name);
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*fNew = fHard;
|
||||
return 1;
|
||||
}
|
||||
*fHard = fVal*ObVal(self->ParArray,SIGN);
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
long MotorRun(void *sulf, SConnection *pCon, float fNew)
|
||||
static long MotorRunImpl(void *sulf, SConnection *pCon, float fNew)
|
||||
{
|
||||
float fHard;
|
||||
int i, iRet, iCode;
|
||||
@ -748,7 +717,7 @@ extern void KillPiPiezo(void *pData);
|
||||
}
|
||||
|
||||
/* check boundaries first */
|
||||
iRet = MotorCheckBoundary(self,fNew,&fHard,pError,131);
|
||||
iRet = MotorCheckBoundaryImpl(self,fNew,&fHard,pError,131);
|
||||
if(!iRet)
|
||||
{
|
||||
snprintf(pBueffel,511,"ERROR: %s",pError);
|
||||
@ -824,59 +793,171 @@ extern void KillPiPiezo(void *pData);
|
||||
}
|
||||
return OKOK;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int MotorGetHardPosition(pMotor self,SConnection *pCon, float *fHard)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
pMotor MotorInit(char *drivername, char *name, MotorDriver *pDriv)
|
||||
{
|
||||
int iRet, iCode;
|
||||
float fVal;
|
||||
char pBueffel[512],pError[256];
|
||||
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
iRet = self->pDriver->GetPosition(self->pDriver,&fVal);
|
||||
if(iRet == OKOK) /* all went well, the exception */
|
||||
pMotor pM = NULL;
|
||||
|
||||
assert(drivername);
|
||||
assert(pDriv);
|
||||
assert(name);
|
||||
|
||||
/* get memory */
|
||||
pM = (pMotor)malloc(sizeof(Motor));
|
||||
if(!pM)
|
||||
{
|
||||
*fHard = fVal;
|
||||
return 1;
|
||||
return NULL;
|
||||
}
|
||||
else /* a problem, the usual case: try fix the problem */
|
||||
{ /* no point in trying this three times */
|
||||
self->pDriver->GetError(self->pDriver,&iCode, pError,255);
|
||||
iRet = self->pDriver->TryAndFixIt(self->pDriver,iCode, fVal);
|
||||
sprintf(pBueffel,"WARNING: Trying to fix %s",pError);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
switch(iRet)
|
||||
|
||||
|
||||
/* create and initialize parameters */
|
||||
pM->ParArray = ObParCreate(MOTOBPARLENGTH);
|
||||
if(!pM->ParArray)
|
||||
{
|
||||
free(pM);
|
||||
return NULL;
|
||||
}
|
||||
ObParInit(pM->ParArray,SLOW,"softlowerlim",pDriv->fLower,usUser);
|
||||
ObParInit(pM->ParArray,SUPP,"softupperlim",pDriv->fUpper,usUser);
|
||||
ObParInit(pM->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser);
|
||||
ObParInit(pM->ParArray,FIX,"fixed",-1,usUser);
|
||||
ObParInit(pM->ParArray,INT,"interruptmode",INTCONT,usMugger);
|
||||
ObParInit(pM->ParArray,PREC,"precision",0.01,usMugger);
|
||||
ObParInit(pM->ParArray,USRIGHTS,"accesscode",(float)usUser,usMugger);
|
||||
ObParInit(pM->ParArray,SIGN,"sign",1.0,usMugger);
|
||||
ObParInit(pM->ParArray,ECOUNT,"failafter",3.0,usMugger);
|
||||
ObParInit(pM->ParArray,POSCOUNT,"maxretry",3.0,usMugger);
|
||||
ObParInit(pM->ParArray,IGNOREFAULT,"ignorefault",0.0,usMugger);
|
||||
ObParInit(pM->ParArray,MOVECOUNT,"movecount",10.0,usMugger);
|
||||
pDriv->GetPosition(pDriv,&(pM->fPosition));
|
||||
pM->fTarget = pM->fPosition;
|
||||
pM->endScriptID = 0;
|
||||
|
||||
/* copy arguments */
|
||||
pM->pDriver = pDriv;
|
||||
pM->drivername = strdup(drivername);
|
||||
pM->name = strdup(name);
|
||||
|
||||
|
||||
/* initialise object descriptor */
|
||||
pM->pDescriptor = CreateDescriptor("Motor");
|
||||
if(!pM->pDescriptor)
|
||||
{
|
||||
ObParDelete(pM->ParArray);
|
||||
free(pM);
|
||||
return NULL;
|
||||
}
|
||||
pM->pDescriptor->GetInterface = MotorGetInterface;
|
||||
pM->pDescriptor->SaveStatus = MotorSaveStatus;
|
||||
|
||||
/* initialise Drivable interface */
|
||||
pM->pDrivInt = CreateDrivableInterface();
|
||||
if(!pM->pDrivInt)
|
||||
{
|
||||
DeleteDescriptor(pM->pDescriptor);
|
||||
ObParDelete(pM->ParArray);
|
||||
free(pM);
|
||||
return NULL;
|
||||
}
|
||||
pM->pDrivInt->SetValue = MotorRunImpl;
|
||||
pM->pDrivInt->CheckLimits = MotorLimits;
|
||||
pM->pDrivInt->CheckStatus = MotorStatus;
|
||||
pM->pDrivInt->GetValue = MotorGetValue;
|
||||
pM->pDrivInt->Halt = MotorHalt;
|
||||
|
||||
/* initialize function pointers */
|
||||
pM->MotorGetPar = MotorGetParImpl;
|
||||
pM->MotorSetPar = MotorSetParImpl;
|
||||
pM->MotorGetHardPosition = MotorGetHardPositionImpl;
|
||||
|
||||
/* initialise callback interface */
|
||||
pM->pCall = CreateCallBackInterface();
|
||||
if(!pM->pCall)
|
||||
{
|
||||
MotorKill(pM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* done */
|
||||
return pM;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
long MotorRun(void *data, SConnection *pCon, float fNew)
|
||||
{
|
||||
pMotor self = (pMotor)data;
|
||||
|
||||
return self->pDrivInt->SetValue(data,pCon,fNew);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int MotorCheckBoundary(pMotor self, float fVal, float *fHard,
|
||||
char *error, int iErrLen)
|
||||
{
|
||||
return self->pDrivInt->CheckLimits(self,fVal,error,iErrLen);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int MotorGetSoftPosition(pMotor self,SConnection *pCon, float *fVal)
|
||||
{
|
||||
float myVal;
|
||||
myVal = self->pDrivInt->GetValue(self,pCon);
|
||||
*fVal = myVal;
|
||||
if(myVal <= -9999999.99){
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
extern void KillPiPiezo(void *pData);
|
||||
|
||||
void MotorKill(void *self)
|
||||
{
|
||||
pMotor pM;
|
||||
assert(self);
|
||||
|
||||
pM = (pMotor)self;
|
||||
|
||||
/* MotorHalt(pM); */
|
||||
|
||||
if(pM->name)
|
||||
free(pM->name);
|
||||
|
||||
if(pM->pDrivInt)
|
||||
{
|
||||
free(pM->pDrivInt);
|
||||
}
|
||||
|
||||
if(pM->pCall)
|
||||
{
|
||||
DeleteCallBackInterface(pM->pCall);
|
||||
}
|
||||
|
||||
/* kill driver */
|
||||
if(pM->drivername)
|
||||
{
|
||||
if(pM->pDriver->KillPrivate != NULL)
|
||||
{
|
||||
case MOTFAIL:
|
||||
sprintf(pBueffel,"ERROR: cannot fix motor %s",
|
||||
self->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT));
|
||||
*fHard = fVal;
|
||||
return 0;
|
||||
case MOTOK:
|
||||
case MOTREDO:
|
||||
iRet = self->pDriver->GetPosition(self->pDriver,&fVal);
|
||||
if(iRet)
|
||||
{
|
||||
*fHard = fVal*ObVal(self->ParArray,SIGN);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: cannot fix motor %s",
|
||||
self->name);
|
||||
SCSetInterrupt(pCon,(int)ObVal(self->ParArray,INT));
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
*fHard = fVal;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
*fHard = fVal*ObVal(self->ParArray,SIGN);
|
||||
return 0;
|
||||
}
|
||||
pM->pDriver->KillPrivate(pM->pDriver);
|
||||
if(pM->pDriver->name != NULL)
|
||||
{
|
||||
free(pM->pDriver->name);
|
||||
}
|
||||
free(pM->pDriver);
|
||||
}
|
||||
free(pM->drivername);
|
||||
}
|
||||
|
||||
/* get rid of parameter space */
|
||||
if(pM->ParArray)
|
||||
{
|
||||
ObParDelete(pM->ParArray);
|
||||
}
|
||||
|
||||
/* kill Descriptor */
|
||||
DeleteDescriptor(pM->pDescriptor);
|
||||
|
||||
free(pM);
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
float MotorHardToSoftPosition(pMotor self, float fValue)
|
||||
{
|
||||
@ -892,40 +973,6 @@ extern void KillPiPiezo(void *pData);
|
||||
/* apply sign */
|
||||
return fValue*ObVal(self->ParArray,SIGN);
|
||||
}
|
||||
/* ------------------------------------------------------------------------*/
|
||||
int MotorGetSoftPosition(pMotor self, SConnection *pCon, float *fVal)
|
||||
{
|
||||
int iRet;
|
||||
float fValue;
|
||||
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
/* get the hard position */
|
||||
iRet = MotorGetHardPosition(self,pCon,&fValue);
|
||||
if(!iRet)
|
||||
{
|
||||
*fVal = fValue;
|
||||
return 0;
|
||||
}
|
||||
/* apply zeropoint */
|
||||
if(ObVal(self->ParArray,SIGN) < 0.)
|
||||
{
|
||||
fValue += ObVal(self->ParArray,SZERO);
|
||||
}
|
||||
else
|
||||
{
|
||||
fValue -= ObVal(self->ParArray,SZERO);
|
||||
}
|
||||
*fVal = fValue;
|
||||
|
||||
/* apply sign */
|
||||
/* *fVal = MotorHardToSoftPosition(self,fValue); */
|
||||
|
||||
*fVal = fValue*ObVal(self->ParArray,SIGN);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int MotorCheckPosition(void *sulf, SConnection *pCon)
|
||||
{
|
||||
@ -1079,9 +1126,9 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
||||
sprintf(pBueffel,"Parameter Listing for motor %s",self->name);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
sprintf(pBueffel,"%s.Position = %f\n", self->name,self->fPosition);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
sprintf(pBueffel,"%s.TargetPosition = %f\n", self->name,self->fTarget);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
|
||||
snprintf(pBueffel,511,"%s.hardlowerlim = %f",self->name,
|
||||
self->pDriver->fLower);
|
||||
@ -1093,7 +1140,7 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
||||
{
|
||||
sprintf(pBueffel,"%s.%s = %f\n",self->name,
|
||||
self->ParArray[i].name,self->ParArray[i].fVal);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1129,11 +1176,14 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
||||
{
|
||||
free(self->pName);
|
||||
}
|
||||
if(self->pCon != NULL)
|
||||
{
|
||||
SCDeleteConnection(self->pCon);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*------------------- The CallBack function for interest ------------------*/
|
||||
static int InterestCallback(int iEvent, void *pEvent, void *pUser,
|
||||
commandContext cc)
|
||||
static int InterestCallback(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
pMotInfo pInfo = NULL;
|
||||
char pBueffel[80];
|
||||
@ -1145,11 +1195,15 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
||||
psCall = (MotCallback *)pEvent;
|
||||
pInfo = (MotInfo *)pUser;
|
||||
|
||||
if(!SCisConnected(pInfo->pCon)){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pInfo->lastValue != psCall->fVal) {
|
||||
pInfo->lastValue = psCall->fVal;
|
||||
(pInfo->pCon)->conEventType=POSITION;
|
||||
sprintf(pBueffel,"%s.position = %f ", pInfo->pName, pInfo->lastValue);
|
||||
SCWriteInContext(pInfo->pCon,pBueffel,eEvent,cc);
|
||||
SCWrite(pInfo->pCon,pBueffel,eEvent);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -1162,8 +1216,7 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
||||
}
|
||||
}
|
||||
/*------------------------ The endscript callback function ----------------*/
|
||||
static int EndScriptCallback(int iEvent, void *pEvent, void *pUser,
|
||||
commandContext cc)
|
||||
static int EndScriptCallback(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
char *pScript = NULL;
|
||||
MotCallback *psCall;
|
||||
@ -1269,7 +1322,7 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
||||
return 0;
|
||||
}
|
||||
pMoti->pName = strdup(argv[0]);
|
||||
pMoti->pCon = pCon;
|
||||
pMoti->pCon = SCCopyConnection(pCon);
|
||||
iRet = MotorGetSoftPosition(self,pCon,&fValue);
|
||||
if(!iRet)
|
||||
{
|
||||
@ -1280,16 +1333,15 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
||||
}
|
||||
pMoti->lastValue = fValue;
|
||||
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),MOTDRIVE, InterestCallback,
|
||||
lID = RegisterCallback(self->pCall, MOTDRIVE, InterestCallback,
|
||||
pMoti, KillInfo);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
DeleteTokenList(pList);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
else if(strcmp(pCurrent->text,"uninterest") == 0)
|
||||
{
|
||||
RemoveCallback2(self->pCall,pCon);
|
||||
RemoveCallbackCon(self->pCall,pCon);
|
||||
SCSendOK(pCon);
|
||||
DeleteTokenList(pList);
|
||||
return 1;
|
||||
@ -1312,9 +1364,8 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
||||
return 0;
|
||||
}
|
||||
self->endScriptID =
|
||||
RegisterCallback(self->pCall, SCGetContext(pCon),MOTEND, EndScriptCallback,
|
||||
RegisterCallback(self->pCall, MOTEND, EndScriptCallback,
|
||||
strdup(pCurrent->text), KillScript);
|
||||
SCRegister(pCon,pSics, self->pCall,self->endScriptID);
|
||||
DeleteTokenList(pList);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
|
14
motor.h
14
motor.h
@ -13,13 +13,17 @@
|
||||
#include "modriv.h"
|
||||
#include "obdes.h"
|
||||
#include "interface.h"
|
||||
#include "hipadaba.h"
|
||||
|
||||
#define MOTOBPARLENGTH 12
|
||||
typedef struct __Motor {
|
||||
pObjectDescriptor pDescriptor;
|
||||
ObPar *ParArray;
|
||||
pObjectDescriptor pDescriptor;
|
||||
pHdb objectNode;
|
||||
pIDrivable pDrivInt;
|
||||
pICallBack pCall;
|
||||
int (*MotorSetPar)(struct __Motor *self, SConnection *pCon, char *name, float fVal);
|
||||
int (*MotorGetPar)(struct __Motor *self, char *name, float *fVal);
|
||||
int (*MotorGetHardPosition)(struct __Motor *self, SConnection *pCon, float *fVal);
|
||||
char *drivername;
|
||||
char *name;
|
||||
MotorDriver *pDriver;
|
||||
@ -31,6 +35,10 @@
|
||||
int retryCount; /* for retries in status */
|
||||
int posFaultCount;
|
||||
int stopped;
|
||||
int errorCount;
|
||||
ObPar *ParArray;
|
||||
void *pPrivate;
|
||||
void (*KillPrivate)(void *);
|
||||
} Motor;
|
||||
typedef Motor *pMotor;
|
||||
/*------------------------------------------------------------------------
|
||||
@ -50,12 +58,10 @@ typedef struct {
|
||||
long MotorRun(void *self, SConnection *pCon, float fNew);
|
||||
int MotorCheckBoundary(pMotor self, float fVal, float *fHard,
|
||||
char *error, int iErrLen);
|
||||
int MotorCheckPosition(void *self, SConnection *pCon);
|
||||
|
||||
/* Where are we ? */
|
||||
int MotorGetSoftPosition(pMotor self,SConnection *pCon, float *fVal);
|
||||
int MotorGetHardPosition(pMotor self,SConnection *pCon, float *fVal);
|
||||
float MotorHardToSoftPosition(pMotor self, float fHard);
|
||||
|
||||
/* creation */
|
||||
int MotorCreate(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
|
749
motorsec.c
Normal file
749
motorsec.c
Normal file
@ -0,0 +1,749 @@
|
||||
/**
|
||||
* This is the implementation of a second generation motor. A second
|
||||
* generation motor differs in various aspects from a first generation
|
||||
* motor though it is functionally equivalent and even adheres to the
|
||||
* same interface. The differing aspects are:
|
||||
* - The second generation motor deos not use the ObPar array for parameter storage
|
||||
* but the Hipadaba parameter system rooted in self->pDes->objectNode.
|
||||
* - The second generation motor does not use the driver. The second generation motor
|
||||
* implements some functionality but is largely a shell. Scripts are supposed to add
|
||||
* more parameters and link to a corresponding ScriptContext object which takes care
|
||||
* of actual talking to the hardware.
|
||||
* - The old callback system is also not implemented: third parties which are interested
|
||||
* to be notified of changes to the motor position shall register a callback.
|
||||
*
|
||||
* This also means that many of the fields in the motor data structure are not used in
|
||||
* this module but are present to support first generation motors. This must be so as we cannot
|
||||
* replace all existing driver with new ones quickly. Here a list of fields which have no use:
|
||||
* - pDriver
|
||||
* - ParArray
|
||||
*
|
||||
* We need three different position parameters to keep this under control:
|
||||
* - the physical value which is the main motor node
|
||||
* - the targetposition which is is the hardware target where the motor is supposed
|
||||
* to be
|
||||
* - The hardposition which is the actual hardware position. This is also the
|
||||
* one which is responsible for talking to the motor.
|
||||
*
|
||||
* Then we need a status parameter which is some text which says what the motor
|
||||
* is up to.
|
||||
*
|
||||
* A less obvious use of a callback is the HardUpdateCallback. It automatically
|
||||
* updates the physical motor position, too.
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, December 2008
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "sics.h"
|
||||
#include "sicshipadaba.h"
|
||||
#include "sicsobj.h"
|
||||
#include "motor.h"
|
||||
#include "splitter.h"
|
||||
|
||||
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int SecMotorGetPar(pMotor self, char *name, float *fVal){
|
||||
char pBueffel[512];
|
||||
hdbValue value;;
|
||||
int status;
|
||||
|
||||
snprintf(pBueffel,511,"%s ", name);
|
||||
status = SICSHdbGetPar(self,NULL,pBueffel, &value);
|
||||
*fVal = (float)value.v.doubleValue;
|
||||
return status;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int SecMotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal){
|
||||
int status;
|
||||
hdbValue value;
|
||||
value = MakeHdbFloat(fVal);
|
||||
status = SICSHdbSetPar(self,
|
||||
pCon,name,value);
|
||||
if(status == 1){
|
||||
SCparChange(pCon);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void *MotorGetInterfaceSec(void *pData, int iID){
|
||||
pMotor self = NULL;
|
||||
|
||||
self = (pMotor)pData;
|
||||
assert(self);
|
||||
if(iID == DRIVEID){
|
||||
return self->pDrivInt;
|
||||
} else if(iID == CALLBACKINTERFACE) {
|
||||
return self->pCall;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static long SecMotorRun(void *sulf, SConnection *pCon, float fNew){
|
||||
pMotor self = (pMotor)sulf;
|
||||
hdbValue v;
|
||||
|
||||
v = MakeHdbFloat(fNew);
|
||||
return SetHipadabaPar(self->pDescriptor->parNode,v,pCon);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int SecMotorCheckBoundary(pMotor self, float fVal, float *fTarget,
|
||||
char *pError, int iErrLen){
|
||||
double fZero, fixed, lowerlim, upperlim, sign;
|
||||
float fHard, hupper, hlower;
|
||||
char pBueffel[512];
|
||||
hdbValue v;
|
||||
|
||||
assert(self);
|
||||
|
||||
assert(SICSHdbGetPar(self,NULL,
|
||||
"fixed",&v) == 1);
|
||||
fixed = v.v.doubleValue;
|
||||
assert(SICSHdbGetPar(self,NULL,
|
||||
"softzero",&v) == 1);
|
||||
fZero = v.v.doubleValue;
|
||||
assert(SICSHdbGetPar(self,NULL,
|
||||
"softlowerlim",&v) == 1);
|
||||
lowerlim = v.v.doubleValue;
|
||||
assert(SICSHdbGetPar(self,NULL,
|
||||
"softupperlim",&v) == 1);
|
||||
upperlim = v.v.doubleValue;
|
||||
assert(SICSHdbGetPar(self,NULL,
|
||||
"sign",&v) == 1);
|
||||
sign = v.v.doubleValue;
|
||||
|
||||
*fTarget = fVal;
|
||||
|
||||
/* check for fixed */
|
||||
if(fixed >= 0){
|
||||
sprintf(pBueffel,"Motor %s is Fixed",self->name);
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0; /* is this an error? */
|
||||
}
|
||||
|
||||
/* check against software boundaries */
|
||||
if(fVal > upperlim){
|
||||
sprintf(pBueffel,"%f violates upper software limit %f on %s",
|
||||
fVal, upperlim,self->name);
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0;
|
||||
}
|
||||
if(fVal < lowerlim){
|
||||
sprintf(pBueffel,"%f violates lower software limit %f on %s",
|
||||
fVal,lowerlim,self->name );
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* correct for zero point */
|
||||
fZero = -fZero;
|
||||
fHard = fVal - fZero;
|
||||
|
||||
/* apply sign */
|
||||
fHard = fHard*sign;
|
||||
|
||||
|
||||
/* check for hardware limits */
|
||||
SecMotorGetPar(self,"hardlowerlim",&hlower);
|
||||
SecMotorGetPar(self,"hardupperlim",&hupper);
|
||||
if(fHard > hupper){
|
||||
sprintf(pBueffel,"%f violates upper hardware limit %f on %s",
|
||||
fVal,hupper,self->name);
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0;
|
||||
}
|
||||
if(fHard < hlower){
|
||||
sprintf(pBueffel,"%f violates lower hardware limit %f on %s",
|
||||
fVal,hlower,self->name);
|
||||
strncpy(pError,pBueffel,iErrLen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*fTarget = fHard;
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int SecMotorLimits(void *sulf, float fVal, char *error, int iErrLen){
|
||||
float fHard;
|
||||
pMotor self;
|
||||
|
||||
assert(sulf);
|
||||
|
||||
self = (pMotor)sulf;
|
||||
|
||||
return SecMotorCheckBoundary(self,fVal,&fHard,error,iErrLen);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int checkPosition(pMotor self, SConnection *pCon){
|
||||
float precision, hard, target, maxretry;
|
||||
pHdb node = NULL;
|
||||
|
||||
if(SCGetInterrupt(pCon) != eContinue){
|
||||
return HWFault;
|
||||
}
|
||||
if(self->stopped){
|
||||
SCPrintf(pCon,eWarning,"WARNING: %s stopped", self->name);
|
||||
return HWFault;
|
||||
}
|
||||
SecMotorGetPar(self,"hardposition",&hard);
|
||||
SecMotorGetPar(self,"targetposition",&target);
|
||||
SecMotorGetPar(self,"precision",&precision);
|
||||
SecMotorGetPar(self,"maxretry",&maxretry);
|
||||
if(ABS(target-hard) > precision){
|
||||
if(self->retryCount >= (int)maxretry){
|
||||
SCPrintf(pCon,eError,
|
||||
"ERROR: Aborting %s after %d retries, off position by %f",
|
||||
self->name, (int)maxretry, target - hard);
|
||||
return HWFault;
|
||||
}
|
||||
self->retryCount++;
|
||||
SCPrintf(pCon,eWarning,"WARNING: %s off position by %f, restarting",
|
||||
self->name, target-hard);
|
||||
node = GetHipadabaNode(self->pDescriptor->parNode,"status");
|
||||
assert(node != NULL);
|
||||
UpdateHipadabaPar(node,MakeHdbText("run"), pCon);
|
||||
node = GetHipadabaNode(self->pDescriptor->parNode,"hardposition");
|
||||
assert(node != NULL);
|
||||
SetHipadabaPar(node,MakeHdbFloat(target), pCon);
|
||||
return HWBusy;
|
||||
}
|
||||
return HWIdle;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static void handleMoveCallback(pMotor self, SConnection *pCon){
|
||||
float movecount;
|
||||
pHdb node = NULL;
|
||||
hdbValue v;
|
||||
|
||||
SecMotorGetPar(self,"movecount",&movecount);
|
||||
self->posCount++;
|
||||
if(self->posCount > (int)movecount){
|
||||
node = GetHipadabaNode(self->pDescriptor->parNode,"hardposition");
|
||||
GetHipadabaPar(node,&v,pCon);
|
||||
UpdateHipadabaPar(node,v,pCon);
|
||||
self->posCount = 0;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int SecMotorStatus(void *sulf, SConnection *pCon){
|
||||
pMotor self = NULL;
|
||||
int status;
|
||||
pHdb node = NULL;
|
||||
hdbValue v;
|
||||
float interrupt;
|
||||
|
||||
assert(sulf);
|
||||
self = (pMotor)sulf;
|
||||
|
||||
node = GetHipadabaNode(self->pDescriptor->parNode,"status");
|
||||
assert(node != NULL);
|
||||
status = GetHipadabaPar(node,&v,pCon);
|
||||
|
||||
if(status != 1){
|
||||
return HWFault;
|
||||
}
|
||||
|
||||
if(v.v.text == NULL){
|
||||
return HWBusy;
|
||||
}
|
||||
if(strstr(v.v.text,"idle") != NULL){
|
||||
status = checkPosition(self,pCon);
|
||||
} else if(strstr(v.v.text,"run") != NULL){
|
||||
handleMoveCallback(self,pCon);
|
||||
status = HWBusy;
|
||||
} else if(strstr(v.v.text,"poserror") != NULL){
|
||||
status = checkPosition(self,pCon);
|
||||
} else if(strstr(v.v.text,"error") != NULL){
|
||||
status = HWFault;
|
||||
} else {
|
||||
SCPrintf(pCon,eError,"ERROR: unknown motor status %s found", v.v.text);
|
||||
status = HWFault;
|
||||
}
|
||||
/*
|
||||
* when terminating: force an update of the position.
|
||||
*/
|
||||
switch(status){
|
||||
case HWFault:
|
||||
self->posCount = 10000;
|
||||
handleMoveCallback(self,pCon);
|
||||
SecMotorGetPar(self,"interrupt",&interrupt);
|
||||
if(SCGetInterrupt(pCon) < (int)interrupt){
|
||||
SCSetInterrupt(pCon,(int)interrupt);
|
||||
}
|
||||
self->errorCount++;
|
||||
break;
|
||||
case HWIdle:
|
||||
self->posCount = 10000;
|
||||
handleMoveCallback(self,pCon);
|
||||
self->errorCount = 0;
|
||||
break;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static float SecMotorGetValue(void *pData, SConnection *pCon){
|
||||
int status;
|
||||
pMotor self = (pMotor)pData;
|
||||
hdbValue v;
|
||||
|
||||
assert(pData);
|
||||
status = GetHipadabaPar(self->pDescriptor->parNode, &v,pCon);
|
||||
if(status != 1){
|
||||
return -9999999.99;
|
||||
} else {
|
||||
return (float)v.v.doubleValue;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int SecMotorHalt(void *sulf){
|
||||
pMotor self;
|
||||
pHdb node = NULL, par[0];
|
||||
SICSOBJFunc haltFunc = NULL;
|
||||
int status;
|
||||
|
||||
assert(sulf);
|
||||
self = (pMotor)sulf;
|
||||
|
||||
node = GetHipadabaNode(self->pDescriptor->parNode,"halt");
|
||||
assert(node != NULL);
|
||||
|
||||
haltFunc = (SICSOBJFunc)node->value.v.func;
|
||||
assert(haltFunc != NULL);
|
||||
self->stopped = 1;
|
||||
return haltFunc((pSICSOBJ)self,pServ->dummyCon,node,par,0);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int SecMotorGetHardPosition(struct __Motor *self,
|
||||
SConnection *pCon, float *fVal){
|
||||
hdbValue v;
|
||||
int status;
|
||||
pHdb node = NULL;
|
||||
|
||||
node = GetHipadabaNode(self->pDescriptor->parNode,"hardposition");
|
||||
assert(node != NULL);
|
||||
status = GetHipadabaPar(node,&v,pCon);
|
||||
*fVal = (float)v.v.doubleValue;
|
||||
return status;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void AddMotorPar(pHdb node, int priv, char *name){
|
||||
pHdb child = NULL;
|
||||
|
||||
child = MakeSICSHdbPar(name,priv,MakeHdbFloat(.0));
|
||||
if(child != NULL){
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static float hardToSoftPosition(pMotor self, float hard){
|
||||
float sign, zero, fVal;
|
||||
|
||||
SecMotorGetPar(self,"sign", &sign);
|
||||
SecMotorGetPar(self,"softzero", &zero);
|
||||
fVal = hard;
|
||||
if(sign < 0){
|
||||
fVal += zero;
|
||||
} else {
|
||||
fVal -= zero;
|
||||
}
|
||||
fVal *= sign;
|
||||
return fVal;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData,
|
||||
pHdbMessage message){
|
||||
SConnection *pCon = NULL;
|
||||
pHdbDataMessage mm = NULL;
|
||||
hdbValue v;
|
||||
pHdb child = NULL;
|
||||
pMotor self = NULL;
|
||||
float fHard, fVal, sign, zero;
|
||||
char pBueffel[512], pError[132];
|
||||
int status;
|
||||
|
||||
self = (pMotor)userData;
|
||||
assert(self != NULL);
|
||||
|
||||
mm = GetHdbSetMessage(message);
|
||||
if(mm != NULL){
|
||||
pCon = (SConnection *)mm->callData;
|
||||
v = *(mm->v);
|
||||
|
||||
/*
|
||||
* check permission
|
||||
*/
|
||||
SecMotorGetPar(self,"accesscode",&fVal);
|
||||
if(!SCMatchRights(pCon,(int)fVal)){
|
||||
sprintf(pBueffel,"ERROR: You are not authorised to move motor %s",
|
||||
self->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
SCSetInterrupt(pCon,eAbortBatch);
|
||||
return hdbAbort;
|
||||
}
|
||||
|
||||
/*
|
||||
* check limits
|
||||
*/
|
||||
status = SecMotorCheckBoundary(self,(float)v.v.doubleValue,
|
||||
&fHard,pError,131);
|
||||
if(status != 1){
|
||||
snprintf(pBueffel,511,"ERROR: %s",pError);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
SCSetInterrupt(pCon,eAbortOperation);
|
||||
return hdbAbort;
|
||||
}
|
||||
|
||||
/*
|
||||
* check the motor bad flag
|
||||
*/
|
||||
SecMotorGetPar(self,"ignorefault",&fVal);
|
||||
if((int)fVal > 0){
|
||||
snprintf(pBueffel,511,"WARNING: motor %s is unreliable",
|
||||
self->name);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
self->errorCount = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* check for alarm condition
|
||||
*/
|
||||
SecMotorGetPar(self,"failafter",&fVal);
|
||||
if(self->errorCount > (int)fVal){
|
||||
/* big alarm */
|
||||
ServerWriteGlobal("ERROR: !!! MOTOR ALARM !!! MOTOR ALARM !!!",eError);
|
||||
sprintf(pBueffel,
|
||||
"ERROR: too many position errors counted at motor %s",
|
||||
self->name);
|
||||
ServerWriteGlobal(pBueffel,eError);
|
||||
SCSetInterrupt(pCon,eAbortBatch);
|
||||
self->errorCount = 0;
|
||||
return hdbAbort;
|
||||
}
|
||||
|
||||
self->posFaultCount = 0;
|
||||
self->retryCount = 0;
|
||||
self->stopped = 0;
|
||||
self->posCount = 0;
|
||||
child = GetHipadabaNode(self->pDescriptor->parNode,"targetposition");
|
||||
UpdateHipadabaPar(child,MakeHdbFloat(fHard),pCon);
|
||||
child = GetHipadabaNode(self->pDescriptor->parNode,"status");
|
||||
UpdateHipadabaPar(child,MakeHdbText("run"), pCon);
|
||||
child = GetHipadabaNode(self->pDescriptor->parNode,"hardposition");
|
||||
SetHipadabaPar(child,MakeHdbFloat(fHard), pCon);
|
||||
|
||||
return hdbContinue;
|
||||
}
|
||||
|
||||
mm = GetHdbGetMessage(message);
|
||||
if(mm != NULL){
|
||||
pCon = (SConnection *)mm->callData;
|
||||
SecMotorGetPar(self,"hardposition", &fVal);
|
||||
fVal = hardToSoftPosition(self,fVal);
|
||||
node->value.v.doubleValue = fVal;
|
||||
mm->v->v.doubleValue = fVal;
|
||||
return hdbContinue;
|
||||
}
|
||||
|
||||
return hdbContinue;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static hdbCallbackReturn HardUpdateCallback(pHdb node, void *userData,
|
||||
pHdbMessage message){
|
||||
pHdbDataMessage mm = NULL;
|
||||
pMotor self = (pMotor)userData;
|
||||
float fVal;
|
||||
hdbValue v;
|
||||
|
||||
assert(self != NULL);
|
||||
|
||||
mm = GetHdbUpdateMessage(message);
|
||||
if(mm != NULL){
|
||||
v = *mm->v;
|
||||
fVal = hardToSoftPosition(self,(float)v.v.doubleValue);
|
||||
v.v.doubleValue = fVal;
|
||||
UpdateHipadabaPar(self->pDescriptor->parNode, v, mm->callData);
|
||||
return hdbContinue;
|
||||
}
|
||||
return hdbContinue;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static hdbCallbackReturn SecMotorSignCallback(pHdb node, void *userData,
|
||||
pHdbMessage message){
|
||||
pMotor self = NULL;
|
||||
SConnection *pCon = NULL;
|
||||
pHdb zero = NULL;
|
||||
double value;
|
||||
pHdbDataMessage mm = NULL;
|
||||
float limit;
|
||||
hdbValue v;
|
||||
|
||||
self = (pMotor)userData;
|
||||
|
||||
mm = GetHdbSetMessage(message);
|
||||
if(mm != NULL){
|
||||
pCon = (SConnection *)mm->callData;
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
return hdbAbort;
|
||||
}
|
||||
v = *mm->v;
|
||||
if(ABS(v.v.doubleValue) - 1. > .01){
|
||||
if(pCon!= NULL){
|
||||
SCWrite(pCon,"ERROR: invalid sign value",eError);
|
||||
return hdbAbort;
|
||||
}
|
||||
}
|
||||
SecMotorGetPar(self,"softlowerlim",&limit);
|
||||
limit *= v.v.doubleValue;
|
||||
SecMotorSetPar(self,pCon,"softlowerlim",limit);
|
||||
SecMotorGetPar(self,"softupperlim",&limit);
|
||||
limit *= v.v.doubleValue;
|
||||
SecMotorSetPar(self,pCon,"softupperlim",limit);
|
||||
SecMotorSetPar(self,pCon,"softzero",.0);
|
||||
UpdateHipadabaPar(node,v,pCon);
|
||||
return hdbContinue;
|
||||
}
|
||||
return hdbContinue;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static hdbCallbackReturn SecMotorZeroCallback(pHdb node, void *userData,
|
||||
pHdbMessage message){
|
||||
pMotor self = NULL;
|
||||
float limit, oldZero, diff;
|
||||
SConnection *pCon = NULL;
|
||||
pHdbDataMessage mm = NULL;
|
||||
hdbValue v;
|
||||
|
||||
self = (pMotor)userData;
|
||||
assert(self != NULL);
|
||||
|
||||
mm = GetHdbSetMessage(message);
|
||||
if(mm != NULL){
|
||||
pCon = (SConnection *)mm->callData;
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return hdbAbort;
|
||||
}
|
||||
v = *mm->v;
|
||||
SecMotorGetPar(self,"softzero", &oldZero);
|
||||
diff = v.v.doubleValue - oldZero;
|
||||
|
||||
SecMotorGetPar(self,"softupperlim",&limit);
|
||||
limit -= diff;
|
||||
SecMotorSetPar(self,pCon,"softupperlim",limit);
|
||||
|
||||
SecMotorGetPar(self,"softlowerlim",&limit);
|
||||
limit -= diff;
|
||||
SecMotorSetPar(self,pCon,"softlowerlim",limit);
|
||||
UpdateHipadabaPar(node,v,pCon);
|
||||
return hdbContinue;
|
||||
}
|
||||
return hdbContinue;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
pMotor SecMotorInit(char *name){
|
||||
pMotor pM = NULL;
|
||||
pHdb node = NULL, child = NULL;
|
||||
hdbValue v;
|
||||
|
||||
assert(name);
|
||||
|
||||
/* get memory */
|
||||
pM = (pMotor)malloc(sizeof(Motor));
|
||||
if(!pM){
|
||||
return NULL;
|
||||
}
|
||||
memset(pM,0,sizeof(Motor));
|
||||
|
||||
/* initialise object descriptor */
|
||||
pM->pDescriptor = CreateDescriptor("Motor");
|
||||
if(!pM->pDescriptor){
|
||||
free(pM);
|
||||
return NULL;
|
||||
}
|
||||
pM->pDescriptor->GetInterface = MotorGetInterfaceSec;
|
||||
pM->pDescriptor->SaveStatus = SaveSICSOBJ;
|
||||
pM->pDescriptor->parNode = MakeSICSHdbPar(name,usSpy,MakeHdbFloat(.0));
|
||||
if(pM->pDescriptor->parNode == NULL){
|
||||
free(pM);
|
||||
return NULL;
|
||||
}
|
||||
node = pM->pDescriptor->parNode;
|
||||
pM->objectNode = node;
|
||||
AppendHipadabaCallback(pM->pDescriptor->parNode,
|
||||
MakeHipadabaCallback(SecMotorCallback,pM,NULL));
|
||||
|
||||
/* copy arguments */
|
||||
pM->name = strdup(name);
|
||||
|
||||
/*
|
||||
* install parameters
|
||||
*/
|
||||
child = MakeSICSHdbPar("targetposition",usInternal,MakeHdbFloat(.0));
|
||||
if(child == NULL){
|
||||
return(NULL);
|
||||
}
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
child = MakeHipadabaNode("hardposition",HIPFLOAT,1);
|
||||
if(child == NULL){
|
||||
return(NULL);
|
||||
}
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
SetHdbProperty(child,"motname", name);
|
||||
AppendHipadabaCallback(child,
|
||||
MakeHipadabaCallback(HardUpdateCallback,pM,NULL));
|
||||
|
||||
child = MakeHipadabaNode("sign",HIPFLOAT, 1);
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
AppendHipadabaCallback(child,
|
||||
MakeHipadabaCallback(SecMotorSignCallback,pM,NULL));
|
||||
UpdateHipadabaPar(child,MakeHdbFloat(1.),NULL);
|
||||
|
||||
child = MakeHipadabaNode("softzero",HIPFLOAT, 1);
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
AppendHipadabaCallback(child,
|
||||
MakeHipadabaCallback(SecMotorZeroCallback,pM,NULL));
|
||||
|
||||
child = MakeHipadabaNode("hardlowerlim",HIPFLOAT, 1);
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
child = MakeHipadabaNode("hardupperlim",HIPFLOAT, 1);
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
child = MakeSICSHdbPar("softlowerlim",usUser,
|
||||
MakeHdbFloat(.0));
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
child = MakeSICSHdbPar("softupperlim",usUser,
|
||||
MakeHdbFloat(.0));
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
child = MakeSICSHdbPar("fixed",usUser,
|
||||
MakeHdbFloat(-1.));
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
child = MakeSICSHdbPar("interruptmode",usMugger,
|
||||
MakeHdbFloat(.0));
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
child = MakeSICSHdbPar("precision",usMugger,
|
||||
MakeHdbFloat(.1));
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
child = MakeSICSHdbPar("accesscode",usMugger,
|
||||
MakeHdbFloat((double)usUser));
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
child = MakeSICSHdbPar("failafter",usMugger,
|
||||
MakeHdbFloat((double)3.0));
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
child = MakeSICSHdbPar("maxretry",usMugger,
|
||||
MakeHdbFloat((double)3.0));
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
child = MakeSICSHdbPar("ignorefault",usMugger,
|
||||
MakeHdbFloat((double).0));
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
child = MakeSICSHdbPar("movecount",usMugger,
|
||||
MakeHdbFloat((double)10.0));
|
||||
SetHdbProperty(child,"__save", "true");
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
child = MakeHipadabaNode("status",HIPTEXT,1);
|
||||
SetHdbProperty(child,"motname", name);
|
||||
AddHipadabaChild(node,child,NULL);
|
||||
|
||||
pM->endScriptID = 0;
|
||||
|
||||
/* initialise Drivable interface */
|
||||
pM->pDrivInt = CreateDrivableInterface();
|
||||
if(!pM->pDrivInt){
|
||||
DeleteDescriptor(pM->pDescriptor);
|
||||
free(pM);
|
||||
return NULL;
|
||||
}
|
||||
pM->pDrivInt->SetValue = SecMotorRun;
|
||||
pM->pDrivInt->CheckLimits = SecMotorLimits;
|
||||
pM->pDrivInt->CheckStatus = SecMotorStatus;
|
||||
pM->pDrivInt->GetValue = SecMotorGetValue;
|
||||
pM->pDrivInt->Halt = SecMotorHalt;
|
||||
|
||||
/*
|
||||
* initialize motor function pointers
|
||||
*/
|
||||
pM->MotorGetPar = SecMotorGetPar;
|
||||
pM->MotorSetPar = SecMotorSetPar;
|
||||
pM->MotorGetHardPosition = SecMotorGetHardPosition;
|
||||
|
||||
/* initialise callback interface */
|
||||
pM->pCall = CreateCallBackInterface();
|
||||
if(!pM->pCall){
|
||||
MotorKill(pM);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* done */
|
||||
return pM;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static void SecMotorKill(void *data){
|
||||
pMotor self = (pMotor)data;
|
||||
if(self == NULL){
|
||||
return;
|
||||
}
|
||||
if(self->name)
|
||||
free(self->name);
|
||||
|
||||
if(self->pDrivInt){
|
||||
free(self->pDrivInt);
|
||||
}
|
||||
|
||||
if(self->pCall){
|
||||
DeleteCallBackInterface(self->pCall);
|
||||
}
|
||||
|
||||
/* kill Descriptor */
|
||||
DeleteDescriptor(self->pDescriptor);
|
||||
|
||||
free(self);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int SecMotorFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pMotor pNew = NULL;
|
||||
|
||||
if(argc < 2){
|
||||
SCWrite(pCon,"ERROR: need name for new motor", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pNew = SecMotorInit(argv[1]);
|
||||
if(pNew == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating motor", eError);
|
||||
return 0;
|
||||
}
|
||||
return AddCommand(pSics,argv[1],InterInvokeSICSOBJ,
|
||||
SecMotorKill,pNew);
|
||||
|
||||
}
|
14
motorsec.h
Normal file
14
motorsec.h
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* This is the header file for the second generation motor object.
|
||||
* More details in the header of the implementation file.
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, December 2008
|
||||
*/
|
||||
#ifndef MOTORSEC_H_
|
||||
#define MOTORSEC_H_
|
||||
int SecMotorFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
#endif /*MOTORSEC_H_*/
|
@ -59,9 +59,11 @@ static int MMCCHalt(void *pData){
|
||||
|
||||
for(i = 0; i < self->nSlaves; i++){
|
||||
status = self->slaves[i]->Halt(self->slaveData[i]);
|
||||
ReleaseCountLock(self->slaves[i]);
|
||||
if(status != OKOK)
|
||||
retVal = status;
|
||||
}
|
||||
ReleaseCountLock(pCount->pCountInt);
|
||||
return retVal;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -77,9 +79,14 @@ static int MMCCStart(void *pData, SConnection *pCon)
|
||||
}
|
||||
assert(self);
|
||||
|
||||
if(!GetCountLock(pCount->pCountInt, pCon)){
|
||||
return HWFault;
|
||||
}
|
||||
|
||||
for(i = 0; i < self->nSlaves; i++){
|
||||
self->slaves[i]->SetCountParameters(self->slaveData[i],
|
||||
pCount->pDriv->fPreset, pCount->pDriv->eMode);
|
||||
ReleaseCountLock(self->slaves[i]);
|
||||
status = self->slaves[i]->StartCount(self->slaveData[i],pCon);
|
||||
if(status != OKOK){
|
||||
MMCCHalt(pData);
|
||||
|
21
nintf.c
21
nintf.c
@ -3,6 +3,8 @@
|
||||
is an implementation.
|
||||
|
||||
Mark Koennecke, February 2000
|
||||
|
||||
Added double version, Mark Koennecke, August 2008
|
||||
---------------------------------------------------------------------------*/
|
||||
|
||||
#include <math.h>
|
||||
@ -24,3 +26,22 @@
|
||||
}
|
||||
return (float) ip;
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
double nintd(double f)
|
||||
{
|
||||
double ip, rm, dVal;
|
||||
double fRes;
|
||||
|
||||
dVal = (double)f;
|
||||
rm = modf(dVal,&ip);
|
||||
if(rm < .0)rm = -rm;
|
||||
if(rm > .5)
|
||||
{
|
||||
if(ip < .0)
|
||||
ip -= 1.;
|
||||
else
|
||||
ip += 1.;
|
||||
|
||||
}
|
||||
return (double) ip;
|
||||
}
|
||||
|
392
nread.c
392
nread.c
@ -10,7 +10,7 @@
|
||||
Telnet Functionality added: Mark Koennecke, January 1998
|
||||
|
||||
Revamped login to non telnet connection.
|
||||
Mark Koennecke, October 20000
|
||||
Mark Koennecke, October 2000
|
||||
|
||||
-----------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
@ -67,6 +67,7 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
int iReadTimeout;
|
||||
int iEnd;
|
||||
long lMagic;
|
||||
pDynString conList;
|
||||
} NetReader;
|
||||
/*---------------------------------------------------------------------------
|
||||
The structure used for an item in the Net Reader list of connections
|
||||
@ -97,7 +98,8 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
memset(pNew,0,sizeof(NetReader));
|
||||
|
||||
pNew->iList = LLDcreate(sizeof(NetItem));
|
||||
if(pNew->iList < 0)
|
||||
pNew->conList = CreateDynString(1024,1024);
|
||||
if(pNew->iList < 0 || pNew->conList == NULL)
|
||||
{
|
||||
free(pNew);
|
||||
return NULL;
|
||||
@ -121,6 +123,10 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
}
|
||||
|
||||
LLDdelete(self->iList);
|
||||
if(self->conList != NULL)
|
||||
{
|
||||
DeleteDynString(self->conList);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -208,10 +214,12 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
if(pNew)
|
||||
{
|
||||
/* create connection object */
|
||||
/* TODO
|
||||
pRes = SCreateConnection(self->pMain->pSics,pNew,3);
|
||||
*/
|
||||
if(!pRes)
|
||||
{
|
||||
SICSLogWrite("Failure to allocate new Connection",eInternal);
|
||||
SICSLogWrite("Failure to allocate new Connection",eInternal);
|
||||
NETClosePort(pNew);
|
||||
free(pNew);
|
||||
return 0;
|
||||
@ -370,7 +378,9 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
if(pNew)
|
||||
{
|
||||
/* create connection object */
|
||||
/* TODO
|
||||
pRes = SCreateConnection(self->pMain->pSics,pNew,usSpy);
|
||||
*/
|
||||
if(!pRes)
|
||||
{
|
||||
SICSLogWrite("Failure to allocate new Connection",eInternal);
|
||||
@ -706,9 +716,6 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
int conCount = 0;
|
||||
char num[50];
|
||||
IPair *options = NULL;
|
||||
char buffer[1024];
|
||||
int bufferLen;
|
||||
static int bufferFull=0;
|
||||
|
||||
self = (pNetRead)pData;
|
||||
assert(self);
|
||||
@ -723,12 +730,13 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
return 0;
|
||||
}
|
||||
|
||||
ANETprocess();
|
||||
|
||||
/* build the select mask */
|
||||
FD_ZERO(&lMask);
|
||||
iRet = LLDnodePtr2First(self->iList);
|
||||
iCount = 0;
|
||||
buffer[0] = '\0';
|
||||
bufferLen = 0;
|
||||
DynStringClear(self->conList);
|
||||
while(iRet != 0)
|
||||
{
|
||||
LLDnodeDataTo(self->iList,&NItem);
|
||||
@ -736,14 +744,10 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
{
|
||||
break;
|
||||
}
|
||||
snprintf(num,sizeof num, "%d, type %d:", NItem.pSock->sockid, NItem.eType);
|
||||
if (bufferLen + strlen(num) < sizeof buffer) {
|
||||
strcpy(buffer + bufferLen, num);
|
||||
bufferLen += strlen(num);
|
||||
} else {
|
||||
if (bufferFull == 0) {
|
||||
bufferFull = 1;
|
||||
}
|
||||
|
||||
sprintf(num,"%d, type %d:", NItem.pSock->sockid, NItem.eType);
|
||||
if(conCount < 100){
|
||||
DynStringConcat(self->conList,num);
|
||||
}
|
||||
FD_SET(NItem.pSock->sockid,&lMask);
|
||||
if(NItem.pSock->sockid > iCount)
|
||||
@ -751,17 +755,20 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
iCount = NItem.pSock->sockid;
|
||||
}
|
||||
conCount++;
|
||||
if(conCount > 100){
|
||||
WriteToCommandLog("WAYTOMANYCONNECTIONS> ", GetCharArray(self->conList));
|
||||
}
|
||||
iRet = LLDnodePtr2Next(self->iList);
|
||||
}
|
||||
|
||||
if(conCount > 100){
|
||||
WriteToCommandLog("WAYTOMANYCONNECTIONS> ", GetCharArray(self->conList));
|
||||
}
|
||||
|
||||
snprintf(num,sizeof num,"%d", conCount);
|
||||
IFSetOption(pSICSOptions,"ConnectionCount",num);
|
||||
IFSetOption(pSICSOptions,"ConMask",buffer);
|
||||
IFSetOption(pSICSOptions,"ConMask",GetCharArray(self->conList));
|
||||
|
||||
if (bufferFull == 1) {
|
||||
bufferFull = 2;
|
||||
WriteToCommandLog("BUFFERFULL>",buffer);
|
||||
}
|
||||
|
||||
/* the select itself */
|
||||
tmo.tv_usec = self->iReadTimeout;
|
||||
@ -1072,5 +1079,348 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*===================================================================================
|
||||
* new code to support the ANET network stuff
|
||||
* =================================================================================*/
|
||||
typedef struct {
|
||||
pDynString command;
|
||||
int state;
|
||||
SConnection *pCon;
|
||||
}CommandCBData, *pCommandCBData;
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
static void killCommandCBData(void *data){
|
||||
pCommandCBData self = (pCommandCBData)data;
|
||||
if(self == NULL){
|
||||
return;
|
||||
}
|
||||
if(self->command != NULL){
|
||||
DeleteDynString(self->command);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
static int testAndInvokeInterrupt(pCommandCBData self, int handle){
|
||||
char *pPtr;
|
||||
char buffer[512];
|
||||
int iInt;
|
||||
|
||||
pPtr = GetCharArray(self->command);
|
||||
if(strstr(pPtr,"INT1712") != NULL){
|
||||
sscanf(pPtr, "%s %d",buffer, &iInt);
|
||||
if(SCMatchRights(self->pCon,usUser)) {
|
||||
TaskSignal(pServ->pTasker, SICSINT, &iInt);
|
||||
snprintf(buffer,512, "INTERRUPT %d issued on sock %d",
|
||||
iInt,handle);
|
||||
WriteToCommandLog("SYS>", buffer);
|
||||
if(iInt == eEndServer){
|
||||
TaskStop(pServ->pTasker);
|
||||
}
|
||||
} else {
|
||||
SCWrite(self->pCon,
|
||||
"ERROR: insufficient privilege to invoke Interrupt",
|
||||
eError);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
static int CommandDataCB(int handle, void *userData){
|
||||
pCommandCBData self = (pCommandCBData)userData;
|
||||
int i, length, status;
|
||||
char *pPtr = NULL;
|
||||
|
||||
assert(self != NULL);
|
||||
pPtr = ANETreadPtr(handle,&length);
|
||||
if(pPtr == NULL){
|
||||
return 1;
|
||||
}
|
||||
for(i = 0; i < length; i++){
|
||||
switch(self->state){
|
||||
case COLLECT:
|
||||
if(pPtr[i] == '\r' || pPtr[i] == '\n'){
|
||||
self->state = SKIPTERM;
|
||||
if(!testAndInvokeInterrupt(self,handle)){
|
||||
status = CostaTop(self->pCon->pStack, GetCharArray(self->command));
|
||||
if(!status){
|
||||
SCWrite(self->pCon,"ERROR: Busy", eError);
|
||||
}
|
||||
}
|
||||
DynStringClear(self->command);
|
||||
} else {
|
||||
if(pPtr[i] != '\0'){
|
||||
DynStringConcatChar(self->command, pPtr[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SKIPTERM:
|
||||
if(pPtr[i] != '\r' && pPtr[i] != '\n' && pPtr[i] != '\0'){
|
||||
DynStringConcatChar(self->command, pPtr[i]);
|
||||
self->state = COLLECT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
ANETreadConsume(handle, length);
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
static int CommandAcceptCB(int handle, void *userData){
|
||||
SConnection *pCon = NULL;
|
||||
pCommandCBData usData = NULL;
|
||||
|
||||
pCon = SCreateConnection(pServ->pSics, handle, 3);
|
||||
usData = malloc(sizeof(CommandCBData));
|
||||
if(pCon == NULL || usData == NULL){
|
||||
SICSLogWrite("Failure to allocate new Connection",eInternal);
|
||||
return 0;
|
||||
}
|
||||
usData->command = CreateDynString(256,256);
|
||||
if(usData->command == NULL){
|
||||
SICSLogWrite("Failure to allocate new Connection",eInternal);
|
||||
return 0;
|
||||
}
|
||||
usData->pCon = pCon;
|
||||
usData->state = COLLECT;
|
||||
TaskRegister(pServ->pTasker,
|
||||
SCTaskFunction,
|
||||
SCSignalFunction,
|
||||
SCDeleteConnection,
|
||||
pCon,
|
||||
1);
|
||||
ANETsetReadCallback(handle, CommandDataCB,
|
||||
usData, killCommandCBData);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int ANETTelnetReply(int sockHandle, char code, char cChar)
|
||||
{
|
||||
char pReply[3];
|
||||
|
||||
pReply[0] = IAC;
|
||||
pReply[1] = code;
|
||||
pReply[2] = cChar;
|
||||
|
||||
ANETwrite(sockHandle,pReply,3);
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int ANETTelnetProcess(int handle, void *usData){
|
||||
pCommandCBData self = NULL;
|
||||
int length, status, i;
|
||||
int cChar;
|
||||
char *pPtr = NULL;
|
||||
char pError[256];
|
||||
|
||||
self = (pCommandCBData)usData;
|
||||
assert(self != NULL);
|
||||
|
||||
pPtr = ANETreadPtr(handle,&length);
|
||||
|
||||
/* do telnet analysis of the data buffer */
|
||||
for(i = 0; i < length; i++){
|
||||
cChar = (int)pPtr[i];
|
||||
#ifdef TELNETDEBUG
|
||||
if( (cChar > 48) && (cChar < 128) ){
|
||||
printf("char: %c\n",cChar);
|
||||
} else {
|
||||
printf("Control: %d\n",cChar);
|
||||
}
|
||||
#endif
|
||||
/* Telnet status switching */
|
||||
switch(self->state){
|
||||
case tData:
|
||||
switch(cChar){
|
||||
case IAC:
|
||||
self->state = tIAC;
|
||||
break;
|
||||
case '\r':
|
||||
case '\n':
|
||||
if(!testAndInvokeInterrupt(self,handle)){
|
||||
status = CostaTop(self->pCon->pStack, GetCharArray(self->command));
|
||||
if(!status){
|
||||
SCWrite(self->pCon,"ERROR: Busy", eError);
|
||||
}
|
||||
}
|
||||
self->state = tCR;
|
||||
DynStringClear(self->command);
|
||||
break;
|
||||
case (char)8: /* backspace */
|
||||
DynStringBackspace(self->command);
|
||||
break;
|
||||
case (char)0:/* ignore 0 character sent as end of text */
|
||||
break;
|
||||
default:
|
||||
DynStringConcatChar(self->command,(char)cChar);
|
||||
break;
|
||||
|
||||
} /* end of tData case */
|
||||
break;
|
||||
case tCR:
|
||||
if(cChar == '\r' || cChar == '\n' || cChar == '\0'){
|
||||
continue;
|
||||
} else {
|
||||
self->state = tData;
|
||||
DynStringConcatChar(self->command,(char)cChar);
|
||||
}
|
||||
break;
|
||||
case tIAC:
|
||||
switch(cChar)
|
||||
{
|
||||
case IAC:
|
||||
self->state = tData;
|
||||
break;
|
||||
case WILL:
|
||||
self->state = tWill;
|
||||
break;
|
||||
case WONT:
|
||||
self->state = tWont;
|
||||
break;
|
||||
case DONT:
|
||||
self->state = tDont;
|
||||
break;
|
||||
case DO:
|
||||
self->state = tDo;
|
||||
break;
|
||||
case EOR:
|
||||
self->state = tData;
|
||||
break;
|
||||
case SB:
|
||||
self->state = tSB;
|
||||
break;
|
||||
case EC:
|
||||
DynStringBackspace(self->command);
|
||||
self->state = tData;
|
||||
break;
|
||||
case EL:
|
||||
DynStringClear(self->command);
|
||||
self->state = tData;
|
||||
break;
|
||||
case IP:
|
||||
SCSetInterrupt(self->pCon,eAbortBatch);
|
||||
self->state = tData;
|
||||
break;
|
||||
default:
|
||||
self->state = tData;
|
||||
break;
|
||||
} /* end of tIAC */
|
||||
break;
|
||||
case tWill: /* we do not do options! */
|
||||
ANETTelnetReply(handle,DONT,cChar);
|
||||
self->state = tData;
|
||||
break;
|
||||
case tWont: /* we do not do options! A Wont is sent by the client
|
||||
if it cannot do a option we requested it to have. As
|
||||
we do not try to force options, this should not happen
|
||||
*/
|
||||
self->state = tData;
|
||||
break;
|
||||
case tDo: /* we do not do options! */
|
||||
ANETTelnetReply(handle,WONT,cChar);
|
||||
self->state = tData;
|
||||
break;
|
||||
case tDont: /* we do not do options! A Dont is sent by the client
|
||||
if it cannot do a option we requested it to have. As
|
||||
we do not try to force options, this should not happen
|
||||
*/
|
||||
self->state = tData;
|
||||
break;
|
||||
case tSB: /* as we do not have options, we cannot have suboption
|
||||
negotaitions. Something is seriously wrong when
|
||||
we are here. It is a protocoll error. However, we
|
||||
ignore it silently. tSB marks the start of the
|
||||
subnegotiation. The current character must be the
|
||||
option code we are dealing with.
|
||||
*/
|
||||
self->state = tSE;
|
||||
break;
|
||||
case tSE:
|
||||
/* now we are in the suboption parameter. Normally data
|
||||
should be copied to a suboption string buffer here
|
||||
until SE.
|
||||
*/
|
||||
switch(cChar)
|
||||
{
|
||||
case IAC:
|
||||
break;
|
||||
case SE:
|
||||
self->state = tData;
|
||||
/* suboption interpretation would go here */
|
||||
break;
|
||||
default:
|
||||
/* copy data to suboption buffer */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* There is something wrong here! */
|
||||
sprintf(pError,"ERROR: bad telnet code %d", cChar);
|
||||
SICSLogWrite(pError,eInternal);
|
||||
self->state = tData;
|
||||
break;
|
||||
|
||||
} /* end master swicth */
|
||||
} /* end for loop */
|
||||
ANETreadConsume(handle,length);
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
static int TelnetAcceptCB(int handle, void *userData){
|
||||
SConnection *pCon = NULL;
|
||||
pCommandCBData usData = NULL;
|
||||
pTelTask pTel = NULL;
|
||||
|
||||
pCon = SCreateConnection(pServ->pSics, handle, 3);
|
||||
usData = malloc(sizeof(CommandCBData));
|
||||
if(pCon == NULL || usData == NULL){
|
||||
SICSLogWrite("Failure to allocate new Connection",eInternal);
|
||||
return 0;
|
||||
}
|
||||
usData->command = CreateDynString(256,256);
|
||||
if(usData->command == NULL){
|
||||
SICSLogWrite("Failure to allocate new Connection",eInternal);
|
||||
return 0;
|
||||
}
|
||||
usData->pCon = pCon;
|
||||
usData->state = tData;
|
||||
/* Create a task object for the telnet connection */
|
||||
pTel = CreateTelnet(pCon);
|
||||
if(!pTel){
|
||||
SICSLogWrite("Failure to allocate new Telnet Task Object",
|
||||
eInternal);
|
||||
SCDeleteConnection(pCon);
|
||||
return 0;
|
||||
}
|
||||
/* register connection and task */
|
||||
pCon->iTelnet = 1;
|
||||
TaskRegister(pServ->pTasker,
|
||||
TelnetTask,
|
||||
TelnetSignal,
|
||||
DeleteTelnet,
|
||||
pTel,
|
||||
1);
|
||||
ANETsetReadCallback(handle, ANETTelnetProcess,
|
||||
usData, killCommandCBData);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
static void NREADlog(int level, char *txt, void *userData){
|
||||
puts(txt);
|
||||
}
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort){
|
||||
ANETsetLog(NREADlog,NULL);
|
||||
switch(eType){
|
||||
case naccept:
|
||||
return ANETopenServerPort(iPort,CommandAcceptCB,NULL);
|
||||
break;
|
||||
case taccept:
|
||||
return ANETopenServerPort(iPort,TelnetAcceptCB,NULL);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
2
nread.h
2
nread.h
@ -32,5 +32,7 @@
|
||||
int NetReadWait4Data(pNetRead self, int iSocket);
|
||||
int NetReadReadable(pNetRead self, int iSocket);
|
||||
int NetReadResetUser(pNetRead self, int iSocket);
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort);
|
||||
|
||||
#endif
|
||||
|
19
nread.tex
19
nread.tex
@ -11,11 +11,11 @@ through a command channel
|
||||
A prior
|
||||
version of SICS had a select system call for each of these cases. It was
|
||||
found, that the code spent most of its time in the select system call
|
||||
thus intrdoducing a major performance problem.
|
||||
thus introducing a major performance problem.
|
||||
|
||||
The select system call can handle more then one file descriptor in one call.
|
||||
This is exactly what this module handles. It does a global select on
|
||||
all open sockets and forwards any pending data to approriate handlers.
|
||||
all open sockets and forwards any pending data to appropriate handlers.
|
||||
This scheme brought a drastic
|
||||
performance improvement.
|
||||
|
||||
@ -25,13 +25,13 @@ differently:
|
||||
A connection request will be validated, a new connection object will be
|
||||
created and a new task for this connection object will be started.
|
||||
|
||||
A command will be placed in the apropriate command stack for the task
|
||||
A command will be placed in the appropriate command stack for the task
|
||||
belonging to this connection to work on in a later stage. The netreader will
|
||||
also take care that all commands are complete, this is the terminator
|
||||
\verb+\n+ or \verb+\r+ has been sent.
|
||||
|
||||
Both forms of interrupt will be interpreted and a suitable signal
|
||||
will be sent to all runing tasks if the interrupt request is valid.
|
||||
will be sent to all running tasks if the interrupt request is valid.
|
||||
|
||||
In order to perform his tasks the network reader needs to maintain a list of
|
||||
all open sockets and their types. Additionally it needs to know about the
|
||||
@ -61,6 +61,11 @@ come in on a user socket. This function is problematic with dynamically
|
||||
creates and deleted objects such as environment device objects. Its use is
|
||||
therefore no longer recommended.
|
||||
|
||||
In January 2009 a new asynchronous I/O structure was devised. This makes most of
|
||||
NetReader obsolete. However, it was decided to keep the old structure for the
|
||||
time being. A new function, NetReadInstallANETPort was added to install server
|
||||
ports for the new system.
|
||||
|
||||
Thus the interface looks like this:
|
||||
|
||||
\begin{flushleft} \small
|
||||
@ -88,7 +93,9 @@ $\langle$nrint {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ int NetReadWait4Data(pNetRead self, int iSocket);@\\
|
||||
\mbox{}\verb@ int NetReadReadable(pNetRead self, int iSocket);@\\
|
||||
\mbox{}\verb@ int NetReadResetUser(pNetRead self, int iSocket);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort); @\\
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
@ -153,7 +160,7 @@ if not.
|
||||
\mbox{}\verb@#define SICSNETREADER@\\
|
||||
\mbox{}\verb@@$\langle$nrint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
|
15
nread.w
15
nread.w
@ -11,11 +11,11 @@ through a command channel
|
||||
A prior
|
||||
version of SICS had a select system call for each of these cases. It was
|
||||
found, that the code spent most of its time in the select system call
|
||||
thus intrdoducing a major performance problem.
|
||||
thus introducing a major performance problem.
|
||||
|
||||
The select system call can handle more then one file descriptor in one call.
|
||||
This is exactly what this module handles. It does a global select on
|
||||
all open sockets and forwards any pending data to approriate handlers.
|
||||
all open sockets and forwards any pending data to appropriate handlers.
|
||||
This scheme brought a drastic
|
||||
performance improvement.
|
||||
|
||||
@ -25,13 +25,13 @@ differently:
|
||||
A connection request will be validated, a new connection object will be
|
||||
created and a new task for this connection object will be started.
|
||||
|
||||
A command will be placed in the apropriate command stack for the task
|
||||
A command will be placed in the appropriate command stack for the task
|
||||
belonging to this connection to work on in a later stage. The netreader will
|
||||
also take care that all commands are complete, this is the terminator
|
||||
\verb+\n+ or \verb+\r+ has been sent.
|
||||
|
||||
Both forms of interrupt will be interpreted and a suitable signal
|
||||
will be sent to all runing tasks if the interrupt request is valid.
|
||||
will be sent to all running tasks if the interrupt request is valid.
|
||||
|
||||
In order to perform his tasks the network reader needs to maintain a list of
|
||||
all open sockets and their types. Additionally it needs to know about the
|
||||
@ -61,6 +61,11 @@ come in on a user socket. This function is problematic with dynamically
|
||||
creates and deleted objects such as environment device objects. Its use is
|
||||
therefore no longer recommended.
|
||||
|
||||
In January 2009 a new asynchronous I/O structure was devised. This makes most of
|
||||
NetReader obsolete. However, it was decided to keep the old structure for the
|
||||
time being. A new function, NetReadInstallANETPort was added to install server
|
||||
ports for the new system.
|
||||
|
||||
Thus the interface looks like this:
|
||||
|
||||
@d nrint @{
|
||||
@ -83,6 +88,8 @@ Thus the interface looks like this:
|
||||
int NetReadWait4Data(pNetRead self, int iSocket);
|
||||
int NetReadReadable(pNetRead self, int iSocket);
|
||||
int NetReadResetUser(pNetRead self, int iSocket);
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int NetReadInstallANETPort(pNetRead self, eNRType eType, int iPort);
|
||||
@}
|
||||
|
||||
This starts off with the definition of a data type for the net reader and an
|
||||
|
@ -213,6 +213,7 @@
|
||||
IFDeleteOptions(pSICSOptions);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
self->pServerPort = NETOpenPort(iPort);
|
||||
if(!self->pServerPort)
|
||||
{
|
||||
@ -222,7 +223,9 @@
|
||||
return 0;
|
||||
}
|
||||
NetReadRegister(pReader, self->pServerPort, naccept, NULL);
|
||||
|
||||
*/
|
||||
NetReadInstallANETPort(pReader,naccept, iPort);
|
||||
|
||||
/* the device executor */
|
||||
openDevexecLog();
|
||||
DevexecLog("START","SICS");
|
||||
@ -273,7 +276,7 @@
|
||||
|
||||
/* install telnet port */
|
||||
InstallTelnet();
|
||||
|
||||
|
||||
/* If the restore file has not been loaded, do so now */
|
||||
if(!hasRestored())
|
||||
{
|
||||
|
370
nxscript.c
370
nxscript.c
@ -8,6 +8,7 @@
|
||||
|
||||
Mark Koennecke, February 2003
|
||||
Mark Koennecke, January 2004
|
||||
added putHdb and putHdbSlab, Mark Koennecke, December 2008
|
||||
------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
@ -30,6 +31,7 @@
|
||||
#include "nxdict.h"
|
||||
#include "nxscript.h"
|
||||
#include "sicsdata.h"
|
||||
#include "sicshipadaba.h"
|
||||
|
||||
extern char *trim(char *str);
|
||||
|
||||
@ -96,7 +98,7 @@ char *makeFilename(SicsInterp *pSics, SConnection *pCon) {
|
||||
if(dir == NULL){
|
||||
mkdir(pRes,S_IRWXU | S_IRGRP | S_IXGRP);
|
||||
snprintf(pBueffel,255,"Creating dir: %s", pRes);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
} else {
|
||||
closedir(dir);
|
||||
}
|
||||
@ -126,6 +128,28 @@ void changeExtension(char *filename, char *newExtension){
|
||||
assert(strlen(pPtr) >= strlen(newExtension));
|
||||
strcpy(pPtr,newExtension);
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int listToArray(SicsInterp *pSics, char *list,
|
||||
int intar[NX_MAXRANK]){
|
||||
int argc, status, i, val;
|
||||
CONST char **argv;
|
||||
Tcl_Interp *pTcl = InterpGetTcl(pSics);
|
||||
|
||||
status = Tcl_SplitList(pTcl, list, &argc, &argv);
|
||||
if(status != TCL_OK){
|
||||
return status;
|
||||
}
|
||||
|
||||
for(i = 0; i < argc; i++){
|
||||
status = Tcl_GetInt(pTcl,argv[i],&val);
|
||||
if(status != TCL_OK){
|
||||
return status;
|
||||
}
|
||||
intar[i] = val;
|
||||
}
|
||||
Tcl_Free((char *)argv);
|
||||
return TCL_OK;
|
||||
}
|
||||
/*======================== Action =======================================*/
|
||||
static int handleFileOperations(SConnection *pCon, pNXScript self,
|
||||
int argc, char *argv[]){
|
||||
@ -209,7 +233,7 @@ static void putMotor(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
|
||||
if(argc < 4){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to putmotor",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -219,7 +243,7 @@ static void putMotor(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
brumm = (pMotor)FindCommandData(pSics,argv[3],"Motor");
|
||||
if(!brumm){
|
||||
sprintf(buffer,"ERROR: motor %s not found!", argv[3]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -229,14 +253,14 @@ static void putMotor(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
status = MotorGetSoftPosition(brumm, pCon,&fVal);
|
||||
if(!status){
|
||||
sprintf(buffer,"ERROR: failed to read position of %s", argv[3]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
status = NXDputalias(self->fileHandle,self->dictHandle,argv[2],&fVal);
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write %s with alias %s",
|
||||
argv[3],argv[2]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -251,7 +275,7 @@ static void putMotor(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write %s zero with alias %s",
|
||||
argv[3],argv[2]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -268,7 +292,7 @@ static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
|
||||
if(argc < 4){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to putcounter",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
memset(dummy,0,80*sizeof(char));
|
||||
@ -279,7 +303,7 @@ static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
cter = (pCounter)FindCommandData(pSics,argv[3],"SingleCounter");
|
||||
if(!cter){
|
||||
sprintf(buffer,"ERROR: counter %s not found!", argv[3]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -292,7 +316,7 @@ static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,&fVal);
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write preset to %s", newAlias);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -309,7 +333,7 @@ static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,dummy);
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write counter mode to %s", newAlias);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -322,7 +346,7 @@ static void putCounter(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
status = NXDputalias(self->fileHandle,self->dictHandle,newAlias,&fVal);
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write count time to %s", newAlias);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
}
|
||||
|
||||
@ -352,7 +376,7 @@ static void putSicsData(SConnection *pCon, SicsInterp *pSics,
|
||||
|
||||
if(argc < 4){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to putSicsData",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -362,14 +386,14 @@ static void putSicsData(SConnection *pCon, SicsInterp *pSics,
|
||||
data = (pSICSData)FindCommandData(pSics,argv[3],"SICSData");
|
||||
if(data == NULL){
|
||||
snprintf(buffer,255,"ERROR: sicsdata %s not found!", argv[3]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
status = NXDputalias(self->fileHandle,self->dictHandle,argv[2],data->data);
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write sicsdata to %s", argv[2]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
@ -380,25 +404,177 @@ static void putAttribute(SConnection *pCon, SicsInterp *pSics,
|
||||
|
||||
if(argc < 5){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to putAttribute",
|
||||
eError);
|
||||
eLogError);
|
||||
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);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
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);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
NXopenpath(self->fileHandle,"/");
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void putHdb(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
int argc, char *argv[]){
|
||||
pHdb node = NULL;
|
||||
char alias[512];
|
||||
hdbValue v;
|
||||
float fVal, *floatAr = NULL;
|
||||
int i;
|
||||
|
||||
if(argc < 3){
|
||||
SCWrite(pCon,"ERROR: putHdb needs at least node name",
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
node = FindHdbNode(NULL,argv[2], pCon);
|
||||
if(node == NULL){
|
||||
SCPrintf(pCon,eLogError,"ERROR: node %s not found", argv[2]);
|
||||
return;
|
||||
}
|
||||
memset(alias,0,512*sizeof(char));
|
||||
if(!GetHdbProperty(node,"nxalias", alias, 512)){
|
||||
if(argc < 4) {
|
||||
SCPrintf(pCon,eLogError,"ERROR: neither nxalias property nor alias on command line found for %s",
|
||||
argv[2]);
|
||||
return;
|
||||
} else {
|
||||
strncpy(alias, argv[3],512);
|
||||
}
|
||||
}
|
||||
GetHipadabaPar(node,&v,pCon);
|
||||
switch(v.dataType){
|
||||
case HIPNONE:
|
||||
return;
|
||||
break;
|
||||
case HIPINT:
|
||||
NXDputalias(self->fileHandle, self->dictHandle, alias,
|
||||
&v.v.intValue);
|
||||
break;
|
||||
case HIPFLOAT:
|
||||
fVal = v.v.doubleValue;
|
||||
NXDputalias(self->fileHandle, self->dictHandle, alias,
|
||||
&fVal);
|
||||
break;
|
||||
case HIPTEXT:
|
||||
NXDputalias(self->fileHandle, self->dictHandle, alias,
|
||||
v.v.text);
|
||||
break;
|
||||
case HIPINTAR:
|
||||
case HIPINTVARAR:
|
||||
NXDputalias(self->fileHandle, self->dictHandle, alias,
|
||||
v.v.intArray);
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
case HIPFLOATVARAR:
|
||||
floatAr = malloc(v.arrayLength*sizeof(float));
|
||||
if(floatAr == NULL){
|
||||
SCPrintf(pCon,eLogError,"ERROR: out of memory writing %s", node->name);
|
||||
return;
|
||||
}
|
||||
for(i = 0; i < v.arrayLength; i++){
|
||||
floatAr[i] = v.v.floatArray[i];
|
||||
}
|
||||
NXDputalias(self->fileHandle, self->dictHandle, alias,
|
||||
floatAr);
|
||||
free(floatAr);
|
||||
break;
|
||||
}
|
||||
ReleaseHdbValue(&v);
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void putHdbSlab(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
int argc, char *argv[]){
|
||||
pHdb node = NULL;
|
||||
char alias[512];
|
||||
hdbValue v;
|
||||
float fVal, *floatAr = NULL;
|
||||
int start[NX_MAXRANK], size[NX_MAXRANK];
|
||||
int i, status;
|
||||
|
||||
if(argc < 5){
|
||||
SCWrite(pCon,"ERROR: putHdbSlab needs at least node name start, size",
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
node = FindHdbNode(NULL,argv[2], pCon);
|
||||
if(node == NULL){
|
||||
SCPrintf(pCon,eLogError,"ERROR: node %s not found", argv[2]);
|
||||
return;
|
||||
}
|
||||
memset(alias,0,512*sizeof(char));
|
||||
if(!GetHdbProperty(node,"nxalias", alias, 512)){
|
||||
SCPrintf(pCon,eLogError,
|
||||
"ERROR: nxalias property not found for %s",
|
||||
argv[2]);
|
||||
return;
|
||||
}
|
||||
status = NXDopenalias(self->fileHandle, self->dictHandle,alias);
|
||||
if(status != NX_OK){
|
||||
SCPrintf(pCon,eLogError,"ERROR: failed to open alias for %s", argv[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
status = listToArray(pSics,argv[3],start);
|
||||
if(status != TCL_OK){
|
||||
SCWrite(pCon,"ERROR: failed to convert start value list", eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
status = listToArray(pSics,argv[4],size);
|
||||
if(status != TCL_OK){
|
||||
SCWrite(pCon,"ERROR: failed to convert size value list", eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
GetHipadabaPar(node,&v,pCon);
|
||||
switch(v.dataType){
|
||||
case HIPNONE:
|
||||
return;
|
||||
break;
|
||||
case HIPINT:
|
||||
status = NXputslab(self->fileHandle, &v.v.intValue, start,size);
|
||||
break;
|
||||
case HIPFLOAT:
|
||||
fVal = v.v.doubleValue;
|
||||
status = NXputslab(self->fileHandle, &fVal, start,size);
|
||||
break;
|
||||
case HIPTEXT:
|
||||
status = NXputslab(self->fileHandle, v.v.text, start,size);
|
||||
break;
|
||||
case HIPINTAR:
|
||||
case HIPINTVARAR:
|
||||
status = NXputslab(self->fileHandle, v.v.intArray, start,size);
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
case HIPFLOATVARAR:
|
||||
floatAr = malloc(v.arrayLength*sizeof(float));
|
||||
if(floatAr == NULL){
|
||||
SCPrintf(pCon,eLogError,"ERROR: out of memory writing %s", node->name);
|
||||
return;
|
||||
}
|
||||
for(i = 0; i < v.arrayLength; i++){
|
||||
floatAr[i] = v.v.floatArray[i];
|
||||
}
|
||||
status = NXputslab(self->fileHandle, floatAr, start,size);
|
||||
free(floatAr);
|
||||
break;
|
||||
}
|
||||
if(status != NX_OK){
|
||||
SCPrintf(pCon,eLogError,"ERROR: failed to write slab for node %s", argv[2]);
|
||||
}
|
||||
ReleaseHdbValue(&v);
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void updateHMDim(NXScript *self, pHistMem mem){
|
||||
int iDim[MAXDIM];
|
||||
int i, rank, timeLength, status;
|
||||
@ -444,7 +620,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
||||
|
||||
if(argc < 4){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to puthm",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -454,7 +630,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
||||
mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem");
|
||||
if(!mem){
|
||||
sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -475,14 +651,14 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
||||
if(status != TCL_OK){
|
||||
sprintf(buffer,"ERROR: failed to convert %s to integer",
|
||||
argv[4]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
status = Tcl_GetInt(InterpGetTcl(pSics),argv[5],&length);
|
||||
if(status != TCL_OK){
|
||||
sprintf(buffer,"ERROR: failed to convert %s to integer",
|
||||
argv[5]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -495,7 +671,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
||||
if(status != TCL_OK){
|
||||
sprintf(buffer,"ERROR: failed to convert %s to integer",
|
||||
argv[6]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -507,7 +683,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
||||
iData = (HistInt *)malloc(length*sizeof(HistInt));
|
||||
if(!iData){
|
||||
SCWrite(pCon,"ERROR: out of memory for reading histogram memory",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
memset(iData,0,length*sizeof(HistInt));
|
||||
@ -526,7 +702,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
||||
}
|
||||
}
|
||||
if(!status){
|
||||
SCWrite(pCon,"ERROR: failed to read histogram memory",eError);
|
||||
SCWrite(pCon,"ERROR: failed to read histogram memory",eLogError);
|
||||
if(subset){
|
||||
free(iData);
|
||||
}
|
||||
@ -539,7 +715,7 @@ static void putHistogramMemory(SConnection *pCon, SicsInterp *pSics,
|
||||
status = NXDputalias(self->fileHandle, self->dictHandle,argv[2],iData);
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write histogram memory data");
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
|
||||
if(subset){
|
||||
@ -563,7 +739,7 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics,
|
||||
|
||||
if(argc < 5){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to puthmchunked",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -573,7 +749,7 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics,
|
||||
mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem");
|
||||
if(!mem){
|
||||
sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -592,7 +768,7 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics,
|
||||
if(status != TCL_OK){
|
||||
sprintf(buffer,"ERROR: failed to convert %s to integer",
|
||||
argv[4]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -603,7 +779,7 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics,
|
||||
iData = (HistInt *)malloc(length*sizeof(HistInt));
|
||||
if(!iData){
|
||||
SCWrite(pCon,"ERROR: out of memory for reading histogram memory",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
memset(iData,0,length*sizeof(HistInt));
|
||||
@ -622,7 +798,7 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics,
|
||||
}
|
||||
}
|
||||
if(!status){
|
||||
SCWrite(pCon,"ERROR: failed to read histogram memory",eError);
|
||||
SCWrite(pCon,"ERROR: failed to read histogram memory",eLogError);
|
||||
if(subset){
|
||||
free(iData);
|
||||
}
|
||||
@ -635,7 +811,7 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics,
|
||||
status = NXDputalias(self->fileHandle, self->dictHandle,argv[2],iData);
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write histogram memory data");
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
|
||||
if(subset){
|
||||
@ -646,28 +822,6 @@ static void putHistogramMemoryChunked(SConnection *pCon, SicsInterp *pSics,
|
||||
return;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int listToArray(SicsInterp *pSics, char *list,
|
||||
int intar[NX_MAXRANK]){
|
||||
int argc, status, i, val;
|
||||
CONST char **argv;
|
||||
Tcl_Interp *pTcl = InterpGetTcl(pSics);
|
||||
|
||||
status = Tcl_SplitList(pTcl, list, &argc, &argv);
|
||||
if(status != TCL_OK){
|
||||
return status;
|
||||
}
|
||||
|
||||
for(i = 0; i < argc; i++){
|
||||
status = Tcl_GetInt(pTcl,argv[i],&val);
|
||||
if(status != TCL_OK){
|
||||
return status;
|
||||
}
|
||||
intar[i] = val;
|
||||
}
|
||||
Tcl_Free((char *)argv);
|
||||
return TCL_OK;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static void putSlab(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
int argc, char *argv[]){
|
||||
int start[NX_MAXRANK], size[NX_MAXRANK];
|
||||
@ -678,25 +832,25 @@ static void putSlab(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
|
||||
if(argc < 6){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to putslab",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
status = NXDopenalias(self->fileHandle, self->dictHandle,argv[2]);
|
||||
if(status != NX_OK){
|
||||
SCPrintf(pCon,eError,"ERROR: failed to open alias %s", argv[2]);
|
||||
SCPrintf(pCon,eLogError,"ERROR: failed to open alias %s", argv[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
status = listToArray(pSics,argv[3],start);
|
||||
if(status != TCL_OK){
|
||||
SCWrite(pCon,"ERROR: failed to convert start value list", eError);
|
||||
SCWrite(pCon,"ERROR: failed to convert start value list", eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
status = listToArray(pSics,argv[4],size);
|
||||
if(status != TCL_OK){
|
||||
SCWrite(pCon,"ERROR: failed to convert size value list", eError);
|
||||
SCWrite(pCon,"ERROR: failed to convert size value list", eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -731,7 +885,7 @@ static void putSlab(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
|
||||
if(written == 0){
|
||||
SCWrite(pCon,"ERROR: failed to write data, data not recognised",
|
||||
eError);
|
||||
eLogError);
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------*/
|
||||
@ -746,7 +900,7 @@ static void putTimeBinning(SConnection *pCon, SicsInterp *pSics,
|
||||
|
||||
if(argc < 4){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to puttimebinning",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -756,7 +910,7 @@ static void putTimeBinning(SConnection *pCon, SicsInterp *pSics,
|
||||
mem = (pHistMem)FindCommandData(pSics,argv[3],"HistMem");
|
||||
if(!mem){
|
||||
sprintf(buffer,"ERROR: HistMem %s not found!", argv[3]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -768,7 +922,7 @@ static void putTimeBinning(SConnection *pCon, SicsInterp *pSics,
|
||||
if(!status){
|
||||
sprintf(buffer,"ERROR: alias %s for time binning not found",
|
||||
argv[2]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
timeBin = GetHistTimeBin(mem,&timeLength);
|
||||
@ -780,7 +934,7 @@ static void putTimeBinning(SConnection *pCon, SicsInterp *pSics,
|
||||
if(self->timeDivisor != 1){
|
||||
timeCopy = (float *)malloc(timeLength*sizeof(float));
|
||||
if(timeCopy == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory writing time binning",eError);
|
||||
SCWrite(pCon,"ERROR: out of memory writing time binning",eLogError);
|
||||
return;
|
||||
}
|
||||
for(i = 0; i < timeLength; i++){
|
||||
@ -796,7 +950,7 @@ static void putTimeBinning(SConnection *pCon, SicsInterp *pSics,
|
||||
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write time binning");
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
SCSendOK(pCon);
|
||||
return;
|
||||
@ -814,7 +968,7 @@ static void putArray(SConnection *pCon, SicsInterp *pSics,
|
||||
|
||||
if(argc < 5){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to array",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
tcl = InterpGetTcl(pSics);
|
||||
@ -825,8 +979,8 @@ static void putArray(SConnection *pCon, SicsInterp *pSics,
|
||||
*/
|
||||
status = Tcl_GetInt(tcl,argv[4],&length);
|
||||
if(status != TCL_OK){
|
||||
sprintf(buffer,"ERROR: failed to convert %s to integer",argv[4]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
sprintf(buffer,"ERROR: failed to convert %s to integer in putarray",argv[4]);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -838,9 +992,9 @@ static void putArray(SConnection *pCon, SicsInterp *pSics,
|
||||
}
|
||||
if(data == NULL){
|
||||
snprintf(buffer,255,
|
||||
"ERROR: out of memory or invalid length at %s, length = %s",
|
||||
"ERROR: out of memory or invalid length in putarray at %s, length = %s",
|
||||
argv[2],argv[4]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
memset(data,0,length*sizeof(float));
|
||||
@ -854,14 +1008,14 @@ static void putArray(SConnection *pCon, SicsInterp *pSics,
|
||||
if(varData != NULL){
|
||||
status = Tcl_GetDouble(tcl,varData,&dVal);
|
||||
if(status != TCL_OK){
|
||||
sprintf(buffer,"ERROR: failed to convert %s to double",
|
||||
sprintf(buffer,"ERROR: failed to convert %s to double in putarray",
|
||||
varData);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
data[i] = (float)dVal;
|
||||
} else {
|
||||
snprintf(buffer,254,"WARNING: failed to find array element %d", i);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
snprintf(buffer,254,"WARNING: failed to find array element %d in putarray", i);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
}
|
||||
|
||||
@ -870,9 +1024,9 @@ static void putArray(SConnection *pCon, SicsInterp *pSics,
|
||||
*/
|
||||
status = NXDdefget(self->dictHandle,argv[2],buffer,254);
|
||||
if(!status){
|
||||
sprintf(buffer,"ERROR: alias %s for array not found",
|
||||
sprintf(buffer,"ERROR: alias %s for array not found in putarray",
|
||||
argv[2]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
free(data);
|
||||
return;
|
||||
}
|
||||
@ -883,8 +1037,8 @@ static void putArray(SConnection *pCon, SicsInterp *pSics,
|
||||
*/
|
||||
status = NXDputdef(self->fileHandle,self->dictHandle,defString,data);
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write array");
|
||||
SCWrite(pCon,buffer,eError);
|
||||
sprintf(buffer,"ERROR: failed to write array in putarray");
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
free(data);
|
||||
SCSendOK(pCon);
|
||||
@ -902,7 +1056,7 @@ static void putIntArray(SConnection *pCon, SicsInterp *pSics,
|
||||
|
||||
if(argc < 5){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to array",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
tcl = InterpGetTcl(pSics);
|
||||
@ -914,7 +1068,7 @@ static void putIntArray(SConnection *pCon, SicsInterp *pSics,
|
||||
status = Tcl_GetInt(tcl,argv[4],&length);
|
||||
if(status != TCL_OK){
|
||||
sprintf(buffer,"ERROR: failed to convert %s to integer",argv[4]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -925,7 +1079,7 @@ static void putIntArray(SConnection *pCon, SicsInterp *pSics,
|
||||
data = (int *)malloc(length*sizeof(int));
|
||||
}
|
||||
if(data == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory or invalid length",eError);
|
||||
SCWrite(pCon,"ERROR: out of memory or invalid length",eLogError);
|
||||
return;
|
||||
}
|
||||
memset(data,0,length*sizeof(int));
|
||||
@ -941,12 +1095,12 @@ static void putIntArray(SConnection *pCon, SicsInterp *pSics,
|
||||
if(status != TCL_OK){
|
||||
sprintf(buffer,"ERROR: failed to convert %s to int",
|
||||
varData);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
data[i] = iVal;
|
||||
} else {
|
||||
snprintf(buffer,254,"WARNING: failed to find array element %d", i);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
}
|
||||
|
||||
@ -957,7 +1111,7 @@ static void putIntArray(SConnection *pCon, SicsInterp *pSics,
|
||||
if(!status){
|
||||
sprintf(buffer,"ERROR: alias %s for array not found",
|
||||
argv[2]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
free(data);
|
||||
return;
|
||||
}
|
||||
@ -969,7 +1123,7 @@ static void putIntArray(SConnection *pCon, SicsInterp *pSics,
|
||||
status = NXDputdef(self->fileHandle,self->dictHandle,defString,data);
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write array");
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
free(data);
|
||||
SCSendOK(pCon);
|
||||
@ -983,7 +1137,7 @@ static void putGlobal(SConnection *pCon, SicsInterp *pSics,
|
||||
|
||||
if(argc < 4){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to putglobal",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -991,7 +1145,7 @@ static void putGlobal(SConnection *pCon, SicsInterp *pSics,
|
||||
status = NXputattr(self->fileHandle,argv[2],value,strlen(value),
|
||||
NX_CHAR);
|
||||
if(status != NX_OK){
|
||||
SCWrite(pCon,"ERROR: failed to write attribute",eError);
|
||||
SCWrite(pCon,"ERROR: failed to write attribute",eLogError);
|
||||
}
|
||||
SCSendOK(pCon);
|
||||
}
|
||||
@ -1007,14 +1161,14 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
if(strcmp(argv[1],"putfloat") == 0){
|
||||
if(argc < 4){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to putfloat",
|
||||
eError);
|
||||
eLogError);
|
||||
return 1;
|
||||
}
|
||||
status = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&dVal);
|
||||
if(status != TCL_OK){
|
||||
sprintf(buffer,"ERROR: failed to convert %s to float",
|
||||
argv[3]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return 1;
|
||||
}
|
||||
fVal = (float)dVal;
|
||||
@ -1023,20 +1177,20 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write %f to alias %s",
|
||||
fVal, argv[2]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
return 1;
|
||||
} else if(strcmp(argv[1],"putint") == 0){
|
||||
if(argc < 4){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to putint",
|
||||
eError);
|
||||
eLogError);
|
||||
return 1;
|
||||
}
|
||||
status = Tcl_GetInt(InterpGetTcl(pSics),argv[3],&iVal);
|
||||
if(status != TCL_OK){
|
||||
sprintf(buffer,"ERROR: failed to convert %s to int",
|
||||
argv[3]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return 1;
|
||||
}
|
||||
status = NXDputalias(self->fileHandle, self->dictHandle,
|
||||
@ -1044,14 +1198,14 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write %d to alias %s",
|
||||
iVal, argv[2]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
return 1;
|
||||
} else if (strcmp(argv[1],"puttext") == 0){
|
||||
/*====================*/
|
||||
if(argc < 4){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to puttext",
|
||||
eError);
|
||||
eLogError);
|
||||
return 1;
|
||||
}
|
||||
Arg2Text(argc-3,&argv[3],buffer,1023);
|
||||
@ -1060,7 +1214,7 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: alias %s not found in puttext",
|
||||
argv[2]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
return 1;
|
||||
}
|
||||
if(strlen(defString) < 900){
|
||||
@ -1070,7 +1224,7 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
strcat(defString," }");
|
||||
} else {
|
||||
SCWrite(pCon,"ERROR: out of definition string space in puttext",
|
||||
eError);
|
||||
eLogError);
|
||||
return 1;
|
||||
}
|
||||
status = NXDputdef(self->fileHandle,self->dictHandle,
|
||||
@ -1078,7 +1232,7 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
if(status != NX_OK){
|
||||
sprintf(buffer,"ERROR: failed to write alias %s",
|
||||
argv[2]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
SCWrite(pCon,buffer,eLogError);
|
||||
}
|
||||
return 1;
|
||||
} else if(strcmp(argv[1],"putmot") == 0){
|
||||
@ -1089,6 +1243,14 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
/* ================*/
|
||||
putCounter(pCon,pSics,self, argc,argv);
|
||||
return 1;
|
||||
} else if(strcmp(argv[1],"puthdb") == 0){
|
||||
/* ================*/
|
||||
putHdb(pCon,pSics,self, argc,argv);
|
||||
return 1;
|
||||
} else if(strcmp(argv[1],"puthdbslab") == 0){
|
||||
/* ================*/
|
||||
putHdbSlab(pCon,pSics,self, argc,argv);
|
||||
return 1;
|
||||
}else if(strcmp(argv[1],"puthm") == 0){
|
||||
/*=================*/
|
||||
putHistogramMemory(pCon,pSics,self,argc, argv);
|
||||
@ -1115,7 +1277,7 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self,
|
||||
/*===============*/
|
||||
putSlab(pCon,pSics,self,argc,argv);
|
||||
} else {
|
||||
SCWrite(pCon,"ERROR: put command not recognised",eError);
|
||||
SCWrite(pCon,"ERROR: put command not recognised",eLogError);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -1128,7 +1290,7 @@ static void makeLink(SConnection *pCon, SicsInterp *pSics,
|
||||
|
||||
if(argc < 4){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to makelink",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1137,7 +1299,7 @@ static void makeLink(SConnection *pCon, SicsInterp *pSics,
|
||||
if(status != NX_OK){
|
||||
snprintf(pBueffel,255,"ERROR: linking %s against %s failed",
|
||||
argv[2], argv[3]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
SCWrite(pCon,pBueffel,eLogError);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1150,12 +1312,12 @@ static void updateDictVar(SConnection *pCon, pNXScript self, int argc,
|
||||
|
||||
if(self->dictHandle == NULL){
|
||||
SCWrite(pCon,"ERROR: cannot update variable, dictionary not open",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
if(argc < 4){
|
||||
SCWrite(pCon,"ERROR: insufficient number of arguments to updateDictVar",
|
||||
eError);
|
||||
eLogError);
|
||||
return;
|
||||
}
|
||||
NXDupdate(self->dictHandle,argv[2],argv[3]);
|
||||
@ -1176,7 +1338,7 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
return 1;
|
||||
}
|
||||
if(argc < 2){
|
||||
SCWrite(pCon,"ERROR: no keyword found",eError);
|
||||
SCWrite(pCon,"ERROR: no keyword found",eLogError);
|
||||
return 1;
|
||||
}
|
||||
strtolower(argv[1]);
|
||||
@ -1193,7 +1355,7 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
}
|
||||
} else if(strcmp(argv[1],"divisor") == 0){
|
||||
if(argc < 3) {
|
||||
SCWrite(pCon,"ERROR: no diviso found",eError);
|
||||
SCWrite(pCon,"ERROR: no divisor found",eLogError);
|
||||
return 1;
|
||||
}
|
||||
if(!SCMatchRights(pCon,usMugger)){
|
||||
@ -1216,7 +1378,7 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
if we are here, we can only continue if files are open
|
||||
*/
|
||||
if(self->fileHandle == NULL || self->dictHandle == NULL){
|
||||
SCWrite(pCon,"ERROR: cannot write, files not open",eError);
|
||||
SCWrite(pCon,"ERROR: cannot write, files not open",eLogError);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1232,7 +1394,7 @@ int NXScriptAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
|
||||
if(strcmp(argv[1],"isalias") == 0) {
|
||||
if(argc < 3) {
|
||||
SCWrite(pCon,"ERROR: need alias to test",eError);
|
||||
SCWrite(pCon,"ERROR: need alias to test",eLogError);
|
||||
return 1;
|
||||
}
|
||||
if(NXDget(self->dictHandle,argv[2],buffer,131) == NX_OK){
|
||||
|
10
nxupdate.c
10
nxupdate.c
@ -46,8 +46,7 @@ static int UpdateTask(void *pData){
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int CountCallback(int iEvent, void *pEventData, void *pUser,
|
||||
commandContext cc){
|
||||
static int CountCallback(int iEvent, void *pEventData, void *pUser){
|
||||
pNXupdate self = NULL;
|
||||
SConnection *pCon = NULL;
|
||||
|
||||
@ -258,7 +257,6 @@ int UpdateFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
char pBueffel[256];
|
||||
pNXupdate self = NULL;
|
||||
CommandList *pCom = NULL;
|
||||
commandContext comCon;
|
||||
|
||||
if(argc < 3){
|
||||
SCWrite(pCon,"ERROR: insuffcient number of argument to UpdateFactory",
|
||||
@ -311,11 +309,9 @@ int UpdateFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
/*
|
||||
register callbacks
|
||||
*/
|
||||
comCon.transID = 0;
|
||||
strncpy(comCon.deviceID,"internal",SCDEVIDLEN);
|
||||
RegisterCallback(pCall,comCon,COUNTSTART,CountCallback,
|
||||
RegisterCallback(pCall,COUNTSTART,CountCallback,
|
||||
self,NULL);
|
||||
RegisterCallback(pCall,comCon,COUNTEND,CountCallback,
|
||||
RegisterCallback(pCall,COUNTEND,CountCallback,
|
||||
self,NULL);
|
||||
|
||||
AddCommand(pSics,argv[1],UpdateAction,KillUpdate,self);
|
||||
|
4
obdes.h
4
obdes.h
@ -1,5 +1,5 @@
|
||||
|
||||
#line 365 "interface.w"
|
||||
#line 385 "interface.w"
|
||||
|
||||
|
||||
#line 29 "interface.w"
|
||||
@ -56,7 +56,7 @@ typedef struct {
|
||||
|
||||
#endif
|
||||
|
||||
#line 366 "interface.w"
|
||||
#line 386 "interface.w"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Additional properties used by the ANSTO site to provide more information
|
||||
|
26
ofac.c
26
ofac.c
@ -85,7 +85,6 @@
|
||||
#include "udpquieck.h"
|
||||
#include "choco.h"
|
||||
#include "chadapter.h"
|
||||
#include "hklscan.h"
|
||||
#include "xytable.h"
|
||||
#include "maximize.h"
|
||||
#include "difrac.h"
|
||||
@ -129,6 +128,10 @@
|
||||
#include "hdbqueue.h"
|
||||
#include "genericcontroller.h"
|
||||
#include "proxy.h"
|
||||
#include "reflist.h"
|
||||
#include "singlex.h"
|
||||
#include "motorsec.h"
|
||||
#include "background.h"
|
||||
/*----------------------- Server options creation -------------------------*/
|
||||
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
@ -257,7 +260,8 @@
|
||||
AddCommand(pInter,"list",SicsList,NULL,NULL);
|
||||
AddCommand(pInter,"InstallHdb",InstallSICSHipadaba,NULL,NULL);
|
||||
MakeProtocol(pInter);
|
||||
|
||||
InstallBackground(pInter);
|
||||
|
||||
/* commands to do with the executor. Only StopExe carries the
|
||||
DeleteFunction in order to avoid double deletion. All the
|
||||
other commands operate on the same datastructure.
|
||||
@ -269,7 +273,7 @@
|
||||
AddCommand(pInter,"pause",PauseAction,NULL,pExe);
|
||||
AddCommand(pInter,"continue",ContinueAction,NULL,pExe);
|
||||
AddCommand(pInter,"devexec",DevexecAction,NULL,pExe);
|
||||
|
||||
|
||||
/* add additional object creation commands here */
|
||||
AddCommand(pInter,"TokenInit",TokenInit,NULL,NULL);
|
||||
AddCommand(pInter,"ServerOption",IFServerOption,NULL,NULL);
|
||||
@ -296,7 +300,6 @@
|
||||
AddCommand(pInter,"kill_command",SICSKill,NULL,NULL);
|
||||
AddCommand(pInter,"MakeChopper",ChocoFactory,NULL,NULL);
|
||||
AddCommand(pInter,"ChopperAdapter",CHAdapterFactory,NULL,NULL);
|
||||
AddCommand(pInter,"MakeHklscan",HklscanFactory,NULL,NULL);
|
||||
AddCommand(pInter,"MakeXYTable",XYFactory,NULL,NULL);
|
||||
AddCommand(pInter,"MakeMaximize",MaximizeFactory,NULL,NULL);
|
||||
AddCommand(pInter,"MakeLin2Ang",MakeLin2Ang,NULL,NULL);
|
||||
@ -350,6 +353,9 @@
|
||||
AddCommand(pInter,"MakeGenController",GenControllerFactory,NULL,NULL);
|
||||
AddCommand(pInter,"genconfigure",GenControllerConfigure,NULL,NULL);
|
||||
AddCommand(pInter,"MakeProxy",ProxyFactory,NULL,NULL);
|
||||
AddCommand(pInter,"MakeRefList",MakeReflectionList,NULL,NULL);
|
||||
AddCommand(pInter,"MakeSingleX",MakeSingleX,NULL,NULL);
|
||||
AddCommand(pInter,"MakeSecMotor",SecMotorFactory,NULL,NULL);
|
||||
|
||||
/*
|
||||
install site specific commands
|
||||
@ -425,6 +431,9 @@
|
||||
RemoveCommand(pSics,"MakeGenController");
|
||||
RemoveCommand(pSics,"genconfigure");
|
||||
RemoveCommand(pSics,"MakeProxy");
|
||||
RemoveCommand(pSics,"MakeRefList");
|
||||
RemoveCommand(pSics,"MakeSingleX");
|
||||
RemoveCommand(pSics,"MakeSecMotor");
|
||||
/*
|
||||
remove site specific installation commands
|
||||
*/
|
||||
@ -475,21 +484,12 @@
|
||||
InitIniCommands(pSics,pServ->pTasker);
|
||||
InstallBckRestore(pCon,pSics);
|
||||
|
||||
pCon->iFiles = 0;
|
||||
|
||||
/* evaluate the file */
|
||||
sprintf(pBueffel,"fileeval %s",file);
|
||||
iRet = InterpExecute(pSics,pCon,pBueffel);
|
||||
if(!iRet)
|
||||
{
|
||||
KillIniCommands(pSics);
|
||||
RemoveStartupCommands();
|
||||
SCDeleteConnection(pCon);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* done */
|
||||
pCon->iFiles = 0;
|
||||
SCDeleteConnection(pCon);
|
||||
KillIniCommands(pSics);
|
||||
RemoveStartupCommands();
|
||||
|
16
optimise.c
16
optimise.c
@ -347,7 +347,7 @@
|
||||
return 0;
|
||||
}
|
||||
sprintf(pBueffel,"Trying hard to optimise variable %s",pOvar->pName);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
iRet = SilentScan(self->pScanner,pOvar->iStep,self->eCount,
|
||||
self->fPreset,pServ->pSics,pCon);
|
||||
if(!iRet)
|
||||
@ -397,11 +397,11 @@
|
||||
strcat(pBueffel,cData);
|
||||
break;
|
||||
}
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
|
||||
if(fMax < self->fThreshold)
|
||||
{
|
||||
SCWrite(pCon,"Peak may be lost, increasing scan range",eWarning);
|
||||
SCWrite(pCon,"Peak may be lost, increasing scan range",eLog);
|
||||
pOvar->iLost++;
|
||||
if(pOvar->iLost > 2)
|
||||
{
|
||||
@ -435,11 +435,11 @@
|
||||
{
|
||||
pOvar->fShift = ABS(pOvar->fCenter - fNewCenter);
|
||||
sprintf(pBueffel,"%s shifted by %8.2f ",pOvar->pName,pOvar->fShift);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
pOvar->fPrecision = 3*fStdDev;
|
||||
sprintf(pBueffel,"%s precision set to 3*StdDev = %8.3f",
|
||||
pOvar->pName, 3*fStdDev);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
pOvar->fCenter = fNewCenter;
|
||||
}
|
||||
/* drive to the new center */
|
||||
@ -627,7 +627,7 @@ static int findDirection(pOptimise self, pOVarEntry pOvar, SConnection *pCon)
|
||||
}
|
||||
snprintf(buffer,255,"Climbing %s, value = %f, count = %ld",
|
||||
pOvar->pName, varValue, currentCount);
|
||||
SCWrite(pCon,buffer,eWarning);
|
||||
SCWrite(pCon,buffer,eLog);
|
||||
|
||||
if(currentCount <= lastCount)
|
||||
{
|
||||
@ -695,7 +695,7 @@ static int findDirection(pOptimise self, pOVarEntry pOvar, SConnection *pCon)
|
||||
for(iCycle = 0; iCycle < self->iMaxCycles; iCycle++)
|
||||
{
|
||||
sprintf(pBueffel,"Optimiser cycle %d of %d started",iCycle, self->iMaxCycles);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
for(i = iRedoVar; i < self->iVar; i++)
|
||||
{
|
||||
iRet = CenterVariable(self,pCon,i);
|
||||
@ -740,7 +740,7 @@ static int findDirection(pOptimise self, pOVarEntry pOvar, SConnection *pCon)
|
||||
for(iCycle = 0; iCycle < self->iMaxCycles; iCycle++)
|
||||
{
|
||||
sprintf(pBueffel,"Optimiser cycle %d of %d started",iCycle, self->iMaxCycles);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
for(i = iRedoVar; i < self->iVar; i++)
|
||||
{
|
||||
iRet = ClimbVariable(self,pCon,i);
|
||||
|
@ -22,6 +22,8 @@
|
||||
"error",
|
||||
"hdbvalue",
|
||||
"hdbevent",
|
||||
"log",
|
||||
"logerror",
|
||||
NULL };
|
||||
static int iNoCodes = 13;
|
||||
#endif
|
||||
|
15
perfmon.c
15
perfmon.c
@ -147,8 +147,7 @@
|
||||
return self->fCPS;
|
||||
}
|
||||
/*------------------- The CallBack function for interest ------------------*/
|
||||
static int InterestCallback(int iEvent, void *pEvent, void *pUser,
|
||||
commandContext cc)
|
||||
static int InterestCallback(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
float *fPos;
|
||||
SConnection *pCon;
|
||||
@ -160,8 +159,13 @@
|
||||
fPos = (float *)pEvent;
|
||||
pCon = (SConnection *)pUser;
|
||||
|
||||
if(pCon == NULL || !SCisConnected(pCon))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(pBueffel,"Performance = %f", *fPos);
|
||||
SCWriteInContext(pCon,pBueffel,eValue,cc);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------------
|
||||
@ -207,10 +211,9 @@
|
||||
|
||||
if(strcmp(argv[1],"interest") == 0)
|
||||
{
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),
|
||||
lID = RegisterCallback(self->pCall,
|
||||
VALUECHANGE, InterestCallback,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
SCCopyConnection(pCon), SCDeleteConnection);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
|
47
protocol.c
47
protocol.c
@ -173,7 +173,7 @@ void DeleteProtocol(void *self)
|
||||
/*------------------------------------------------------------------*/
|
||||
static int ContextDo(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
commandContext comCon;
|
||||
SConnection *comCon = NULL;
|
||||
char buffer[1024];
|
||||
char *command;
|
||||
int status;
|
||||
@ -183,23 +183,27 @@ static int ContextDo(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = Tcl_GetInt(pSics->pTcl,argv[1],&comCon.transID);
|
||||
comCon = SCCopyConnection(pCon);
|
||||
if(comCon == NULL){
|
||||
SCWrite(pCon,"EROOR: out of memory in contextdo", eError);
|
||||
return 0;
|
||||
}
|
||||
status = Tcl_GetInt(pSics->pTcl,argv[1],&comCon->transID);
|
||||
if(status != TCL_OK){
|
||||
snprintf(buffer,1023,"ERROR: failed to convert %s to transaction ID", argv[1]);
|
||||
SCWrite(pCon,buffer,eError);
|
||||
return 0;
|
||||
}
|
||||
strncpy(comCon.deviceID,argv[2],SCDEVIDLEN);
|
||||
strncpy(comCon->deviceID,argv[2],SCDEVIDLEN);
|
||||
memset(buffer,0,sizeof(buffer));
|
||||
command = Arg2Tcl(argc-2,&argv[2],buffer,sizeof buffer);
|
||||
if (!command) {
|
||||
SCWrite(pCon,"ERROR: no more memory",eError);
|
||||
return 0;
|
||||
}
|
||||
SCPushContext2(pCon,comCon);
|
||||
status = InterpExecute(pSics,pCon,command);
|
||||
status = InterpExecute(pSics,comCon,command);
|
||||
if (command != buffer) free(command);
|
||||
SCPopContext(pCon);
|
||||
SCDeleteConnection(comCon);
|
||||
return status;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -236,7 +240,7 @@ static int ProtocolOptions(SConnection* pCon, pProtocol pPro)
|
||||
for(i=0;i<pPro->iNumPros;i++)
|
||||
{
|
||||
sprintf(pBuffer,"Protocol[%d] = %s",i,pPro->pProList[i]);
|
||||
SCWrite(pCon,pBuffer,eStatus);
|
||||
SCWrite(pCon,pBuffer,eValue);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -246,18 +250,22 @@ static int ProtocolHelp(SConnection* pCon, Protocol* pPro)
|
||||
{
|
||||
SCWrite(pCon,
|
||||
"Usage: protocol {help|list|options|reset} | set protocolName",
|
||||
eStatus);
|
||||
eValue);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int ProtocolSet(SConnection* pCon, Protocol* pPro, char *pProName)
|
||||
{
|
||||
SConnection *pMaster = NULL;
|
||||
|
||||
int proID;
|
||||
if(!SCVerifyConnection(pCon))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
pMaster = SCfindMaster(pCon);
|
||||
assert(pMaster != NULL);
|
||||
|
||||
/* lazy initialisation of defaultWriter since connection is verified */
|
||||
InitDefaultProtocol(pCon,pPro);
|
||||
@ -278,28 +286,35 @@ static int ProtocolSet(SConnection* pCon, Protocol* pPro, char *pProName)
|
||||
break;
|
||||
|
||||
case 1: /* normal (connection start default) */
|
||||
SCSetWriteFunc(pCon,SCNormalWrite);
|
||||
SCSetWriteFunc(pMaster,SCNormalWrite);
|
||||
SCSetWriteFunc(pCon,SCNormalWrite);
|
||||
break;
|
||||
|
||||
case 2: /* outcodes */
|
||||
SCSetWriteFunc(pCon,SCWriteWithOutcode);
|
||||
SCSetWriteFunc(pMaster,SCWriteWithOutcode);
|
||||
SCSetWriteFunc(pCon,SCWriteWithOutcode);
|
||||
break;
|
||||
|
||||
case 3: /* sycamore */
|
||||
SCSetWriteFunc(pCon,SCWriteSycamore);
|
||||
SCSetWriteFunc(pMaster,SCWriteSycamore);
|
||||
SCSetWriteFunc(pCon,SCWriteSycamore);
|
||||
break;
|
||||
case 4: /* json */
|
||||
SCSetWriteFunc(pCon,SCWriteJSON_String);
|
||||
SCSetWriteFunc(pCon,SCWriteJSON_String);
|
||||
SCSetWriteFunc(pMaster,SCWriteJSON_String);
|
||||
break;
|
||||
case 5:
|
||||
SCSetWriteFunc(pCon,SCACTWrite);
|
||||
SCSetWriteFunc(pMaster,SCACTWrite);
|
||||
SCSetWriteFunc(pCon,SCACTWrite);
|
||||
break;
|
||||
case 0: /* default = psi_sics */
|
||||
default:
|
||||
SCSetWriteFunc(pCon,pPro->defaultWriter);
|
||||
SCSetWriteFunc(pMaster,pPro->defaultWriter);
|
||||
SCSetWriteFunc(pCon,pPro->defaultWriter);
|
||||
break;
|
||||
}
|
||||
pCon->iProtocolID = proID;
|
||||
pMaster->iProtocolID = proID;
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
@ -356,7 +371,7 @@ static int ProtocolList(SConnection* pCon, Protocol* pPro)
|
||||
{
|
||||
SCWrite(pCon,
|
||||
"Usage: protocol {help|list|options|reset} | set protocolName",
|
||||
eStatus);
|
||||
eValue);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -589,7 +604,6 @@ int SCWriteSycamore(SConnection *pCon, char *pBuffer, int iOut)
|
||||
/* first the socket */
|
||||
/*strcat(pMsg, pBueffel);*/
|
||||
iRet = SCDoSockWrite(pCon,GetCharArray(pMsg));
|
||||
SCWriteToLogFiles(pCon,GetCharArray(pMsg));
|
||||
}
|
||||
if (pMsg != NULL)
|
||||
DeleteDynString(pMsg);
|
||||
@ -742,7 +756,6 @@ int SCWriteJSON_String(SConnection *pCon, char *pBuffer, int iOut)
|
||||
iRet = 0;
|
||||
} else {
|
||||
iRet = SCDoSockWrite(pCon,json_object_to_json_string(my_object));
|
||||
SCWriteToLogFiles(pCon,pBuffer);
|
||||
}
|
||||
}
|
||||
if (tmp_json != NULL && !is_error(tmp_json))
|
||||
|
49
remob.c
49
remob.c
@ -45,7 +45,7 @@ typedef struct RemServer {
|
||||
int taskActive;
|
||||
int interestActive;
|
||||
int forwardMessages;
|
||||
SCStore *conn;
|
||||
SConnection *conn;
|
||||
} RemServer;
|
||||
|
||||
struct Remob {
|
||||
@ -156,7 +156,7 @@ static int RemHandle(RemServer *remserver) {
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void RemCopy(RemChannel *rc, SConnection *pCon) {
|
||||
if (pCon != NULL && rc->line[0] != '\0') {
|
||||
SCPrintf(pCon, eStatus, " %s", rc->line);
|
||||
SCPrintf(pCon, eLog, " %s", rc->line);
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -260,10 +260,8 @@ static int RemServerTask(void *data) {
|
||||
|
||||
if (remserver->forwardMessages) {
|
||||
/* forward all other messages */
|
||||
if (SCStoreConnected(remserver->conn)) {
|
||||
pCon = SCStorePush(remserver->conn);
|
||||
RemCopy(rc, pCon);
|
||||
SCStorePop(remserver->conn);
|
||||
if (SCisConnected(remserver->conn)) {
|
||||
RemCopy(rc, remserver->conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -406,7 +404,10 @@ static float RemobGetValue(void *pData, SConnection *pCon) {
|
||||
|
||||
assert(remob);
|
||||
|
||||
remserver->conn = SCSave(pCon, remserver->conn);
|
||||
if(remserver->conn != NULL){
|
||||
SCDeleteConnection(remserver->conn);
|
||||
}
|
||||
remserver->conn = SCCopyConnection(pCon);
|
||||
none = -1.25e6;
|
||||
value= none;
|
||||
snprintf(buf, sizeof(buf), "<%s", remob->name);
|
||||
@ -457,7 +458,10 @@ static int RemobStatus(void *pData, SConnection *pCon) {
|
||||
|
||||
assert(remob);
|
||||
|
||||
remob->server->conn = SCSave(pCon, remob->server->conn);
|
||||
if(remob->server->conn != NULL){
|
||||
SCDeleteConnection(remob->server->conn);
|
||||
}
|
||||
remob->server->conn = SCCopyConnection(pCon);
|
||||
return remob->status;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
@ -475,10 +479,14 @@ static long RemobRun(void *self, SConnection *pCon, float fNew) {
|
||||
RemChannel *rc;
|
||||
int nChan;
|
||||
|
||||
remserver = remob->server;
|
||||
remserver->conn = SCSave(pCon, remserver->conn);
|
||||
assert(remob);
|
||||
assert(pCon);
|
||||
|
||||
remserver = remob->server;
|
||||
if(remserver->conn != NULL){
|
||||
SCDeleteConnection(remserver->conn);
|
||||
}
|
||||
remserver->conn = SCCopyConnection(pCon);
|
||||
|
||||
rights = SCGetRights(pCon);
|
||||
nChan = rights <= usUser;
|
||||
@ -526,6 +534,9 @@ static void KillInfo(void *pData) {
|
||||
if (self->pName) {
|
||||
free(self->pName);
|
||||
}
|
||||
if(self->pCon){
|
||||
SCDeleteConnection(self->pCon);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*------------------- The CallBack function for interest ------------------*/
|
||||
@ -572,7 +583,10 @@ int RemobAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
nChan = (rights <= usUser);
|
||||
rc = &remserver->rc[nChan];
|
||||
if (rights >= usUser) {
|
||||
remserver->conn = SCSave(pCon, remserver->conn);
|
||||
if(remserver->conn != NULL){
|
||||
SCDeleteConnection(remserver->conn);
|
||||
}
|
||||
remserver->conn = SCCopyConnection(pCon);
|
||||
}
|
||||
if (argc == 1) {
|
||||
iRet = RemTransact(remserver, nChan, pCon, remob->name, ">", NULL);
|
||||
@ -629,7 +643,7 @@ static void RemobKill(void *self) {
|
||||
if (remob->pCall) {
|
||||
DeleteCallBackInterface(remob->pCall);
|
||||
}
|
||||
|
||||
|
||||
/* kill Descriptor */
|
||||
if (remob->desc) {
|
||||
DeleteDescriptor(remob->desc);
|
||||
@ -664,7 +678,10 @@ int RemServerAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
nChan = (rights <= usUser);
|
||||
rc = &remserver->rc[nChan];
|
||||
if (nChan) {
|
||||
remserver->conn = SCSave(pCon, remserver->conn);
|
||||
if(remserver->conn != NULL){
|
||||
SCDeleteConnection(remserver->conn);
|
||||
}
|
||||
remserver->conn = SCCopyConnection(pCon);
|
||||
}
|
||||
if (argc == 1) {
|
||||
serverport = IFindOption(pSICSOptions,"ServerPort");
|
||||
@ -680,7 +697,7 @@ int RemServerAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
}
|
||||
}
|
||||
if (thishostname == NULL) thishostname = "undef";
|
||||
SCPrintf(pCon, eStatus, "%s = %s:%d %s:%s",
|
||||
SCPrintf(pCon, eValue, "%s = %s:%d %s:%s",
|
||||
argv[0], remserver->host, remserver->port, thishostname, serverport);
|
||||
} else if (argc>2 && strcasecmp(argv[1],"nowait") == 0) {
|
||||
RemConnect(remserver, nChan);
|
||||
@ -737,7 +754,9 @@ static void RemServerKill(void *self) {
|
||||
DeleteDescriptor(remserver->desc);
|
||||
if (remserver->name) free(remserver->name);
|
||||
if (remserver->host) free(remserver->host);
|
||||
SCStoreFree(remserver->conn);
|
||||
if(remserver->conn != NULL){
|
||||
SCDeleteConnection(remserver->conn);
|
||||
}
|
||||
free(remserver);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -237,7 +237,7 @@ int readRS232TillTerm(prs232 self, void *data, int *datalen){
|
||||
}
|
||||
else if(iRet == -1)
|
||||
{
|
||||
printf("Incomplete read: %s\n", (char *)data);
|
||||
printf("Incomplete read: %s, errno = %d\n", (char *)data, errno);
|
||||
return INCOMPLETE;
|
||||
}
|
||||
else if (iRet < 0)
|
||||
@ -374,7 +374,7 @@ int transactRS232(prs232 self, void *send, int sendLen,
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("RS232 IN/TRANS/INCOMPLETE: %s",(char *)reply);
|
||||
printf("RS232 IN/TRANS/INCOMPLETE: %s, errno = %d",(char *)reply, errno);
|
||||
}
|
||||
}
|
||||
if(iRet == 0)
|
||||
|
134
scan.c
134
scan.c
@ -395,7 +395,7 @@ int StoreScanCounts(pScanData self, char *data)
|
||||
if(data == NULL)
|
||||
{
|
||||
SCWrite(self->pCon,"WARNING: StoreScanCounts called without data",
|
||||
eWarning);
|
||||
eLog);
|
||||
return 1;
|
||||
}
|
||||
InitCountEntry(&sCount);
|
||||
@ -409,9 +409,9 @@ int StoreScanCounts(pScanData self, char *data)
|
||||
}
|
||||
else
|
||||
{
|
||||
SCWrite(self->pCon,"WARNING: No data in StoreScanCounts",eWarning);
|
||||
SCWrite(self->pCon,"WARNING: No data in StoreScanCounts",eLog);
|
||||
snprintf(pBueffel,255,"Received: %s", data);
|
||||
SCWrite(self->pCon,pBueffel,eWarning);
|
||||
SCWrite(self->pCon,pBueffel,eLog);
|
||||
return 1;
|
||||
}
|
||||
pPtr = stptok(pPtr,pNumber,29," \t");
|
||||
@ -431,7 +431,7 @@ int StoreScanCounts(pScanData self, char *data)
|
||||
{
|
||||
SCWrite(self->pCon,
|
||||
"ERROR: I have only space for 10 Monitors in count structure",
|
||||
eError);
|
||||
eLogError);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -484,7 +484,7 @@ CountEntry CollectCounterData(pScanData self)
|
||||
iRet = Tcl_Eval(pTcl,self->pCommand);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
SCWrite(self->pCon,pTcl->result,eError);
|
||||
SCWrite(self->pCon,pTcl->result,eLogError);
|
||||
return sCount;
|
||||
}
|
||||
/* interprete the Tcl result as a list of counts
|
||||
@ -495,7 +495,7 @@ CountEntry CollectCounterData(pScanData self)
|
||||
pPtr = strtok(pAns," ");
|
||||
if(!pPtr)
|
||||
{
|
||||
SCWrite(self->pCon,"ERROR: no counts found in Tcl-result",eError);
|
||||
SCWrite(self->pCon,"ERROR: no counts found in Tcl-result",eLogError);
|
||||
}
|
||||
sscanf(pPtr,"%f",&fVal);
|
||||
sCount.lCount = (long)fVal;
|
||||
@ -559,11 +559,11 @@ CountEntry CollectCounterData(pScanData self)
|
||||
SCSetInterrupt(self->pCon,eContinue);
|
||||
SCWrite(self->pCon,
|
||||
"WARNING: skipped scan point due to motor failure",
|
||||
eWarning);
|
||||
eLog);
|
||||
continue;
|
||||
break;
|
||||
case eAbortScan:
|
||||
SCWrite(self->pCon,"ERROR: Scan aborted",eError);
|
||||
SCWrite(self->pCon,"ERROR: Scan aborted",eLogError);
|
||||
/* eat the interrupt, the requested op has been
|
||||
done
|
||||
*/
|
||||
@ -571,14 +571,14 @@ CountEntry CollectCounterData(pScanData self)
|
||||
return 0;
|
||||
break;
|
||||
default: /* all others */
|
||||
SCWrite(self->pCon,"ERROR: Scan aborted",eError);
|
||||
SCWrite(self->pCon,"ERROR: Scan aborted",eLogError);
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(self->pCon,"WARNING: skipped scan point after drive failure",
|
||||
eWarning);
|
||||
eLog);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -596,7 +596,7 @@ CountEntry CollectCounterData(pScanData self)
|
||||
continue;
|
||||
break;
|
||||
case eAbortScan:
|
||||
SCWrite(self->pCon,"ERROR: Scan aborted",eError);
|
||||
SCWrite(self->pCon,"ERROR: Scan aborted",eLogError);
|
||||
/* eat the interrupt, the requested op has been
|
||||
done
|
||||
*/
|
||||
@ -604,14 +604,14 @@ CountEntry CollectCounterData(pScanData self)
|
||||
return 0;
|
||||
break;
|
||||
default: /* all others */
|
||||
SCWrite(self->pCon,"ERROR: Scan aborted",eError);
|
||||
SCWrite(self->pCon,"ERROR: Scan aborted",eLogError);
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
if(!iRet)
|
||||
{
|
||||
SCWrite(self->pCon,"WARNING: skipped scan point after count failure",
|
||||
eWarning);
|
||||
eLog);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1264,8 +1264,7 @@ CountEntry CollectCounterData(pScanData self)
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int ScanInterest(int iEvent, void *pEventData, void *pUser,
|
||||
commandContext cc)
|
||||
static int ScanInterest(int iEvent, void *pEventData, void *pUser)
|
||||
{
|
||||
pScanData self = NULL;
|
||||
SConnection *pCon = NULL;
|
||||
@ -1280,14 +1279,18 @@ CountEntry CollectCounterData(pScanData self)
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
if(!SCisConnected(pCon)){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(iEvent == SCANSTART)
|
||||
{
|
||||
SCWriteInContext(pCon,"NewScan",eWarning,cc);
|
||||
SCWrite(pCon,"NewScan",eLog);
|
||||
return 1;
|
||||
}
|
||||
else if(iEvent == SCANEND)
|
||||
{
|
||||
SCWriteInContext(pCon,"ScanEnd",eWarning,cc);
|
||||
SCWrite(pCon,"ScanEnd",eLog);
|
||||
return 1;
|
||||
}
|
||||
else if(iEvent == SCANPOINT)
|
||||
@ -1319,7 +1322,7 @@ CountEntry CollectCounterData(pScanData self)
|
||||
strcat(pPtr,"}");
|
||||
oldWrite = SCGetWriteFunc(pCon);
|
||||
SCSetWriteFunc(pCon,SCOnlySockWrite);
|
||||
SCWrite(pCon,pPtr,eWarning);
|
||||
SCWrite(pCon,pPtr,eLog);
|
||||
SCSetWriteFunc(pCon,oldWrite);
|
||||
free(lData);
|
||||
free(pPtr);
|
||||
@ -1328,8 +1331,7 @@ CountEntry CollectCounterData(pScanData self)
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int ScanDynInterest(int iEvent, void *pEventData, void *pUser,
|
||||
commandContext cc)
|
||||
static int ScanDynInterest(int iEvent, void *pEventData, void *pUser)
|
||||
{
|
||||
pScanData self = NULL;
|
||||
SConnection *pCon = NULL;
|
||||
@ -1347,14 +1349,19 @@ CountEntry CollectCounterData(pScanData self)
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
if(!SCisConnected(pCon))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(iEvent == SCANSTART)
|
||||
{
|
||||
SCWriteInContext(pCon,"NewScan",eWarning,cc);
|
||||
SCWrite(pCon,"NewScan",eLog);
|
||||
return 1;
|
||||
}
|
||||
else if(iEvent == SCANEND)
|
||||
{
|
||||
SCWriteInContext(pCon,"ScanEnd",eWarning,cc);
|
||||
SCWrite(pCon,"ScanEnd",eLog);
|
||||
return 1;
|
||||
}
|
||||
else if(iEvent == SCANPOINT)
|
||||
@ -1376,16 +1383,15 @@ CountEntry CollectCounterData(pScanData self)
|
||||
}
|
||||
snprintf(pBueffel,255,"%s.scanpoint = {%d %f %ld}",
|
||||
self->objectName,i,fVal,lVal);
|
||||
SCWriteInContext(pCon,pBueffel,eValue,cc);
|
||||
SCWrite(pCon,pBueffel,eLog);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int ScanUUInterest(int iEvent, void *pEventData, void *pUser,
|
||||
commandContext cc)
|
||||
static int ScanUUInterest(int iEvent, void *pEventData, void *pUser)
|
||||
{
|
||||
pScanData self = NULL;
|
||||
SConnection *pCon = NULL;
|
||||
SConnection *pCon = NULL, *comCon = NULL;
|
||||
char pItem[20];
|
||||
long *lData = NULL;
|
||||
int *iData = NULL;
|
||||
@ -1396,15 +1402,21 @@ CountEntry CollectCounterData(pScanData self)
|
||||
|
||||
assert(self);
|
||||
assert(pCon);
|
||||
|
||||
/*
|
||||
printf("ScanUUInterest called for pCon = %p handle %d\n", pCon, pCon->sockHandle);
|
||||
*/
|
||||
if(!SCisConnected(pCon)){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(iEvent == SCANSTART)
|
||||
{
|
||||
SCWriteInContext(pCon,"NewScan",eWarning,cc);
|
||||
SCWrite(pCon,"NewScan",eLog);
|
||||
return 1;
|
||||
}
|
||||
else if(iEvent == SCANEND)
|
||||
{
|
||||
SCWriteInContext(pCon,"ScanEnd",eWarning,cc);
|
||||
SCWrite(pCon,"ScanEnd",eLog);
|
||||
return 1;
|
||||
}
|
||||
else if(iEvent == SCANPOINT)
|
||||
@ -1426,9 +1438,7 @@ CountEntry CollectCounterData(pScanData self)
|
||||
{
|
||||
iData[i] = htonl((int)lData[i]);
|
||||
}
|
||||
SCPushContext2(pCon,cc);
|
||||
SCWriteUUencoded(pCon,"ScanData",iData,self->iNP*sizeof(int));
|
||||
SCPopContext(pCon);
|
||||
free(lData);
|
||||
free(iData);
|
||||
return 1;
|
||||
@ -1929,53 +1939,53 @@ static int DumpScan(pScanData self, SConnection *pCon)
|
||||
/*-------- interest */
|
||||
else if(strcmp(argv[1],"interest") == 0)
|
||||
{
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANSTART, ScanInterest,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANEND, ScanInterest,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANPOINT, ScanInterest,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
/*
|
||||
printf("Registering scan callbacks on handle %d\n", pCon->sockHandle);
|
||||
*/
|
||||
lID = RegisterCallback(self->pCall, SCANSTART, ScanInterest,
|
||||
SCCopyConnection(pCon), SCDeleteConnection);
|
||||
lID = RegisterCallback(self->pCall, SCANEND, ScanInterest,
|
||||
SCCopyConnection(pCon),SCDeleteConnection);
|
||||
lID = RegisterCallback(self->pCall, SCANPOINT, ScanInterest,
|
||||
SCCopyConnection(pCon), SCDeleteConnection);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*-------- interest */
|
||||
else if(strcmp(argv[1],"dyninterest") == 0)
|
||||
{
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANSTART, ScanDynInterest,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon), SCANEND, ScanDynInterest,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANPOINT, ScanDynInterest,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
/*
|
||||
printf("Registering scanDyn callbacks on handle %d\n", pCon->sockHandle);
|
||||
*/
|
||||
lID = RegisterCallback(self->pCall, SCANSTART, ScanDynInterest,
|
||||
SCCopyConnection(pCon), SCDeleteConnection);
|
||||
lID = RegisterCallback(self->pCall,SCANEND, ScanDynInterest,
|
||||
SCCopyConnection(pCon), SCDeleteConnection);
|
||||
lID = RegisterCallback(self->pCall, SCANPOINT, ScanDynInterest,
|
||||
SCCopyConnection(pCon), SCDeleteConnection);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*-------- uuinterest */
|
||||
else if(strcmp(argv[1],"uuinterest") == 0)
|
||||
{
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANSTART, ScanUUInterest,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANEND, ScanUUInterest,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),SCANPOINT, ScanUUInterest,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
/*
|
||||
printf("Registering scanUU callbacks on handle %d, con = %p\n",
|
||||
conSave->sockHandle, conSave);
|
||||
*/
|
||||
lID = RegisterCallback(self->pCall, SCANSTART, ScanUUInterest,
|
||||
SCCopyConnection(pCon), SCDeleteConnection);
|
||||
lID = RegisterCallback(self->pCall, SCANEND, ScanUUInterest,
|
||||
SCCopyConnection(pCon),SCDeleteConnection);
|
||||
lID = RegisterCallback(self->pCall, SCANPOINT, ScanUUInterest,
|
||||
SCCopyConnection(pCon), SCDeleteConnection);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/* ------- uninterest */
|
||||
else if(strcmp(argv[1],"uninterest") == 0)
|
||||
{
|
||||
RemoveCallback2(self->pCall,pCon);
|
||||
SCUnregister(pCon,self->pCall);
|
||||
RemoveCallbackCon(self->pCall,pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
@ -2134,7 +2144,7 @@ static int DumpScan(pScanData self, SConnection *pCon)
|
||||
iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&lNP);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]);
|
||||
sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
@ -2187,7 +2197,7 @@ static int DumpScan(pScanData self, SConnection *pCon)
|
||||
iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&lNP);
|
||||
if(iRet != TCL_OK)
|
||||
{
|
||||
sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]);
|
||||
sprintf(pBueffel,"ERROR: expected number, got %s",argv[2]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
4
script.c
4
script.c
@ -79,12 +79,12 @@
|
||||
if(pOwner)
|
||||
{
|
||||
Interrupt2Text(SCGetInterrupt(pOwner),pBueffel,131);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Interrupt2Text(SCGetInterrupt(pCon),pBueffel,131);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
102
scriptcontext.c
102
scriptcontext.c
@ -33,7 +33,7 @@ typedef struct ScriptContext {
|
||||
struct SctController {
|
||||
DevSer *devser;
|
||||
Hdb *node; /* the controller node */
|
||||
SCStore *conn;
|
||||
SConnection*conn;
|
||||
int verbose;
|
||||
};
|
||||
|
||||
@ -41,13 +41,13 @@ struct SctController {
|
||||
typedef struct SctData {
|
||||
char *name;
|
||||
SctController *controller;
|
||||
SCStore *conCtx;
|
||||
SConnection*conCtx;
|
||||
int answered;
|
||||
Hdb *node;
|
||||
} SctData;
|
||||
|
||||
static ScriptContext *sct = NULL;
|
||||
static SCStore *currentCon = NULL;
|
||||
static SConnection *currentCon = NULL;
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
@ -184,6 +184,14 @@ int SctCommand(SConnection *con, SicsInterp *sics, void *object,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* controller
|
||||
*/
|
||||
if(strcmp(argv[1],"controller") == 0){
|
||||
SCWrite(con,cNode->name, eValue);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* time stamping
|
||||
*/
|
||||
@ -271,9 +279,9 @@ static char *SctActionHandler(void *actionData, char *lastReply) {
|
||||
char timeKey[50], timeVal[50];
|
||||
|
||||
if (currentCon) {
|
||||
con = SCStorePush(currentCon);
|
||||
con = currentCon;
|
||||
} else {
|
||||
con = SCStorePush(controller->conn);
|
||||
con = controller->conn;
|
||||
}
|
||||
SetProp(node, controller->node, "result", lastReply);
|
||||
if (controller->verbose && lastReply != NULL && *lastReply != '\0') {
|
||||
@ -310,26 +318,16 @@ static char *SctActionHandler(void *actionData, char *lastReply) {
|
||||
send = GetProp(node, controller->node, "send");
|
||||
if (send != NULL && send[0] != '\0') {
|
||||
if (controller->verbose) {
|
||||
SCPrintf(con, eWarning, "send : %s", send);
|
||||
}
|
||||
if (currentCon) {
|
||||
SCStorePop(currentCon);
|
||||
} else {
|
||||
SCStorePop(controller->conn);
|
||||
SCPrintf(con, eLog, "send : %s", send);
|
||||
}
|
||||
return send;
|
||||
}
|
||||
}
|
||||
SCPrintf(con, eError, "ERROR: too many quick scripts chained");
|
||||
SCPrintf(con, eLogError, "ERROR: too many quick scripts chained");
|
||||
finish:
|
||||
SetProp(node, controller->node, "state", "idle");
|
||||
if (currentCon) {
|
||||
SCStorePop(currentCon);
|
||||
} else {
|
||||
SCStorePop(controller->conn);
|
||||
}
|
||||
if (data->conCtx != NULL) {
|
||||
SCStoreFree(data->conCtx);
|
||||
SCDeleteConnection(data->conCtx);
|
||||
data->conCtx = NULL;
|
||||
}
|
||||
return send;
|
||||
@ -337,7 +335,7 @@ finish:
|
||||
|
||||
static char *SctWriteHandler(void *actionData, char *lastReply) {
|
||||
SctData *data = actionData;
|
||||
SCStore *old;
|
||||
SConnection*old;
|
||||
char *result;
|
||||
|
||||
old = currentCon;
|
||||
@ -470,14 +468,12 @@ static hdbCallbackReturn SctActionCallback(Hdb *node, void *userData,
|
||||
}
|
||||
|
||||
if (data->conCtx != NULL) {
|
||||
con2 = SCStorePush(data->conCtx);
|
||||
GetHdbPath(node, path, sizeof path);
|
||||
SCPrintf(con2, eValue, "%s target changed to %s before completion",
|
||||
SCPrintf(data->conCtx, eLog, "%s target changed to %s before completion",
|
||||
path, GetCharArray(text));
|
||||
SCStorePop(data->conCtx);
|
||||
}
|
||||
DeleteDynString(text);
|
||||
data->conCtx = SCSave(con, data->conCtx);
|
||||
data->conCtx = SCCopyConnection(con);
|
||||
data->answered = 0;
|
||||
DevQueue(data->controller->devser, data, prio,
|
||||
SctWriteHandler, SctMatch, NULL);
|
||||
@ -490,12 +486,12 @@ static hdbCallbackReturn SctActionCallback(Hdb *node, void *userData,
|
||||
if (currentCon) { /* update called from a write action */
|
||||
data->answered = 1;
|
||||
GetHdbPath(node, path, sizeof path);
|
||||
con = SCStorePush(currentCon);
|
||||
con = currentCon;
|
||||
text = formatValue(*(mm->v), node);
|
||||
SCPrintf(con, eStatus, "%s = %s", path,
|
||||
/* Markus: who is receiving this message? */
|
||||
SCPrintf(con, eLog, "%s = %s", path,
|
||||
GetCharArray(text));
|
||||
DeleteDynString(text);
|
||||
SCStorePop(currentCon);
|
||||
}
|
||||
return hdbContinue;
|
||||
}
|
||||
@ -537,7 +533,7 @@ static void SctKillData(void *d) {
|
||||
SctData *data = d;
|
||||
|
||||
if (data->name) free(data->name);
|
||||
if (data->conCtx) SCStoreFree(data->conCtx);
|
||||
if (data->conCtx) SCDeleteConnection(data->conCtx);
|
||||
free(data);
|
||||
}
|
||||
|
||||
@ -564,7 +560,7 @@ int SctAddPollNode(SctController *controller, Hdb *node, double interval,
|
||||
assert(data);
|
||||
data->controller = controller;
|
||||
data->node = node;
|
||||
data->conCtx = NULL;
|
||||
data->conCtx = NULL; /* we might need a dummy connection here */
|
||||
data->name = strdup(action);
|
||||
|
||||
return DevSchedule(controller->devser, data, prio, interval,
|
||||
@ -755,10 +751,16 @@ void SctQueueNode(SctController *controller, Hdb *node,
|
||||
data->name = strdup(action);
|
||||
data->conCtx = NULL;
|
||||
|
||||
DevQueue(data->controller->devser, data, prio,
|
||||
SctWriteHandler, SctMatch, SctKillData);
|
||||
if (con != NULL) {
|
||||
data->conCtx = SCSave(con, NULL);
|
||||
if(!DevQueue(data->controller->devser, data, prio,
|
||||
SctWriteHandler, SctMatch, SctKillData)){
|
||||
if(data->name != NULL){
|
||||
free(data->name);
|
||||
}
|
||||
free(data);
|
||||
} else {
|
||||
if (con != NULL) {
|
||||
data->conCtx = SCCopyConnection(con);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -813,6 +815,9 @@ static void KillSctTransact(void *data){
|
||||
if(self->command){
|
||||
free(self->command);
|
||||
}
|
||||
if(self->con){
|
||||
SCDeleteConnection(self->con);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
|
||||
@ -844,7 +849,7 @@ static int SctTransactCmd(pSICSOBJ ccmd, SConnection *con,
|
||||
SCWrite(con,"ERROR: out of memory in SctTransactCommand", eError);
|
||||
return 0;
|
||||
}
|
||||
st->con = con;
|
||||
st->con = SCCopyConnection(con);
|
||||
st->command = strdup(par[0]->value.v.text);
|
||||
|
||||
DevQueue(c->devser, st, WritePRIO,
|
||||
@ -863,6 +868,8 @@ static int SctSendCmd(pSICSOBJ ccmd, SConnection *con,
|
||||
Hdb *cmdNode, Hdb *par[], int nPar) {
|
||||
pSctTransact st = NULL;
|
||||
SctController *c;
|
||||
char *prioText = NULL;
|
||||
int prio;
|
||||
|
||||
c = (SctController *)ccmd->pPrivate;
|
||||
|
||||
@ -871,14 +878,28 @@ static int SctSendCmd(pSICSOBJ ccmd, SConnection *con,
|
||||
SCWrite(con,"ERROR: out of memory in SctSendCmd", eError);
|
||||
return 0;
|
||||
}
|
||||
st->con = con;
|
||||
st->con = SCCopyConnection(con);
|
||||
st->command = strdup(par[0]->value.v.text);
|
||||
|
||||
DevQueue(c->devser, st, WritePRIO,
|
||||
prioText = ParText(cmdNode, "prio", nPar, "write");
|
||||
prio = DevText2Prio(prioText);
|
||||
if(prio == NullPRIO){
|
||||
prio = WritePRIO;
|
||||
}
|
||||
|
||||
DevQueue(c->devser, st, prio,
|
||||
TransactionHandler, SctTransactMatch, KillSctTransact);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int SctDisconnect(pSICSOBJ ccmd, SConnection *con,
|
||||
Hdb *cmdNode, Hdb *par[], int nPar) {
|
||||
SctController *c;
|
||||
|
||||
c = (SctController *)ccmd->pPrivate;
|
||||
DevDisconnect(c->devser);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static hdbCallbackReturn SctDebugCallback(Hdb *node, void *userData,
|
||||
hdbMessage *msg) {
|
||||
@ -911,9 +932,7 @@ static void SctKillController(void *c) {
|
||||
CleanStack(controller->node);
|
||||
RemoveSICSInternalCallback(controller);
|
||||
if (controller->conn) {
|
||||
con = SCLoad(controller->conn);
|
||||
SCDeleteConnection(con);
|
||||
SCStoreFree(controller->conn);
|
||||
SCDeleteConnection(controller->conn);
|
||||
}
|
||||
DevKill(controller->devser);
|
||||
free(controller);
|
||||
@ -943,7 +962,7 @@ static int SctMakeController(SConnection *con, SicsInterp *sics,
|
||||
|
||||
ccmd = MakeSICSOBJv(nodeName, "SctController", HIPNONE, usSpy);
|
||||
controller->node = ccmd->objectNode;
|
||||
controller->conn = SCSave(SCCreateDummyConnection(pServ->pSics), NULL);
|
||||
controller->conn = SCCreateDummyConnection(pServ->pSics);
|
||||
|
||||
assert(ccmd);
|
||||
assert(controller->node->mama == NULL);
|
||||
@ -992,8 +1011,11 @@ static int SctMakeController(SConnection *con, SicsInterp *sics,
|
||||
cmd = AddSICSHdbPar(controller->node,
|
||||
"send", usMugger, MakeSICSFunc(SctSendCmd));
|
||||
AddSICSHdbPar(cmd, "data", usMugger, MakeHdbText(""));
|
||||
AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText(""));
|
||||
|
||||
|
||||
cmd = AddSICSHdbPar(controller->node,
|
||||
"disconnect", usMugger, MakeSICSFunc(SctDisconnect));
|
||||
|
||||
par = AddSICSHdbPar(controller->node, "debug", usUser, MakeHdbInt(-1));
|
||||
|
||||
cb = MakeHipadabaCallback(SctDebugCallback, controller, NULL);
|
||||
|
14
selector.c
14
selector.c
@ -356,28 +356,28 @@ end:
|
||||
/* print known parameters */
|
||||
iLen = ObParLength(self->pParams);
|
||||
sprintf(pBueffel,"Parameter Listing for %s\n",self->name);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
for(i = 0; i < iLen; i++)
|
||||
{
|
||||
sprintf(pBueffel,"%s.%s = %f\n",self->name,
|
||||
self->pParams[i].name,self->pParams[i].fVal);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
|
||||
/* print motornames as well */
|
||||
sprintf(pBueffel,"%s.ThetaMotor = %s\n",self->name,self->pTheta->name);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
sprintf(pBueffel,"%s.TwoThetaMotor = %s\n",self->name,self->pTwoTheta->name);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
if(self->pBend1)
|
||||
{
|
||||
sprintf(pBueffel,"%s.VerticalBenderMotor = %s\n",self->name,self->pBend1->name);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
if(self->pBend2)
|
||||
{
|
||||
sprintf(pBueffel,"%s.HorizontalBenderMotor = %s\n",self->name,self->pBend2->name);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------
|
||||
@ -790,7 +790,7 @@ end:
|
||||
{
|
||||
sprintf(pBueffel,"WARNING: monochromator %s out of sync by %f\n",
|
||||
self->name,fVal);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eWarning);
|
||||
}
|
||||
|
||||
/* calculate wavelength from angles */
|
||||
|
22
selvar.c
22
selvar.c
@ -480,8 +480,7 @@
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int WaveLengthCallBack(int iEvent, void *pEvent, void *pUser,
|
||||
commandContext cc)
|
||||
static int WaveLengthCallBack(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
SConnection *pCon = NULL;
|
||||
pSelVar self = NULL;
|
||||
@ -493,9 +492,14 @@
|
||||
assert(pCon);
|
||||
assert(self);
|
||||
|
||||
if(pCon == NULL || !SCisConnected(pCon))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
fVal = GetSelValue(self,pCon);
|
||||
sprintf(pBueffel,"%s.value = %f", self->name, fVal);
|
||||
SCWriteInContext(pCon,pBueffel,eValue,cc);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------
|
||||
@ -527,10 +531,9 @@
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"interest") == 0)
|
||||
{
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),
|
||||
lID = RegisterCallback(self->pCall,
|
||||
WLCHANGE, WaveLengthCallBack,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
SCCopyConnection(pCon), SCDeleteConnection);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
@ -570,7 +573,7 @@
|
||||
{
|
||||
fWave = GetMonoPosition(self->pSel,pCon);
|
||||
sprintf(pBueffel,"%s = %f",argv[0],fWave);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@ -597,10 +600,9 @@
|
||||
strtolower(argv[1]);
|
||||
if(strcmp(argv[1],"interest") == 0)
|
||||
{
|
||||
lID = RegisterCallback(self->pCall, SCGetContext(pCon),
|
||||
lID = RegisterCallback(self->pCall,
|
||||
WLCHANGE, WaveLengthCallBack,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
@ -644,7 +646,7 @@
|
||||
fWave = 777.77;
|
||||
}
|
||||
sprintf(pBueffel,"%s = %f",argv[0],fWave);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -284,8 +284,8 @@
|
||||
{
|
||||
if( (pCurrent->iOut == eOut) || (pCurrent->iAllFlag == 1) )
|
||||
{
|
||||
NETWrite(pCurrent->pCon->pSock,pText,strlen(pText));
|
||||
NETWrite(pCurrent->pCon->pSock,"\n",1);
|
||||
ANETwrite(pCurrent->pCon->sockHandle,pText,strlen(pText));
|
||||
ANETwrite(pCurrent->pCon->sockHandle,"\n",1);
|
||||
}
|
||||
pCurrent = pCurrent->pNext;
|
||||
}
|
||||
|
280
sghkl.c
Normal file
280
sghkl.c
Normal file
@ -0,0 +1,280 @@
|
||||
/*
|
||||
Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#include "sginfo.h"
|
||||
|
||||
|
||||
static const char *IErr_Inc_SymMx =
|
||||
"Internal Error: Inconsistent symmetry matrices";
|
||||
|
||||
|
||||
int IsSysAbsent_hkl(const T_SgInfo *SgInfo,
|
||||
int h, int k, int l, int *TH_Restriction)
|
||||
{
|
||||
int iTrV, nTrV;
|
||||
const int *TrV;
|
||||
int iList, mh, mk, ml, hm, km, lm;
|
||||
int TH, THr, FlagMismatch;
|
||||
const T_RTMx *lsmx;
|
||||
|
||||
|
||||
mh = -h;
|
||||
mk = -k;
|
||||
ml = -l;
|
||||
|
||||
/* check list of symmetry operations
|
||||
take care of lattice type and "centric" flag */
|
||||
|
||||
THr = -1;
|
||||
if (TH_Restriction != NULL) *TH_Restriction = THr;
|
||||
FlagMismatch = 0;
|
||||
|
||||
nTrV = SgInfo->LatticeInfo->nTrVector;
|
||||
lsmx = SgInfo->ListSeitzMx;
|
||||
|
||||
for (iList = 0; iList < SgInfo->nList; iList++, lsmx++)
|
||||
{
|
||||
hm = lsmx->s.R[0] * h + lsmx->s.R[3] * k + lsmx->s.R[6] * l;
|
||||
km = lsmx->s.R[1] * h + lsmx->s.R[4] * k + lsmx->s.R[7] * l;
|
||||
lm = lsmx->s.R[2] * h + lsmx->s.R[5] * k + lsmx->s.R[8] * l;
|
||||
|
||||
TrV = SgInfo->LatticeInfo->TrVector;
|
||||
|
||||
for (iTrV = 0; iTrV < nTrV; iTrV++)
|
||||
{
|
||||
TH = (lsmx->s.T[0] + *TrV++) * h;
|
||||
TH += (lsmx->s.T[1] + *TrV++) * k;
|
||||
TH += (lsmx->s.T[2] + *TrV++) * l;
|
||||
TH %= STBF; if (TH < 0) TH += STBF;
|
||||
|
||||
if (mh == hm && mk == km && ml == lm)
|
||||
{
|
||||
if (TH != 0 && SgInfo->Centric == -1)
|
||||
return -(iList + 1 + iTrV * SgInfo->nList);
|
||||
|
||||
if (THr < 0)
|
||||
THr = TH;
|
||||
else if (THr != TH)
|
||||
FlagMismatch = 1; /* must be systematic absent */
|
||||
/* will check later ... */
|
||||
}
|
||||
else if ( h == hm && k == km && l == lm)
|
||||
{
|
||||
if (TH != 0)
|
||||
return (iList + 1 + iTrV * SgInfo->nList);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (THr >= 0 && FlagMismatch) /* ... consistency check */
|
||||
SetSgError(IErr_Inc_SymMx);
|
||||
|
||||
if (TH_Restriction != NULL)
|
||||
{
|
||||
if (SgInfo->Centric == -1) *TH_Restriction = 0;
|
||||
else *TH_Restriction = THr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int BuildEq_hkl(const T_SgInfo *SgInfo, T_Eq_hkl *Eq_hkl, int h, int k, int l)
|
||||
{
|
||||
int iList, hm, km, lm, i;
|
||||
T_RTMx *lsmx;
|
||||
T_Eq_hkl BufEq_hkl;
|
||||
|
||||
|
||||
if (Eq_hkl == NULL)
|
||||
Eq_hkl = &BufEq_hkl;
|
||||
|
||||
Eq_hkl->M = 1;
|
||||
Eq_hkl->N = 1;
|
||||
Eq_hkl->h[0] = h;
|
||||
Eq_hkl->k[0] = k;
|
||||
Eq_hkl->l[0] = l;
|
||||
Eq_hkl->TH[0] = 0;
|
||||
|
||||
if (! (h || k || l))
|
||||
return Eq_hkl->M; /* this is 000 */
|
||||
|
||||
Eq_hkl->M++;
|
||||
|
||||
/* check list of symmetry operations */
|
||||
|
||||
lsmx = &SgInfo->ListSeitzMx[1]; /* skip first = identity matrix */
|
||||
|
||||
for (iList = 1; iList < SgInfo->nList; iList++, lsmx++)
|
||||
{
|
||||
hm = lsmx->s.R[0] * h + lsmx->s.R[3] * k + lsmx->s.R[6] * l;
|
||||
km = lsmx->s.R[1] * h + lsmx->s.R[4] * k + lsmx->s.R[7] * l;
|
||||
lm = lsmx->s.R[2] * h + lsmx->s.R[5] * k + lsmx->s.R[8] * l;
|
||||
|
||||
for (i = 0; i < Eq_hkl->N; i++)
|
||||
{
|
||||
if ( ( hm == Eq_hkl->h[i] && km == Eq_hkl->k[i] && lm == Eq_hkl->l[i])
|
||||
|| (-hm == Eq_hkl->h[i] && -km == Eq_hkl->k[i] && -lm == Eq_hkl->l[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == Eq_hkl->N)
|
||||
{
|
||||
if (Eq_hkl->N >= 24) {
|
||||
SetSgError(IErr_Inc_SymMx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Eq_hkl->h[i] = hm;
|
||||
Eq_hkl->k[i] = km;
|
||||
Eq_hkl->l[i] = lm;
|
||||
|
||||
Eq_hkl->TH[i] = ( lsmx->s.T[0] * h
|
||||
+ lsmx->s.T[1] * k
|
||||
+ lsmx->s.T[2] * l) % STBF;
|
||||
if (Eq_hkl->TH[i] < 0)
|
||||
Eq_hkl->TH[i] += STBF;
|
||||
|
||||
Eq_hkl->M += 2;
|
||||
Eq_hkl->N++;
|
||||
}
|
||||
}
|
||||
|
||||
if (SgInfo->nList % Eq_hkl->N) /* another error trap */ {
|
||||
SetSgError(IErr_Inc_SymMx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Eq_hkl->M;
|
||||
}
|
||||
|
||||
|
||||
int AreSymEquivalent_hkl(const T_SgInfo *SgInfo, int h1, int k1, int l1,
|
||||
int h2, int k2, int l2)
|
||||
{
|
||||
int iList, mh2, mk2, ml2, hm, km, lm;
|
||||
T_RTMx *lsmx;
|
||||
|
||||
|
||||
mh2 = -h2;
|
||||
mk2 = -k2;
|
||||
ml2 = -l2;
|
||||
|
||||
/* check list of symmetry operations */
|
||||
|
||||
lsmx = SgInfo->ListSeitzMx;
|
||||
|
||||
for (iList = 0; iList < SgInfo->nList; iList++, lsmx++)
|
||||
{
|
||||
hm = lsmx->s.R[0] * h1 + lsmx->s.R[3] * k1 + lsmx->s.R[6] * l1;
|
||||
km = lsmx->s.R[1] * h1 + lsmx->s.R[4] * k1 + lsmx->s.R[7] * l1;
|
||||
lm = lsmx->s.R[2] * h1 + lsmx->s.R[5] * k1 + lsmx->s.R[8] * l1;
|
||||
|
||||
if ( h2 == hm && k2 == km && l2 == lm)
|
||||
return (iList + 1);
|
||||
|
||||
else if (mh2 == hm && mk2 == km && ml2 == lm)
|
||||
return -(iList + 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void SetListMin_hkl(const T_SgInfo *SgInfo, int Maxk, int Maxl,
|
||||
int *Minh, int *Mink, int *Minl)
|
||||
{
|
||||
*Minh = 0;
|
||||
|
||||
switch(SgInfo->XtalSystem)
|
||||
{
|
||||
case XS_Triclinic:
|
||||
*Mink = -Maxk;
|
||||
*Minl = -Maxl;
|
||||
break;
|
||||
case XS_Monoclinic:
|
||||
if (SgInfo->UniqueRefAxis == 'z')
|
||||
{
|
||||
*Mink = -Maxk;
|
||||
*Minl = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*Mink = 0;
|
||||
*Minl = -Maxl;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (SgInfo->XtalSystem == XS_Trigonal && SgInfo->UniqueDirCode == '*')
|
||||
*Mink = -Maxk;
|
||||
else
|
||||
*Mink = 0;
|
||||
*Minl = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int IsSuppressed_hkl(const T_SgInfo *SgInfo, int Minh, int Mink, int Minl,
|
||||
int Maxk, int Maxl,
|
||||
int h, int k, int l)
|
||||
{
|
||||
int iList, mate, hm, km, lm;
|
||||
T_RTMx *lsmx;
|
||||
|
||||
|
||||
/* check for Friedel mate first */
|
||||
|
||||
hm = -h, km = -k, lm = -l;
|
||||
|
||||
if ( (Minh <= hm && hm <= h)
|
||||
&& (Mink <= km && km <= Maxk)
|
||||
&& (Minl <= lm && lm <= Maxl)){
|
||||
if (hm < h) return -1;
|
||||
else /* if (h == 0) */
|
||||
if (km < k) return -1;
|
||||
else if (k == 0)
|
||||
if (lm < l) return -1;
|
||||
}
|
||||
|
||||
lsmx = &SgInfo->ListSeitzMx[1]; /* skip first = identity matrix */
|
||||
|
||||
for (iList = 1; iList < SgInfo->nList; iList++, lsmx++)
|
||||
{
|
||||
/* check if equivalent hm, km, lm are inside loop range ... */
|
||||
|
||||
hm = lsmx->s.R[0] * h + lsmx->s.R[3] * k + lsmx->s.R[6] * l;
|
||||
km = lsmx->s.R[1] * h + lsmx->s.R[4] * k + lsmx->s.R[7] * l;
|
||||
lm = lsmx->s.R[2] * h + lsmx->s.R[5] * k + lsmx->s.R[8] * l;
|
||||
|
||||
for (mate = 0; mate < 2; mate++)
|
||||
{
|
||||
if (mate) hm = -hm, km = -km, lm = -lm; /* ... or friedel mate */
|
||||
|
||||
if ( Minh <= hm && hm <= h
|
||||
&& Mink <= km && km <= Maxk
|
||||
&& Minl <= lm && lm <= Maxl)
|
||||
{
|
||||
/* ... and were processed before */
|
||||
|
||||
if (hm < h)
|
||||
return (mate ? -(iList + 1) : iList + 1);
|
||||
else /* if (hm == h) */
|
||||
if (km < k)
|
||||
return (mate ? -(iList + 1) : iList + 1);
|
||||
else if (km == k)
|
||||
if (lm < l)
|
||||
return (mate ? -(iList + 1) : iList + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
445
sgsi.c
Normal file
445
sgsi.c
Normal file
@ -0,0 +1,445 @@
|
||||
/*
|
||||
Space Group Info's (c) 1994-96 Ralf W. Grosse-Kunstleve
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef APP_INCLUDE
|
||||
#include APP_INCLUDE
|
||||
#endif
|
||||
|
||||
#ifndef AppMalloc
|
||||
#define AppMalloc(ptr, n) (ptr) = malloc((n) * sizeof (*(ptr)))
|
||||
#endif
|
||||
#ifndef AppFree
|
||||
#define AppFree(ptr, n) free(ptr)
|
||||
#endif
|
||||
|
||||
|
||||
#include "sginfo.h"
|
||||
|
||||
|
||||
/* Non elegant way to get s.i. vectors and moduli:
|
||||
1. Build field with legal reference points marked (TestField)
|
||||
2. Go through list of possible s.i. vects and mods:
|
||||
Verify with TestField
|
||||
*/
|
||||
|
||||
|
||||
void MarkLegalOrigins(const T_SgInfo *SgInfo, int *TestField)
|
||||
{
|
||||
int O[3], V[3], lx, ly, lz, mx, my, mz, i;
|
||||
int IsFine, iList, iLoopInv, nLoopInv;
|
||||
int BufMx[9];
|
||||
const T_RTMx *lsmx;
|
||||
int nTrV, iTrV;
|
||||
const int *TrV;
|
||||
|
||||
|
||||
nLoopInv = Sg_nLoopInv(SgInfo);
|
||||
|
||||
nTrV = SgInfo->LatticeInfo->nTrVector;
|
||||
|
||||
switch (SgInfo->LatticeInfo->Code)
|
||||
{
|
||||
default:
|
||||
case 'P': lx = ly = lz = 12; break;
|
||||
case 'A': lx = ly = 12; lz = 6; break;
|
||||
case 'B': ly = lz = 12; lx = 6; break;
|
||||
case 'C': lz = lx = 12; ly = 6; break;
|
||||
case 'I': lx = ly = 12; lz = 6; break;
|
||||
case 'R': lx = ly = 12; lz = 4; break;
|
||||
case 'S': lz = lx = 12; ly = 4; break;
|
||||
case 'T': ly = lz = 12; lx = 4; break;
|
||||
case 'F': lx = 12; ly = lz = 6; break;
|
||||
}
|
||||
|
||||
for (O[0] = 0; O[0] < 12; O[0]++)
|
||||
for (O[1] = 0; O[1] < 12; O[1]++)
|
||||
for (O[2] = 0; O[2] < 12; O[2]++)
|
||||
{
|
||||
IsFine = 1;
|
||||
|
||||
for (iList = 0; IsFine && iList < SgInfo->nList; iList++)
|
||||
{
|
||||
lsmx = &SgInfo->ListSeitzMx[iList];
|
||||
|
||||
for (iLoopInv = 0; IsFine && iLoopInv < nLoopInv; iLoopInv++)
|
||||
{
|
||||
if (iLoopInv == 0)
|
||||
for (i = 0; i < 9; i++)
|
||||
{
|
||||
if (i % 4) BufMx[i] = lsmx->s.R[i];
|
||||
else BufMx[i] = lsmx->s.R[i] - 1;
|
||||
}
|
||||
else
|
||||
for (i = 0; i < 9; i++)
|
||||
{
|
||||
if (i % 4) BufMx[i] = -lsmx->s.R[i];
|
||||
else BufMx[i] = -lsmx->s.R[i] - 1;
|
||||
}
|
||||
|
||||
RotMx_t_Vector(V, BufMx, O, 12);
|
||||
|
||||
TrV = SgInfo->LatticeInfo->TrVector;
|
||||
|
||||
for (iTrV = 0; iTrV < nTrV; iTrV++)
|
||||
{
|
||||
mx = (V[0] * (STBF / 12) + *TrV++) % STBF;
|
||||
my = (V[1] * (STBF / 12) + *TrV++) % STBF;
|
||||
mz = (V[2] * (STBF / 12) + *TrV++) % STBF;
|
||||
|
||||
if (mx == 0 && my == 0 && mz == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (iTrV == nTrV) IsFine = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (! (O[0] < lx && O[1] < ly && O[2] < lz))
|
||||
IsFine = -IsFine;
|
||||
|
||||
*TestField++ = IsFine;
|
||||
|
||||
#if DEBUG_MarkLegalOrigins
|
||||
if (IsFine == 1) putc(' ', stdout);
|
||||
else if (IsFine == -1) putc('#', stdout);
|
||||
if (IsFine != 0)
|
||||
fprintf(stdout, " %2d %2d %2d\n", O[0], O[1], O[2]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define IsArbitraryShift(iShift) \
|
||||
( (iShift) == 1 || (iShift) == 5 \
|
||||
|| (iShift) == 7 || (iShift) == 11)
|
||||
|
||||
|
||||
int Verify_si(int h, int k, int l, const int *TestField)
|
||||
{
|
||||
int O[3], TH;
|
||||
|
||||
|
||||
for (O[0] = 0; O[0] < 12; O[0]++)
|
||||
for (O[1] = 0; O[1] < 12; O[1]++)
|
||||
for (O[2] = 0; O[2] < 12; O[2]++)
|
||||
{
|
||||
if (*TestField++)
|
||||
{
|
||||
TH = h * O[0] + k * O[1] + l * O[2];
|
||||
TH %= 12;
|
||||
if (TH) return 0;
|
||||
|
||||
if (IsArbitraryShift(O[0])) TH += h;
|
||||
if (IsArbitraryShift(O[1])) TH += k;
|
||||
if (IsArbitraryShift(O[2])) TH += l;
|
||||
if (TH) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int Is_si(const T_SgInfo *SgInfo, int h, int k, int l)
|
||||
{
|
||||
int i_si_v, u;
|
||||
const int *si_v, *si_m;
|
||||
|
||||
|
||||
si_v = SgInfo->si_Vector;
|
||||
si_m = SgInfo->si_Modulus;
|
||||
|
||||
for (i_si_v = 0; i_si_v < SgInfo->n_si_Vector; i_si_v++)
|
||||
{
|
||||
u = *si_v++ * h;
|
||||
u += *si_v++ * k;
|
||||
u += *si_v++ * l;
|
||||
|
||||
if (*si_m) {
|
||||
if (u % (*si_m)) return 0; }
|
||||
else {
|
||||
if (u) return 0; }
|
||||
|
||||
si_m++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int Set_si(T_SgInfo *SgInfo)
|
||||
{
|
||||
static const int TabTrial_si[] =
|
||||
{
|
||||
0,
|
||||
|
||||
1, 0, 2, -1, 4, /* I -4 */
|
||||
1, 2, -1, 0, 4,
|
||||
1, -1, 0, 2, 4,
|
||||
|
||||
1, 2, 4, 3, 6, /* P 3 2 */
|
||||
1, 4, 3, 2, 6,
|
||||
1, 3, 2, 4, 6,
|
||||
|
||||
1, 1, 1, 1, 4,
|
||||
1, 1, 1, 1, 2,
|
||||
1, 1, 1, 1, 0,
|
||||
|
||||
1, 0, 0, 1, 2,
|
||||
1, 0, 1, 0, 2,
|
||||
1, 1, 0, 0, 2,
|
||||
|
||||
1, 0, 0, 1, 0,
|
||||
1, 0, 1, 0, 0,
|
||||
1, 1, 0, 0, 0,
|
||||
|
||||
2, 1, -1, 0, 3,
|
||||
0, 0, 1, 0,
|
||||
2, -1, 0, 1, 3,
|
||||
0, 1, 0, 0,
|
||||
2, 0, 1, -1, 3,
|
||||
1, 0, 0, 0,
|
||||
|
||||
2, 0, 1, 1, 4, /* F 2x */
|
||||
1, 0, 0, 0,
|
||||
2, 1, 0, 1, 4, /* F 2y */
|
||||
0, 1, 0, 0,
|
||||
2, 1, 1, 0, 4, /* F 2z */
|
||||
0, 0, 1, 0,
|
||||
|
||||
2, 1, 0, 0, 2,
|
||||
0, 0, 1, 2,
|
||||
2, 0, 1, 0, 2,
|
||||
0, 0, 1, 2,
|
||||
2, 1, 0, 0, 2,
|
||||
0, 1, 0, 2,
|
||||
|
||||
2, 1, 1, 0, 2,
|
||||
0, 0, 1, 2,
|
||||
2, 1, 0, 1, 2,
|
||||
0, 1, 0, 2,
|
||||
2, 0, 1, 1, 2,
|
||||
1, 0, 0, 2,
|
||||
|
||||
2, 1, 0, 0, 2,
|
||||
0, 0, 1, 0,
|
||||
2, 0, 1, 0, 2,
|
||||
0, 0, 1, 0,
|
||||
2, 1, 0, 0, 2,
|
||||
0, 1, 0, 0,
|
||||
|
||||
2, 1, 0, 0, 0,
|
||||
0, 0, 1, 2,
|
||||
2, 0, 1, 0, 0,
|
||||
0, 0, 1, 2,
|
||||
2, 1, 0, 0, 0,
|
||||
0, 1, 0, 2,
|
||||
|
||||
2, 1, 1, 0, 2,
|
||||
0, 0, 1, 0,
|
||||
2, 1, 0, 1, 2,
|
||||
0, 1, 0, 0,
|
||||
2, 0, 1, 1, 2,
|
||||
1, 0, 0, 0,
|
||||
|
||||
2, 1, 0, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
2, 0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
2, 1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
|
||||
3, 1, 0, 0, 2,
|
||||
0, 1, 0, 2,
|
||||
0, 0, 1, 2,
|
||||
|
||||
3, 1, 0, 0, 0,
|
||||
0, 1, 0, 2,
|
||||
0, 0, 1, 2,
|
||||
|
||||
3, 1, 0, 0, 2,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 2,
|
||||
|
||||
3, 1, 0, 0, 2,
|
||||
0, 1, 0, 2,
|
||||
0, 0, 1, 0,
|
||||
|
||||
3, 1, 0, 0, 2,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
|
||||
3, 1, 0, 0, 0,
|
||||
0, 1, 0, 2,
|
||||
0, 0, 1, 0,
|
||||
|
||||
3, 1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 2,
|
||||
|
||||
3, 1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
|
||||
3, -1, 0, 0, 2, /* -A 1 */
|
||||
0, -1, 1, 4,
|
||||
0, 1, 1, 4,
|
||||
|
||||
3, -1, 0, 1, 4, /* -B 1 */
|
||||
0, -1, 0, 2,
|
||||
1, 0, 1, 4,
|
||||
|
||||
3, 1, 1, 0, 4, /* -C 1 */
|
||||
1, -1, 0, 4,
|
||||
0, 0, -1, 2,
|
||||
|
||||
3, -1, 1, 1, 4, /* -I 1 */
|
||||
1, -1, 1, 4,
|
||||
1, 1, -1, 4,
|
||||
|
||||
3, 0, 1, 1, 4, /* -F 1 */
|
||||
1, 0, 1, 4,
|
||||
1, 1, 0, 4,
|
||||
|
||||
3, -1, 0, 0, 0, /* A 2x */
|
||||
0, -1, 1, 4,
|
||||
0, 1, 1, 4,
|
||||
|
||||
3, -1, 0, 1, 4, /* B 2y */
|
||||
0, -1, 0, 0,
|
||||
1, 0, 1, 4,
|
||||
|
||||
3, 1, 1, 0, 4, /* C 2z */
|
||||
1, -1, 0, 4,
|
||||
0, 0, -1, 0,
|
||||
|
||||
-1
|
||||
};
|
||||
|
||||
int h, k, l, iList;
|
||||
int Maxh, Maxk, Maxl;
|
||||
int Minh, Mink, Minl;
|
||||
int nTestField, *TestField;
|
||||
int nProperty, *Property, *pp;
|
||||
int IsFine, would_be, is;
|
||||
int i_si, *si_v;
|
||||
const int *trial_si;
|
||||
|
||||
|
||||
SgInfo->n_si_Vector = -1;
|
||||
|
||||
nTestField = 12 * 12 * 12;
|
||||
AppMalloc(TestField, nTestField);
|
||||
if (TestField == NULL) {
|
||||
SetSgError("Not enough core");
|
||||
return -1;
|
||||
}
|
||||
|
||||
MarkLegalOrigins(SgInfo, TestField);
|
||||
|
||||
Maxh = Maxk = Maxl = 7;
|
||||
SetListMin_hkl(SgInfo, Maxk, Maxl, &Minh, &Mink, &Minl);
|
||||
|
||||
nProperty = (Maxh - Minh + 1)
|
||||
* (Maxk - Mink + 1)
|
||||
* (Maxl - Minl + 1);
|
||||
AppMalloc(Property, nProperty);
|
||||
if (Property == NULL) {
|
||||
SetSgError("Not enough core");
|
||||
AppFree(TestField, nTestField);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pp = Property;
|
||||
for (h = Minh; h <= Maxh; h++)
|
||||
for (k = Mink; k <= Maxk; k++)
|
||||
for (l = Minl; l <= Maxl; l++)
|
||||
{
|
||||
iList = IsSysAbsent_hkl(SgInfo, h, k, l, NULL);
|
||||
if (SgError != NULL)
|
||||
{
|
||||
AppFree(Property, nProperty);
|
||||
AppFree(TestField, nTestField);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iList == 0)
|
||||
*pp++ = Verify_si(h, k, l, TestField);
|
||||
else
|
||||
*pp++ = -1;
|
||||
}
|
||||
|
||||
trial_si = TabTrial_si;
|
||||
while (*trial_si >= 0)
|
||||
{
|
||||
SgInfo->n_si_Vector = *trial_si++;
|
||||
si_v = SgInfo->si_Vector;
|
||||
for (i_si = 0; i_si < SgInfo->n_si_Vector; i_si++)
|
||||
{
|
||||
*si_v++ = *trial_si++;
|
||||
*si_v++ = *trial_si++;
|
||||
*si_v++ = *trial_si++;
|
||||
SgInfo->si_Modulus[i_si] = *trial_si++;
|
||||
}
|
||||
|
||||
IsFine = 1;
|
||||
|
||||
pp = Property;
|
||||
for (h = Minh; IsFine && h <= Maxh; h++)
|
||||
for (k = Mink; IsFine && k <= Maxk; k++)
|
||||
for (l = Minl; IsFine && l <= Maxl; l++)
|
||||
{
|
||||
is = *pp++;
|
||||
|
||||
if (is >= 0)
|
||||
{
|
||||
would_be = Is_si(SgInfo, h, k, l);
|
||||
if (is != would_be)
|
||||
IsFine = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsFine)
|
||||
{
|
||||
AppFree(Property, nProperty);
|
||||
AppFree(TestField, nTestField);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
SgInfo->n_si_Vector = -1;
|
||||
SetSgError("Internal Error: Can't determine s.i. vectors and moduli");
|
||||
|
||||
AppFree(Property, nProperty);
|
||||
AppFree(TestField, nTestField);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void Set_uvw(const T_SgInfo *SgInfo, int h, int k, int l, int *uvw)
|
||||
{
|
||||
int i_si_v, u;
|
||||
const int *si_v, *si_m;
|
||||
|
||||
|
||||
si_v = SgInfo->si_Vector;
|
||||
si_m = SgInfo->si_Modulus;
|
||||
|
||||
for (i_si_v = 0; i_si_v < SgInfo->n_si_Vector; i_si_v++)
|
||||
{
|
||||
u = *si_v++ * h;
|
||||
u += *si_v++ * k;
|
||||
u += *si_v++ * l;
|
||||
|
||||
if (*si_m) u %= (*si_m);
|
||||
si_m++;
|
||||
|
||||
uvw[i_si_v] = u;
|
||||
}
|
||||
}
|
@ -78,7 +78,7 @@
|
||||
StatisticsEnd(old);
|
||||
MacroPop();
|
||||
if (iRet != TCL_OK) {
|
||||
SCPrintf(self->pCon, eStatus,
|
||||
SCPrintf(self->pCon, eLogError,
|
||||
"ERROR in sicscron script: %s", pTcl->result);
|
||||
self->iEnd = 0;
|
||||
return 0;
|
||||
@ -114,12 +114,12 @@
|
||||
if (self->iEnd == 2 && data->dolater) {
|
||||
tm = *localtime(&self->tNext);
|
||||
strftime(datim, sizeof datim, "%Y-%m-%d %T", &tm);
|
||||
SCPrintf(data->pCon, eStatus, "%s %s", datim,
|
||||
SCPrintf(data->pCon, eLog, "%s %s", datim,
|
||||
self->pCommand);
|
||||
} else if (self->iEnd == 1 && !data->dolater) {
|
||||
tm = *localtime(&self->tNext);
|
||||
strftime(datim, sizeof datim, "%Y-%m-%d %T", &tm);
|
||||
SCPrintf(data->pCon, eStatus, "%s %8d %s", datim,
|
||||
SCPrintf(data->pCon, eLog, "%s %8d %s", datim,
|
||||
self->iInterval, self->pCommand);
|
||||
}
|
||||
}
|
||||
|
@ -53,8 +53,7 @@ static void AddPrivProperty(pHdb node, int priv){
|
||||
SetHdbProperty(node,PRIVNAM,pPriv);
|
||||
}
|
||||
/*=================== motor code =======================================*/
|
||||
static int MoveCallback(int iEvent, void *eventData, void *userData,
|
||||
commandContext cc){
|
||||
static int MoveCallback(int iEvent, void *eventData, void *userData){
|
||||
MotCallback *motData = (MotCallback *)eventData;
|
||||
pHdb motor = (pHdb)userData;
|
||||
pHdb pos = NULL;
|
||||
@ -71,8 +70,7 @@ static int MoveCallback(int iEvent, void *eventData, void *userData,
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int MotorValueCallback(int iEvent, void *eventData, void *userData,
|
||||
commandContext cc){
|
||||
static int MotorValueCallback(int iEvent, void *eventData, void *userData){
|
||||
pHdb motor = (pHdb)userData;
|
||||
pMotor pMot = (pMotor)eventData;
|
||||
pHdb current = NULL;
|
||||
@ -280,9 +278,9 @@ static pHdb CreateMotorAdapter(char *name, pMotor pMot){
|
||||
*/
|
||||
strncpy(comCom.deviceID,name,255);
|
||||
comCom.transID = -77;
|
||||
RegisterCallback(pMot->pCall,comCom, MOTDRIVE, MoveCallback,
|
||||
RegisterCallback(pMot->pCall,MOTDRIVE, MoveCallback,
|
||||
result,NULL);
|
||||
RegisterCallback(pMot->pCall,comCom, HDBVAL, MotorValueCallback,
|
||||
RegisterCallback(pMot->pCall,HDBVAL, MotorValueCallback,
|
||||
result,NULL);
|
||||
|
||||
if(!AddStdMotorPar(result,pMot)){
|
||||
@ -396,8 +394,7 @@ static hdbCallbackReturn SicsVarSetCallback(pHdb currentNode, void *userData,
|
||||
return hdbContinue;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int ValueCallback(int iEvent, void *eventData, void *userData,
|
||||
commandContext cc){
|
||||
static int ValueCallback(int iEvent, void *eventData, void *userData){
|
||||
pSicsVariable pVar = (pSicsVariable)eventData;
|
||||
pHdb node = (pHdb)userData;
|
||||
hdbValue v;
|
||||
@ -451,10 +448,8 @@ static pHdb MakeSicsVarNode(pSicsVariable pVar, char *name){
|
||||
if(pCall == NULL){
|
||||
return NULL;
|
||||
}
|
||||
strncpy(comCom.deviceID,name,255);
|
||||
comCom.transID = -77;
|
||||
AppendHipadabaCallback(node,pCall);
|
||||
RegisterCallback(pVar->pCall,comCom, VALUECHANGE, ValueCallback,
|
||||
RegisterCallback(pVar->pCall,VALUECHANGE, ValueCallback,
|
||||
node,NULL);
|
||||
snprintf(command,1023,"%s ", pVar->name);
|
||||
SetHdbProperty(node,"sicscommand",command);
|
||||
@ -503,8 +498,7 @@ static void updateCountList(){
|
||||
SCDeleteConnection(pDummy);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int CounterCallback(int iEvent, void *eventData, void *userData,
|
||||
commandContext cc){
|
||||
static int CounterCallback(int iEvent, void *eventData, void *userData){
|
||||
if(iEvent == MONITOR || iEvent == COUNTEND){
|
||||
updateCountList();
|
||||
}
|
||||
@ -714,13 +708,13 @@ int SICSHdbAdapter(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
hugo.node = path;
|
||||
if(countList < 0){
|
||||
countList = LLDcreate(sizeof(CountEntry));
|
||||
RegisterCallback(pCount->pCall, SCGetContext(pCon),
|
||||
RegisterCallback(pCount->pCall,
|
||||
COUNTSTART, CounterCallback,
|
||||
NULL, NULL);
|
||||
RegisterCallback(pCount->pCall, SCGetContext(pCon),
|
||||
RegisterCallback(pCount->pCall,
|
||||
COUNTEND, CounterCallback,
|
||||
NULL, NULL);
|
||||
RegisterCallback(pCount->pCall, SCGetContext(pCon),
|
||||
RegisterCallback(pCount->pCall,
|
||||
MONITOR, CounterCallback,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
@ -175,6 +175,7 @@ static int MakeLinkNode(pHdb parent, char *name, SConnection *pCon,
|
||||
assert(pInter);
|
||||
|
||||
/* print command to log files */
|
||||
/*
|
||||
for( i = 0; i < self->iFiles; i++)
|
||||
{
|
||||
if(self->pFiles[i])
|
||||
@ -182,7 +183,8 @@ static int MakeLinkNode(pHdb parent, char *name, SConnection *pCon,
|
||||
fprintf(self->pFiles[i],"SICS>> %s\n",pCommand);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/* print to command log if user or manager */
|
||||
if(SCGetRights(self) <= usUser)
|
||||
{
|
||||
@ -218,7 +220,7 @@ static hdbCallbackReturn CommandSetCallback(pHdb node, void *userData,
|
||||
if((mm = GetHdbSetMessage(message)) == NULL){
|
||||
return hdbContinue;
|
||||
}
|
||||
pCon = (SConnection *)pCon;
|
||||
pCon = (SConnection *)mm->callData;
|
||||
v = *(mm->v);
|
||||
|
||||
if(pCon == NULL){
|
||||
@ -245,7 +247,9 @@ static hdbCallbackReturn CommandSetCallback(pHdb node, void *userData,
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
SendHdbStatusMessage(node,"start");
|
||||
status = HDBInvoke(pCon,pServ->pSics, GetCharArray(cmd));
|
||||
SendHdbStatusMessage(node,"stop");
|
||||
DeleteDynString(cmd);
|
||||
if(status == 1){
|
||||
return hdbContinue;
|
||||
|
157
sicshipadaba.c
157
sicshipadaba.c
@ -17,6 +17,8 @@
|
||||
* interpreter interface.
|
||||
*
|
||||
* Refactored to new callback system, Markus Zolliker, Mark Koennecke, March 2008
|
||||
*
|
||||
* Added start and finished messages to commands. Mark Koennecke, November 2008
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -47,6 +49,8 @@ char *trim(char *str);
|
||||
static char killID[] = {"killID"};
|
||||
static char killInternalID[] = {"killInternalID"};
|
||||
static char killPtr[] = {"killPtr"};
|
||||
static char startID[] = {"start"};
|
||||
static char stopID[] = {"stop"};
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
pHdbIDMessage GetKillIDMessage(pHdbMessage message){
|
||||
if(message->type == killID){
|
||||
@ -68,7 +72,38 @@ pHdbPtrMessage GetKillPtrMessage(pHdbMessage message){
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
pHdbMessage GetHdbStartMessage(pHdbMessage message){
|
||||
if(message->type == startID){
|
||||
return (pHdbMessage)message;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
pHdbMessage GetHdbStopMessage(pHdbMessage message){
|
||||
if(message->type == stopID){
|
||||
return (pHdbMessage)message;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SendHdbStatusMessage(pHdb node, char *status){
|
||||
pHdbMessage pRes = NULL;
|
||||
pRes = malloc(sizeof(hdbMessage));
|
||||
if(pRes == NULL){
|
||||
return;
|
||||
}
|
||||
if(strcmp(status,"start") == 0){
|
||||
pRes->type = startID;
|
||||
} else if(strcmp(status,"stop") == 0){
|
||||
pRes->type = stopID;
|
||||
} else {
|
||||
/* someone is trying to create an non existent message */
|
||||
assert(0);
|
||||
}
|
||||
InvokeCallbackChain(node,pRes);
|
||||
free(pRes);
|
||||
}
|
||||
/*=============== common callback functions used for SICS ===========================*/
|
||||
static hdbCallbackReturn SICSCheckPermissionCallback(pHdb node, void *userData,
|
||||
pHdbMessage message){
|
||||
@ -274,8 +309,10 @@ static hdbCallbackReturn SICSFuncCallback(pHdb node, void *userData,
|
||||
}
|
||||
func = (SICSOBJFunc)node->value.v.func;
|
||||
if(func != NULL){
|
||||
SendHdbStatusMessage(node, "start");
|
||||
status = func((pSICSOBJ)userData,(SConnection *)mm->callData,
|
||||
node, par,nPar);
|
||||
SendHdbStatusMessage(node, "stop");
|
||||
} else {
|
||||
printf("Great Badness in calling SICSFuncCallback\n");
|
||||
return hdbAbort;
|
||||
@ -297,7 +334,6 @@ pHdbCallback MakeSICSReadDriveCallback(void *sicsObject){
|
||||
/*---------------------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
SConnection *pCon;
|
||||
commandContext context;
|
||||
int ID;
|
||||
int internalID;
|
||||
}HdbCBInfo;
|
||||
@ -438,6 +474,7 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
|
||||
pHdbIDMessage idm = NULL;
|
||||
pHdbPtrMessage cmm = NULL;
|
||||
pHdbDataMessage mm = NULL;
|
||||
SConnection *tstCon;
|
||||
|
||||
cbInfo = (HdbCBInfo *)userData;
|
||||
|
||||
@ -459,15 +496,41 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
|
||||
}
|
||||
}
|
||||
if((cmm = GetKillPtrMessage(message)) != NULL){
|
||||
if(cmm->pPtr == cbInfo->pCon){
|
||||
tstCon = cmm->pPtr;
|
||||
if(tstCon != NULL && tstCon->ident == cbInfo->pCon->ident){
|
||||
return hdbKill;
|
||||
} else {
|
||||
return hdbContinue;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* handle start and stop messages
|
||||
*/
|
||||
if(GetHdbStartMessage(message) != NULL){
|
||||
pPath = GetHipadabaPath(node);
|
||||
result = CreateDynString(128,128);
|
||||
DynStringConcat(result, pPath);
|
||||
DynStringConcat(result," STARTED");
|
||||
SCWrite(cbInfo->pCon, GetCharArray(result), eEvent);
|
||||
DeleteDynString(result);
|
||||
free(pPath);
|
||||
return hdbContinue;
|
||||
}
|
||||
|
||||
if(GetHdbStopMessage(message) != NULL){
|
||||
pPath = GetHipadabaPath(node);
|
||||
result = CreateDynString(128,128);
|
||||
DynStringConcat(result, pPath);
|
||||
DynStringConcat(result," FINISHED");
|
||||
SCWrite(cbInfo->pCon, GetCharArray(result), eEvent);
|
||||
DeleteDynString(result);
|
||||
free(pPath);
|
||||
return hdbContinue;
|
||||
}
|
||||
|
||||
/*
|
||||
* react only on update messages
|
||||
* Deal with update messages
|
||||
*/
|
||||
if((mm = GetHdbUpdateMessage(message)) == NULL){
|
||||
return hdbContinue;
|
||||
@ -481,20 +544,12 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
|
||||
outCode = eEvent;
|
||||
|
||||
|
||||
/*
|
||||
* we want our notifications to come even when called from a macro
|
||||
*/
|
||||
macro = SCinMacro(cbInfo->pCon);
|
||||
SCsetMacro(cbInfo->pCon,0);
|
||||
/**
|
||||
* if transfer = zip always transfer data in zipped form
|
||||
*/
|
||||
if(GetHdbProperty(node,"transfer",value,80) == 1){
|
||||
if(strstr(value,"zip") != NULL){
|
||||
SCPushContext2(cbInfo->pCon,cbInfo->context);
|
||||
status = sendZippedNodeData(node, cbInfo->pCon);
|
||||
SCPopContext(cbInfo->pCon);
|
||||
SCsetMacro(cbInfo->pCon,macro);
|
||||
free(pPath);
|
||||
DeleteDynString(result);
|
||||
return hdbContinue;
|
||||
@ -503,9 +558,8 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
|
||||
if(mm->v->arrayLength < 100){
|
||||
printedData = formatValue(*(mm->v), node);
|
||||
if(pPath == NULL || printedData == NULL || result == NULL){
|
||||
SCWriteInContext(cbInfo->pCon,"ERROR: out of memory formatting data" ,
|
||||
eEvent,cbInfo->context);
|
||||
SCsetMacro(cbInfo->pCon,macro);
|
||||
SCWrite(cbInfo->pCon,"ERROR: out of memory formatting data" ,
|
||||
eEvent);
|
||||
/*
|
||||
* no need to interrupt something because writing data to a client does
|
||||
* not work
|
||||
@ -514,33 +568,46 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
|
||||
}
|
||||
formatNameValue(protocol, pPath, GetCharArray(printedData), result,
|
||||
mm->v->dataType);
|
||||
SCWriteInContext(cbInfo->pCon,GetCharArray(result),
|
||||
outCode,cbInfo->context);
|
||||
SCWrite(cbInfo->pCon,GetCharArray(result),
|
||||
outCode);
|
||||
DeleteDynString(printedData);
|
||||
} else {
|
||||
formatNameValue(protocol, pPath,"!!datachange!!", result, HIPTEXT);
|
||||
SCWriteInContext(cbInfo->pCon,GetCharArray(result),
|
||||
outCode,cbInfo->context);
|
||||
SCWrite(cbInfo->pCon,GetCharArray(result),
|
||||
outCode);
|
||||
}
|
||||
SCsetMacro(cbInfo->pCon,macro);
|
||||
free(pPath);
|
||||
DeleteDynString(result);
|
||||
|
||||
return hdbContinue;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------------*/
|
||||
static void cbKill(void *pData){
|
||||
HdbCBInfo *cbInfo = (HdbCBInfo *)pData;
|
||||
if(cbInfo == NULL){
|
||||
return;
|
||||
}
|
||||
if(cbInfo->pCon != NULL){
|
||||
SCDeleteConnection(cbInfo->pCon);
|
||||
}
|
||||
free(cbInfo);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------------*/
|
||||
pHdbCallback MakeNotifyCallback(SConnection *pCon, int id){
|
||||
HdbCBInfo *cbInfo = NULL;
|
||||
HdbCBInfo *cbInfo = NULL;
|
||||
|
||||
cbInfo = malloc(sizeof(HdbCBInfo));
|
||||
if(cbInfo == NULL){
|
||||
return NULL;
|
||||
}
|
||||
cbInfo->pCon = pCon;
|
||||
cbInfo->context = SCGetContext(pCon);
|
||||
cbInfo->pCon = SCCopyConnection(pCon);
|
||||
if(cbInfo->pCon == NULL){
|
||||
return NULL;
|
||||
}
|
||||
SCsetMacro(cbInfo->pCon,0);
|
||||
cbInfo->ID = id;
|
||||
cbInfo->internalID = -1;
|
||||
return MakeHipadabaCallback(SICSNotifyCallback, cbInfo,free);
|
||||
return MakeHipadabaCallback(SICSNotifyCallback, cbInfo,cbKill);
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData,
|
||||
@ -553,6 +620,7 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData,
|
||||
pHdbIDMessage idm = NULL;
|
||||
pHdbPtrMessage cmm = NULL;
|
||||
pHdbTreeChangeMessage tm = NULL;
|
||||
SConnection *tstCon = NULL;
|
||||
|
||||
HdbCBInfo *cbInfo = (HdbCBInfo *)userData;
|
||||
|
||||
@ -574,7 +642,8 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData,
|
||||
}
|
||||
}
|
||||
if((cmm = GetKillPtrMessage(message)) != NULL){
|
||||
if(cmm->pPtr == cbInfo->pCon){
|
||||
tstCon = cmm->pPtr;
|
||||
if(tstCon != NULL && tstCon->ident == cbInfo->pCon->ident){
|
||||
return hdbKill;
|
||||
} else {
|
||||
return hdbContinue;
|
||||
@ -588,7 +657,7 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData,
|
||||
if(cbInfo != NULL && cbInfo->pCon != NULL){
|
||||
result = CreateDynString(128,128);
|
||||
if(result == NULL){
|
||||
SCWriteInContext(cbInfo->pCon,"ERROR: out of memory in TreeChangeCallback",outCode,cbInfo->context);
|
||||
SCWrite(cbInfo->pCon,"ERROR: out of memory in TreeChangeCallback",outCode);
|
||||
return hdbAbort;
|
||||
}
|
||||
path = GetHipadabaPath(node);
|
||||
@ -597,7 +666,7 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData,
|
||||
else
|
||||
outCode = eEvent;
|
||||
formatNameValue(protocol, "treechange", path, result, node->value.dataType);
|
||||
SCWriteInContext(cbInfo->pCon,GetCharArray(result),outCode,cbInfo->context);
|
||||
SCWrite(cbInfo->pCon,GetCharArray(result),outCode);
|
||||
DeleteDynString(result);
|
||||
free(path);
|
||||
}
|
||||
@ -611,10 +680,12 @@ pHdbCallback MakeTreeChangeCallback(SConnection *pCon, int id){
|
||||
if(cbInfo == NULL){
|
||||
return NULL;
|
||||
}
|
||||
cbInfo->pCon = pCon;
|
||||
cbInfo->context = SCGetContext(pCon);
|
||||
cbInfo->pCon = SCCopyConnection(pCon);
|
||||
if(cbInfo->pCon == NULL){
|
||||
return NULL;
|
||||
}
|
||||
cbInfo->ID = id;
|
||||
return MakeHipadabaCallback(TreeChangeCallback, cbInfo,free);
|
||||
return MakeHipadabaCallback(TreeChangeCallback, cbInfo,cbKill);
|
||||
}
|
||||
/*----------------------------------------------------------------------------------------*/
|
||||
static hdbCallbackReturn SICSScriptWriteCallback(pHdb node, void *userData,
|
||||
@ -1740,7 +1811,13 @@ pDynString formatValue(hdbValue v, pHdb node){
|
||||
snprintf(number,30,format, v.v.floatArray[i]);
|
||||
DynStringConcat(result,number);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case HIPFUNC:
|
||||
DynStringConcat(result,"FUNCTION");
|
||||
break;
|
||||
case HIPOBJ:
|
||||
DynStringConcat(result,"OBJECT");
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -2281,7 +2358,7 @@ static int GetHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
if ((protocol = isJSON(pCon)) == 1)
|
||||
outCode = eHdbEvent;
|
||||
else
|
||||
outCode = eEvent;
|
||||
outCode = eValue;
|
||||
|
||||
result = CreateDynString(128,128);
|
||||
formatNameValue(protocol, oriPath, GetCharArray(parData), result, newValue.dataType);
|
||||
@ -2322,7 +2399,7 @@ static int GetHdbVal(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
if ((protocol = isJSON(pCon)) == 1)
|
||||
outCode = eHdbEvent;
|
||||
else
|
||||
outCode = eEvent;
|
||||
outCode = eValue;
|
||||
SCWrite(pCon,GetCharArray(parData), outCode);
|
||||
DeleteDynString(parData);
|
||||
ReleaseHdbValue(&newValue);
|
||||
@ -2610,7 +2687,7 @@ static int ListHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
outCode = eHdbEvent;
|
||||
} else {
|
||||
listData = formatPlainList(node);
|
||||
outCode = eEvent;
|
||||
outCode = eValue;
|
||||
}
|
||||
}
|
||||
if(listData == NULL){
|
||||
@ -2801,6 +2878,7 @@ static int ChainHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
assert(pInter);
|
||||
|
||||
/* print command to log files */
|
||||
/*
|
||||
for( i = 0; i < self->iFiles; i++)
|
||||
{
|
||||
if(self->pFiles[i])
|
||||
@ -2808,7 +2886,8 @@ static int ChainHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
fprintf(self->pFiles[i],"SICS>> %s\n",pCommand);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/* print to command log if user or manager */
|
||||
if(SCGetRights(self) <= usUser)
|
||||
{
|
||||
@ -2841,10 +2920,14 @@ static hdbCallbackReturn CommandSetCallback(pHdb node, void *userData,
|
||||
pHdbDataMessage mm = NULL;
|
||||
hdbValue v;
|
||||
|
||||
/**
|
||||
* TODO: this is a duplicate: resolve. It is still here because the old
|
||||
* Hipadaba configuration commands still work
|
||||
*/
|
||||
if((mm = GetHdbSetMessage(message)) == NULL){
|
||||
return hdbContinue;
|
||||
}
|
||||
pCon = (SConnection *)pCon;
|
||||
pCon = (SConnection *)mm->callData;
|
||||
v = *(mm->v);
|
||||
|
||||
if(pCon == NULL){
|
||||
@ -2871,7 +2954,9 @@ static hdbCallbackReturn CommandSetCallback(pHdb node, void *userData,
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
SendHdbStatusMessage(node,"start");
|
||||
status = HDBInvoke(pCon,pServ->pSics, GetCharArray(cmd));
|
||||
SendHdbStatusMessage(node,"stop");
|
||||
DeleteDynString(cmd);
|
||||
if(status == 1){
|
||||
return hdbContinue;
|
||||
|
@ -34,6 +34,9 @@ typedef struct {
|
||||
}hdbPtrMessage, *pHdbPtrMessage;
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
pHdbPtrMessage GetKillPtrMessage(pHdbMessage message);
|
||||
pHdbMessage GetHdbStartMessage(pHdbMessage message);
|
||||
pHdbMessage GetHdbStopMessage(pHdbMessage message);
|
||||
void SendHdbStatusMessage(pHdb node, char *status);
|
||||
/*======================== data structure for automatic parameter update =======*/
|
||||
typedef struct {
|
||||
SConnection *pCon;
|
||||
@ -299,7 +302,7 @@ int SICSHdbGetPar(void *obj, SConnection *pCon, char *path, hdbValue *v);
|
||||
int SICSHdbUpdatePar(void *obj, SConnection *pCon, char *path, hdbValue v);
|
||||
/**
|
||||
* SICSHdbSetPar sets the value of a parameter.
|
||||
* @param obj The object for which to get a parameter.
|
||||
* @param obj The object for which to set a parameter.
|
||||
* @param pCon The optional connection object to use for reporting errors.
|
||||
* @param path The path to the parameter.
|
||||
* @param v the value
|
||||
|
112
sicsobj.c
112
sicsobj.c
@ -5,6 +5,7 @@
|
||||
*
|
||||
* Mark Koennecke, July 2007
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <sics.h>
|
||||
#include <tcl.h>
|
||||
#include "assert.h"
|
||||
@ -21,6 +22,50 @@ extern int decodeSICSPriv(char *txt); /* from access.c */
|
||||
void DefaultKill(void *data){
|
||||
return;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void DefaultFree(void *data){
|
||||
if(data != NULL){
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void saveSICSNode(pHdb node, char *prefix, FILE *fd){
|
||||
char newprefix[1024], val[20];
|
||||
pHdb child;
|
||||
hdbValue v;
|
||||
pDynString data = NULL;
|
||||
|
||||
if(GetHdbProperty(node,"__save",val,20) == 1){
|
||||
GetHipadabaPar(node,&v,NULL);
|
||||
data = formatValue(v,node);
|
||||
if(data != NULL){
|
||||
fprintf(fd,"%s %s\n", prefix, GetCharArray(data));
|
||||
DeleteDynString(data);
|
||||
}
|
||||
child = node->child;
|
||||
while(child != NULL){
|
||||
snprintf(newprefix,1024,"%s/%s", prefix,child->name);
|
||||
saveSICSNode(child,newprefix,fd);
|
||||
child = child->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int SaveSICSOBJ(void *data, char *name, FILE *fd){
|
||||
pSICSOBJ self = (pSICSOBJ)data;
|
||||
char prefix[1024];
|
||||
pHdb node;
|
||||
|
||||
if(self != NULL && self->objectNode != NULL){
|
||||
node = self->objectNode->child;
|
||||
while(node != NULL){
|
||||
snprintf(prefix, 1024,"%s %s", name, node->name);
|
||||
saveSICSNode(node, prefix, fd);
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
pSICSOBJ MakeSICSOBJv(char *name, char *class, int type, int priv){
|
||||
pSICSOBJ pNew = NULL;
|
||||
@ -32,12 +77,13 @@ pSICSOBJ MakeSICSOBJv(char *name, char *class, int type, int priv){
|
||||
}
|
||||
memset(pNew,0,sizeof(SICSOBJ));
|
||||
pNew->pDes = CreateDescriptor(class);
|
||||
pNew->pDes->SaveStatus = SaveSICSOBJ;
|
||||
if (type == HIPNONE) {
|
||||
pNew->objectNode = MakeHipadabaNode(name, HIPNONE, 1);
|
||||
} else {
|
||||
val = makeHdbValue(type,0);
|
||||
pNew->objectNode = MakeSICSHdbPar(name, priv, val);
|
||||
ReleaseHdbValue(&val);
|
||||
val = makeHdbValue(type,0);
|
||||
pNew->objectNode = MakeSICSHdbPar(name, priv, val);
|
||||
ReleaseHdbValue(&val);
|
||||
}
|
||||
if(pNew->pDes == NULL || pNew->objectNode == NULL){
|
||||
free(pNew);
|
||||
@ -87,7 +133,21 @@ static int invokeOBJFunction(pSICSOBJ object, pHdb commandNode, SConnection *pCo
|
||||
pHdb currentPar = NULL;
|
||||
SICSOBJFunc pFunc = NULL;
|
||||
pHdb parArray[64];
|
||||
|
||||
char buffer[1024];
|
||||
|
||||
/*
|
||||
* If the first argument has the special name args, concatenate all arguments
|
||||
* and put the result as text into this parameter. This allows for the
|
||||
* object function to parse and interpret the arguments itself.
|
||||
*/
|
||||
if(commandNode->child != NULL && strcmp(commandNode->child->name,"args") == 0) {
|
||||
Arg2Text(argc,argv,buffer,1024);
|
||||
assignPar(commandNode->child,pCon,buffer);
|
||||
parArray[0] = commandNode->child;
|
||||
count = 1;
|
||||
goto invoke;
|
||||
}
|
||||
|
||||
/*
|
||||
* assign parameters and fill parameter array for function at the same
|
||||
* time. Be lenient about missing parameters: Then the old values will
|
||||
@ -106,12 +166,14 @@ static int invokeOBJFunction(pSICSOBJ object, pHdb commandNode, SConnection *pCo
|
||||
count++;
|
||||
}
|
||||
|
||||
pFunc = (SICSOBJFunc)commandNode->value.v.func;
|
||||
invoke: pFunc = (SICSOBJFunc)commandNode->value.v.func;
|
||||
if(pFunc == NULL){
|
||||
SCWrite(pCon,"ERROR: internal error, function not found",eError);
|
||||
return 0;
|
||||
}
|
||||
SendHdbStatusMessage(commandNode,"start");
|
||||
status = pFunc(object, pCon, commandNode, parArray,count);
|
||||
SendHdbStatusMessage(commandNode,"stop");
|
||||
return status;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
@ -128,7 +190,7 @@ static int ScriptObjFunc(pSICSOBJ obj, SConnection *pCon, pHdb commandNode,
|
||||
GetHdbProperty(commandNode,"priv",value,256);
|
||||
status = decodeSICSPriv(value);
|
||||
if(!SCMatchRights(pCon,status)){
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(GetHdbProperty(commandNode,"script",value,256) != 1){
|
||||
@ -219,6 +281,42 @@ static int isNodePrintable(pHdb node){
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void objFormatNode(pHdb node, pDynString data){
|
||||
char par[40];
|
||||
pDynString val = NULL;
|
||||
|
||||
snprintf(par,40,"%-20s = ",node->name);
|
||||
DynStringConcat(data,par);
|
||||
val = formatValue(node->value,node);
|
||||
if(val != NULL){
|
||||
DynStringConcat(data,GetCharArray(val));
|
||||
DynStringConcatChar(data,'\n');
|
||||
DeleteDynString(val);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int ListObj(pSICSOBJ self, SConnection *pCon, int argc, char *argv[]){
|
||||
pHdb node = NULL;
|
||||
pDynString data;
|
||||
|
||||
data = CreateDynString(128,128);
|
||||
if(data == NULL){
|
||||
return 0;
|
||||
}
|
||||
node = self->pDes->parNode;
|
||||
if(node != NULL){
|
||||
objFormatNode(node,data);
|
||||
node = node->child;
|
||||
while(node != NULL){
|
||||
objFormatNode(node,data);
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
SCWrite(pCon,GetCharArray(data),eValue);
|
||||
DeleteDynString(data);
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int InvokeSICSOBJ(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pSICSOBJ self = NULL;
|
||||
@ -263,6 +361,8 @@ int InvokeSICSOBJ(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
if(status == -1){
|
||||
if(strcmp(argv[1],"makescriptfunc") == 0) {
|
||||
return MakeScriptFunc(self,pCon,argc,argv);
|
||||
} else if(strcmp(argv[1],"list") == 0){
|
||||
return ListObj(self,pCon,argc,argv);
|
||||
}
|
||||
SCPrintf(pCon, eError, "ERROR: %s %s not found", argv[0], argv[1]);
|
||||
}
|
||||
|
@ -29,7 +29,9 @@ pSICSOBJ MakeSICSOBJ(char *name, char *class);
|
||||
pSICSOBJ MakeSICSOBJv(char *name, char *class, int type, int priv);
|
||||
void KillSICSOBJ(void *data);
|
||||
void DefaultKill(void *data);
|
||||
void DefaultFree(void *data);
|
||||
|
||||
int SaveSICSOBJ(void *data, char *name, FILE *fd);
|
||||
|
||||
/**
|
||||
* This creates a new SICS object and installs it in the interpreter. It returns
|
||||
|
19
sicvar.c
19
sicvar.c
@ -345,8 +345,7 @@
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int VarInterestCallback(int iEvent, void *pEvent, void *pUser,
|
||||
commandContext cc)
|
||||
static int VarInterestCallback(int iEvent, void *pEvent, void *pUser)
|
||||
{
|
||||
SConnection *pCon;
|
||||
char pBueffel[512];
|
||||
@ -360,7 +359,13 @@
|
||||
|
||||
pVar = (pSicsVariable)pEvent;
|
||||
pCon = (SConnection *)pUser;
|
||||
SCPushContext2(pCon,cc);
|
||||
|
||||
/* check kill conditions */
|
||||
if(pCon == NULL || !SCisConnected(pCon))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch(pVar->eType)
|
||||
{
|
||||
case veInt:
|
||||
@ -386,7 +391,6 @@
|
||||
status = 1;
|
||||
break;
|
||||
}
|
||||
SCPopContext(pCon);
|
||||
return status;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
@ -536,17 +540,16 @@ static int VarSetFromText(pSicsVariable self, SConnection *pCon, char *text)
|
||||
}
|
||||
else if(strcmp(pCurrent->text,"interest") == 0) /* interest */
|
||||
{
|
||||
lID = RegisterCallback(pVar->pCall, SCGetContext(pCon),
|
||||
lID = RegisterCallback(pVar->pCall,
|
||||
VALUECHANGE, VarInterestCallback,
|
||||
pCon, NULL);
|
||||
SCRegister(pCon,pInterp, pVar->pCall,lID);
|
||||
SCCopyConnection(pCon), SCDeleteConnection);
|
||||
DeleteTokenList(pList);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
else if(strcmp(pCurrent->text,"uninterest") == 0)
|
||||
{
|
||||
RemoveCallback2(pVar->pCall,pCon);
|
||||
RemoveCallbackCon(pVar->pCall,pCon);
|
||||
DeleteTokenList(pList);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
|
@ -20,8 +20,8 @@
|
||||
#define RANDOMWARNING -7003
|
||||
#define STOPPED -7004
|
||||
|
||||
#define FAILRATE 0.05
|
||||
#define WARNRATE 0.1
|
||||
#define FAILRATE 0.00005
|
||||
#define WARNRATE 0.00001
|
||||
/*-----------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
time_t tTarget;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user