diff --git a/SICSmain.c b/SICSmain.c index f6187cf7..ae5bdf88 100644 --- a/SICSmain.c +++ b/SICSmain.c @@ -23,6 +23,7 @@ #include "nserver.h" #include "servlog.h" +extern void KeepStartupCommands(); /* ofac.c */ /***************************** Necessary Globals ****************************/ IPair *pSICSOptions = NULL; @@ -47,6 +48,8 @@ int main(int argc, char *argv[]) for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-nolog") == 0) { SICSLogEnable(0); + }else if(strcmp(argv[i],"-keepstartup") == 0){ + KeepStartupCommands(); } else if (file == NULL) { file = argv[i]; } diff --git a/confvirtualmot.c b/confvirtualmot.c index c930f23f..6215a6ad 100644 --- a/confvirtualmot.c +++ b/confvirtualmot.c @@ -14,14 +14,14 @@ - a checkscript to be run at the end of driving the motor - a means to call the write script multiple times. This is useful if you need to drive to the value in multiple steps. An example is the - BOA double crystal monochromator where you first have to pu the baldes to + BOA double crystal monochromator where you first have to put the blades to 0, then drive the translation and then drive the blades to the real theta. All this to avoid collisions. In order to support this, a state field and and a readable target field has been added. The mode of operation is such that the on first run the, writescript set the state to something different then idle. This causes after the first set of motors finished running the writescript to be called again. This can figure out by lookin at the - state variable what to do. This can be doen in repetition until the + state variable what to do. This can be done in repetition until the writescript sets state to idle again. Mark Koennecke, April 2012 diff --git a/counter.c b/counter.c index c6b6ab5b..345aabeb 100644 --- a/counter.c +++ b/counter.c @@ -61,7 +61,7 @@ typedef struct { char *pName; } MonEvent, *pMonEvent; -/*--------------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------------*/ static int Halt(void *pData) { pCounter self = NULL; @@ -444,12 +444,13 @@ int MakeCounter(SConnection * pCon, SicsInterp * pSics, void *pData, assert(pCon); assert(pSics); - argtolower(argc, argv); if (argc < 3) { SCWrite(pCon, "ERROR: insuficient number of arguments to MakeCounter", eError); return 0; } + strtolower(argv[1]); + strtolower(argv[2]); site = getSite(); if (site != NULL) { pDriv = site->CreateCounterDriver(pCon, argc, argv); diff --git a/devexec.c b/devexec.c index 8f90a07f..6d25ca25 100644 --- a/devexec.c +++ b/devexec.c @@ -17,6 +17,10 @@ Modified to accommodate run levels Mark Koennecke, April 2009 + + Heavily restructured to use separate tasks for each action + + Mark Koennecke, February 2013 Copyright: @@ -118,75 +122,24 @@ void DevexecLog(char *operation, char *device) traceDevice("devexec","%s:%s",device, operation); } -/*======================== internal data structures =======================*/ -typedef struct _DevEntry { - void *pData; - pObjectDescriptor pDescriptor; - float fVal; - char *name; - SConnection *pCon; - int level; -} DevEntry, *pDevEntry; -/*------------------------------------------------------------------------*/ -typedef struct { - pExeList self; - pDevEntry pDev; - pICountable pCountInt; - pIDrivable pDrivInt; -} checkContext, *pCheckContext; -/*-------------------------------------------------------------------------*/ -static pDevEntry CreateDevEntry(pObjectDescriptor pDes, SConnection * pCon, - void *pData, float fVal, char *name, int level) -{ - pDevEntry pNew = NULL; - - assert(pDes); - - pNew = (pDevEntry) malloc(sizeof(DevEntry)); - if (!pNew) { - return NULL; - } - pNew->pDescriptor = pDes; - pNew->pData = pData; - pNew->name = strdup(name); - pNew->fVal = fVal; - pNew->pCon = SCCopyConnection(pCon); - pNew->pCon->runLevel = level; - pNew->level = level; - return pNew; -} - -/*-------------------------------------------------------------------------*/ -static void DeleteDevEntry(pDevEntry self) -{ - assert(self); - - if (self->name) { - free(self->name); - } - if (self->pCon) { - SCDeleteConnection(self->pCon); - } - free(self); -} /* ----------------- The Executor himself ---------------------------------*/ typedef struct __EXELIST { pObjectDescriptor pDes; SConnection *pOwner; - int iList; int iRun; - int iStop; int iStatus; - int iEnd; int drivePrint; long lTask; + long waitID; + long runID; pTaskMan pTask; int iLock; pICallBack pCall; time_t lastRun; int paused; int taskRunning; + int instStatus; } ExeList; static pExeList pExecutor = NULL; @@ -222,15 +175,11 @@ pExeList CreateExeList(pTaskMan pTask) free(pRes); return NULL; } - pRes->iList = LLDcreate(sizeof(pDevEntry)); - if (pRes->iList == -1) { - free(pRes); - return NULL; - } - pRes->iRun = 0; pRes->iStatus = DEVDONE; pRes->pTask = pTask; pRes->lTask = -1; + pRes->waitID = -1; + pRes->runID = -1; pRes->iLock = 0; pRes->drivePrint = 0; pRes->paused = 0; @@ -252,7 +201,6 @@ void DeleteExeList(void *pData) if (self->pDes) DeleteDescriptor(self->pDes); ClearExecutor(self); - LLDdelete(self->iList); if (self->pCall) DeleteCallBackInterface(self->pCall); @@ -268,16 +216,13 @@ void DeleteExeList(void *pData) devLog = NULL; } } - /*--------------------------------------------------------------------------*/ -void ExeInterest(pExeList self, pDevEntry pDev, char *text) +void ExeInterest(pExeList self, char *name, char *text) { char buf[128]; - if (pDev) { - snprintf(buf, sizeof(buf), "%s %s", pDev->name, text); - InvokeCallBack(self->pCall, DRIVSTAT, buf); - } + snprintf(buf, sizeof(buf), "%s %s", name, text); + InvokeCallBack(self->pCall, DRIVSTAT, buf); } /*------------------------------------------------------------------------*/ void InvokeNewTarget(pExeList self, char *name, float target) @@ -295,14 +240,15 @@ void InvokeNewTarget(pExeList self, char *name, float target) int StartDevice(pExeList self, char *name, pObjectDescriptor pDes, void *pData, SConnection * pCon, int level, float fNew) { - pDevEntry pNew = NULL; - int iRet; + int iRet; char pBueffel[132], pError[80]; pIDrivable pDrivInt = NULL; pICountable pCountInt = NULL; static int overwriteOwner = -1; char *overwriteOption; float oldVal; + long taskID; + pTaskGroupData taskGroup = NULL; assert(self); assert(pDes); @@ -335,65 +281,57 @@ int StartDevice(pExeList self, char *name, pObjectDescriptor pDes, return 0; } - /* well create a new entry */ - self->iStop = 0; - pNew = CreateDevEntry(pDes, pCon, pData, fNew, name, level); - if (!pNew) { - SCWrite(pCon, "ERROR: memory exhausted in Device Executor ", eError); - return 0; + if(self->waitID < 0 && level == RUNDRIVE){ + self->waitID = GetTaskGroupID(pServ->pTasker); + self->iStatus = DEVBUSY; + } else if(self->runID < 0 && level == RUNRUN){ + self->runID = GetTaskGroupID(pServ->pTasker); + self->iStatus = DEVBUSY; } - /* start it */ - pDrivInt = pDes->GetInterface(pData, DRIVEID); - pCountInt = pDes->GetInterface(pData, COUNTID); - if (pDrivInt) { - iRet = pDrivInt->SetValue(pData, pCon, fNew); - if (iRet == OKOK && self->drivePrint == 1) { + + + if((pDrivInt = pDes->GetInterface(pData,DRIVEID)) != NULL){ + taskID = StartDriveTask(pData, pCon, name, fNew); + if(self->instStatus != eCounting){ + self->instStatus = eDriving; + SetStatus(eDriving); + } + if(taskID > 0 && self->drivePrint == 1){ oldVal = pDrivInt->GetValue(pData, pCon); snprintf(pBueffel, 131, "Driving %s from %8.3f to %8.3f", name, oldVal, fNew); SCWrite(pCon, pBueffel, eValue); } - if(iRet == OKOK){ - InvokeNewTarget(self,name,fNew); - } - } else if (pCountInt) { - iRet = pCountInt->StartCount(pData, pCon); - } else { /* this is a programmers error */ - SCWrite(pCon, "ERROR: Programmer error in StartDevice ", eError); - iRet = 0; + } else if(pDes->GetInterface(pData,COUNTID) != NULL){ + taskID = StartCountTask(pData,pCon,name); + self->instStatus = eCounting; + SetStatus(eCounting); + } else { + SCPrintf(pCon,eLogError, "ERROR: type unkonw, cannot start %s", name); + return 0; } - /* check return status */ - if (iRet == OKOK) { - LLDnodeAppendFrom(self->iList, &pNew); - sprintf(pBueffel, "started"); - if (NULL != pNew->pCon->deviceID) { - snprintf(pBueffel, 130, "started (%s)", pNew->pCon->deviceID); + if(taskID > 0){ + self->lastRun = time(NULL); + if(level == RUNRUN){ + AddTaskToGroup(pServ->pTasker, taskID, self->runID); + } else { + AddTaskToGroup(pServ->pTasker, taskID, self->waitID); } - ExeInterest(self, pNew, pBueffel); self->iRun = 1; - self->iStatus = DEVDONE; - /* if no task: start it */ - if (self->lTask < 0) { + self->iStatus = DEVBUSY; + if(self->lTask < 0) { self->lTask = TaskRegisterN(self->pTask,"devexec", DevExecTask, - DevExecSignal, NULL, self, 1); - self->iEnd = 0; - pCon->conStatus = HWBusy; + DevExecSignal, + NULL, self,1); } - DevexecLog("START", pNew->name); + pCon->conStatus = HWBusy; return 1; } else { snprintf(pBueffel,131, "ERROR: cannot start device %s", name); SCWrite(pCon, pBueffel, eError); - DeleteDevEntry(pNew); - if (LLDcheck(self->iList) >= LIST_EMPTY) { - if (self->pOwner != NULL) { - SCDeleteConnection(self->pOwner); - } - self->pOwner = NULL; - } return 0; } return 0; @@ -406,97 +344,18 @@ int StartDevice(pExeList self, char *name, pObjectDescriptor pDes, static int ForceStartDevice(pExeList self, char *name, pObjectDescriptor pDes, void *pData, SConnection * pCon, float fNew) { - pDevEntry pNew = NULL; - int iRet; - char pBueffel[132], pError[80]; + long taskID; pIDrivable pDrivInt = NULL; - pICountable pCountInt = NULL; - static int overwriteOwner = -1; - char *overwriteOption; - float oldVal; - assert(self); - assert(pDes); - assert(pCon); - - /* may we? */ - if (self->pOwner != NULL) { - pCon = self->pOwner; - } - if (self->iLock == 1) { - SCWrite(pCon, "ERROR: instrument is locked", eError); - return 0; - } - - /* well create a new entry */ - self->iStop = 0; - pNew = CreateDevEntry(pDes, SCCopyConnection(pCon), - pData, fNew, name, RUNRUN); - if (!pNew) { - SCWrite(pCon, "ERROR: memory exhausted in Device Executor ", eError); - return 0; - } - - /* start it */ - pDrivInt = pDes->GetInterface(pData, DRIVEID); - pCountInt = pDes->GetInterface(pData, COUNTID); - if (pDrivInt) { - iRet = pDrivInt->SetValue(pData, pCon, fNew); - if (iRet == OKOK && self->drivePrint == 1) { - oldVal = pDrivInt->GetValue(pData, pCon); - snprintf(pBueffel, 131, "Driving %s from %8.3f to %8.3f", - name, oldVal, fNew); - SCWrite(pCon, pBueffel, eValue); - } - if(iRet == OKOK){ - InvokeNewTarget(self,name,fNew); - } - } else if (pCountInt) { - /** - * Cannot set count parameters here: means of getting hold of the - * count mode missing here. As this is a POLDI hack where I only need - * to run a HV, I omit this now. But it will work if a proper - * preset and mode is set on a counter to start it. - */ - iRet = pCountInt->StartCount(pData, pCon); - } else { /* this is a programmers error */ - SCWrite(pCon, "ERROR: Programmer error in StartDevice ", eError); - iRet = 0; - } - - /* check return status */ - if (iRet == OKOK) { - LLDnodeAppendFrom(self->iList, &pNew); - sprintf(pBueffel, "started"); - if (NULL != pNew->pCon->deviceID) { - snprintf(pBueffel, 130, "started (%s)", pNew->pCon->deviceID); - } - ExeInterest(self, pNew, pBueffel); - self->iRun = 1; - self->iStatus = DEVDONE; - /* if no task: start it */ - if (self->lTask < 0) { - self->lTask = TaskRegisterN(self->pTask,"devexec", - DevExecTask, - DevExecSignal, NULL, self, 1); - self->iEnd = 0; - pCon->conStatus = HWBusy; - } - DevexecLog("START", pNew->name); - return 1; + if((pDrivInt = pDes->GetInterface(pData,DRIVEID)) != NULL){ + taskID = StartDriveTask(pData, pCon, name, fNew); + } else if(pDes->GetInterface(pData,COUNTID) != NULL){ + taskID = StartCountTask(pData,pCon,name); } else { - snprintf(pBueffel,131, "ERROR: cannot start device %s", name); - SCWrite(pCon, pBueffel, eError); - DeleteDevEntry(pNew); - if (LLDcheck(self->iList) >= LIST_EMPTY) { - if (self->pOwner != NULL) { - SCDeleteConnection(self->pOwner); - } - self->pOwner = NULL; - } + SCPrintf(pCon,eLogError, "ERROR: type unkonw, cannot start %s", name); return 0; } - return 0; + return 1; } /*--------------------------------------------------------------------------*/ int StartMotor(pExeList self, SicsInterp * pSics, SConnection * pCon, @@ -578,232 +437,21 @@ int StartCounter(pExeList self, SicsInterp * pSics, SConnection * pCon, pCon, level, pCter->pDriv->fPreset); } -/*-------------------------------------------------------------------------*/ -static int checkInterrupt(pCheckContext pCheck, int targetStatus) -{ - if (SCGetInterrupt(pCheck->self->pOwner) != eContinue) { - pCheck->self->iStatus = DEVINT; - SetStatus(eEager); - return -1; - } else { - return targetStatus; - } -} - -/*--------------------------------------------------------------------------*/ -static int initializeCheck(pCheckContext pCheck, pDevEntry pDev) -{ - int eCode = HWFault; - - 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, pDev->pCon); - } else if (pCheck->pCountInt != NULL) { - eCode = pCheck->pCountInt->CheckCountStatus(pDev->pData, pDev->pCon); - } - return eCode; -} - -/*--------------------------------------------------------------------------*/ -static int finishDevice(pCheckContext pCheck) -{ - int status; - - if (pCheck->pCountInt != NULL) { - pCheck->pCountInt->TransferData(pCheck->pDev->pData, - pCheck->pDev->pCon); - } else if (pCheck->pDrivInt != NULL) { - pCheck->pDrivInt->iErrorCount = 0; - } - ExeInterest(pCheck->self, pCheck->pDev, "finished"); - DevexecLog("STOP", pCheck->pDev->name); - DeleteDevEntry(pCheck->pDev); - LLDnodeDelete(pCheck->self->iList); - status = LLDnodePtr2Prev(pCheck->self->iList); - SCWrite(pCheck->self->pOwner, "", eFinish); - pCheck->self->iStatus = DEVDONE; - return checkInterrupt(pCheck, status); -} - -/*-------------------------------------------------------------------------*/ -static int errorDevice(pCheckContext pCheck) -{ - int status; - - ExeInterest(pCheck->self, pCheck->pDev, "finished with problem"); - DevexecLog("STOP", pCheck->pDev->name); - LLDnodeDelete(pCheck->self->iList); - status = LLDnodePtr2Prev(pCheck->self->iList); - SCWrite(pCheck->self->pOwner, "", eFinish); - pCheck->self->iStatus = DEVERROR; - if (pCheck->pDrivInt != NULL) { - pCheck->pDrivInt->iErrorCount++; - } - status = checkInterrupt(pCheck, status); - DeleteDevEntry(pCheck->pDev); - return status; -} - -/*-------------------------------------------------------------------------*/ -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; - self->iStop = 0; - self->lTask = -1; - return 1; - } else { - return 0; - } -} - -/*--------------------------------------------------------------------------*/ -int CheckExeList(pExeList self) -{ - int iRet, status; - checkContext check; - pDevEntry pDev = NULL; - pICountable pCountInt = NULL; - pIDrivable pDrivInt = NULL; - int eCode; - int isCounting = 0, isDriving = 0; - char pBueffel[512]; - - 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 (testFinish(self) == 1) { - return 1; - } - - /* - check the status of all registered devices. Remove when finished - */ - check.self = self; - status = LLDnodePtr2First(self->iList); - while (status != 0) { - LLDnodeDataTo(self->iList, &pDev); - if (pDev) { - eCode = initializeCheck(&check, pDev); - if (eCode != HWNoBeam && eCode != HWPause && self->paused == 1) { - DevexecLog("CONTINUE", "ALL"); - self->paused = 0; - } - switch (eCode) { - case HWIdle: - case OKOK: - status = finishDevice(&check); - if (status < 0) { - return status; - } - break; - case HWFault: /* real HW error: burning, no net etc.. */ - status = errorDevice(&check); - if (status < 0) { - return status; - } - break; - case HWNoBeam: - SetStatus(eOutOfBeam); - if (self->paused == 0) { - self->paused = 1; - DevexecLog("NOBEAM", "ALL"); - } - status = checkInterrupt(&check, 1); - if (status < 0) { - return status; - } - break; - case HWPause: - SetStatus(ePaused); - if (self->paused == 0) { - self->paused = 1; - DevexecLog("PAUSE", "ALL"); - } - status = checkInterrupt(&check, 1); - if (status < 0) { - /* - * continue in order to wait for devices to come to a stop - */ - ContinueExecution(self); - return status; - } - break; - case HWBusy: - if (check.pDrivInt != NULL) { - isDriving = 1; - } else if (check.pCountInt != NULL) { - isCounting = 1; - } - self->iStatus = DEVBUSY; - break; - case HWPosFault: /* cannot get somewhere... */ - status = errorDevice(&check); - if (status < 0) { - return status; - } - break; - } - } - status = LLDnodePtr2Next(self->iList); - } - - if (isCounting) { - if (isDriving) { - SetStatus(eCountDrive); - } else { - SetStatus(eCounting); - } - } else if (isDriving) { - SetStatus(eDriving); - } - - iRet = LLDnodePtr2First(self->iList); - return testFinish(self); -} -/*-------------------------------------------------------------------------- -Cludge to not move the current pointer for CheckExeList -*/ -void *LLDgetCurrent(int List); -void LLDsetCurrent(int List, void *pointer); /*---------------------------------------------------------------------------*/ int DevExecLevelRunning(pExeList self, int level) { - int iRet; - pDevEntry pDev = NULL; - void *current; - - if(self->lTask < 0){ - return 0; - } - current = LLDgetCurrent(self->iList); - iRet = LLDnodePtr2First(self->iList); - while (iRet != 0) { - LLDnodeDataTo(self->iList, &pDev); - if (pDev) { - if(pDev->level >= level){ - LLDsetCurrent(self->iList,current); - return 1; - } + if(level == RUNRUN){ + if(isTaskGroupRunning(self->pTask, self->runID)){ + return 1; } - iRet = LLDnodePtr2Next(self->iList); - } - LLDsetCurrent(self->iList,current); + } else if(level == RUNDRIVE){ + if(isTaskGroupRunning(self->pTask, self->waitID)){ + return 1; + } + } return 0; } - /*---------------------------------------------------------------------------*/ int Wait4Success(pExeList self) { @@ -819,7 +467,7 @@ int Wait4Success(pExeList self) /* wait for Devexec task to finish */ /*TaskWait(self->pTask, self->lTask); */ - while(DevExecLevelRunning(self,RUNDRIVE)){ + while(isTaskIDRunning(self->pTask,self->lTask)){ TaskYield(self->pTask); } #ifdef DEBUG @@ -829,40 +477,6 @@ int Wait4Success(pExeList self) return self->iStatus; } -/*--------------------------------------------------------------------------*/ -int ListPending(pExeList self, SConnection * pCon) -{ - int iRet, i; - char pBueffel[512]; - pDevEntry pDev = NULL; - - assert(self); - assert(pCon); - - /* first make sure that the list is fully updated */ - iRet = CheckExeList(self); - if (iRet == 1) { /* nothing to do! */ - SCWrite(pCon, "Machine idle", eValue); - return 1; - } else if (iRet == -1) { - SCWrite(pCon, "Handling Interrupt", eError); - return 0; - } - - - /* search the list for entries */ - iRet = LLDnodePtr2First(self->iList); - while (iRet != 0) { - LLDnodeDataTo(self->iList, &pDev); - if (pDev) { - sprintf(pBueffel, "\t%s %f", pDev->name, pDev->fVal); - SCWrite(pCon, pBueffel, eValue); - } - iRet = LLDnodePtr2Next(self->iList); - } - return 1; -} - /* -----------------------------------------------------------------------*/ long GetDevexecID(pExeList self) { @@ -874,121 +488,26 @@ long GetDevexecID(pExeList self) /*--------------------------------------------------------------------------*/ int StopExe(pExeList self, char *name) { - int i, iRet; - pDevEntry pDev = NULL; - pIDrivable pDrivInt = NULL; - pICountable pCountInt = NULL; + int interrupt = 3; + assert(self); /* if not active, nothing to do */ - if ((self->pOwner == NULL) || (LLDcheck(self->iList) == LIST_EMPTY)) { + if ((self->pOwner == NULL) ) { self->iRun = 0; return 1; } + + TaskSignalGroup(self->pTask, SICSINT, &interrupt, self->waitID); - /* first the ALL case */ - if (strcmp(name, "all") == 0) { - /* - check for stop flag. This is to stop unnecessary calls to StopExe. - There may be way to many, but each call is reasonable under certain - circumstances. - */ - if (self->iStop == 1) { - return 0; - } else { - self->iStop = 1; - } - - iRet = LLDnodePtr2First(self->iList); - while (iRet != 0) { - pDev = (pDevEntry) LLDnodePtr(self->iList); - if (pDev) { - pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData, DRIVEID); - pCountInt = pDev->pDescriptor->GetInterface(pDev->pData, COUNTID); - if (pDrivInt) { - pDrivInt->Halt(pDev->pData); - } else if (pCountInt) { - pCountInt->Halt(pDev->pData); - } - } - iRet = LLDnodePtr2Next(self->iList); - } - SCWrite(self->pOwner, "ERROR: Full Stop called!!", eLogError); - if (SCGetInterrupt(self->pOwner) > eContinue) { - self->iStatus = DEVINT; - } - return 1; - } - - /* now the special case: a well defined command */ - iRet = LLDnodePtr2First(self->iList); - while (iRet != 0) { - pDev = (pDevEntry) LLDnodePtr(self->iList); - if (pDev) { - if (strcmp(pDev->name, name) == 0) { - pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData, DRIVEID); - pCountInt = pDev->pDescriptor->GetInterface(pDev->pData, COUNTID); - if (pDrivInt) { - pDrivInt->Halt(pDev->pData); - } else if (pCountInt) { - pCountInt->Halt(pDev->pData); - } - return 1; - } - } - iRet = LLDnodePtr2Next(self->iList); - } - - return 0; -} - -/*-------------------------------------------------------------------------*/ -int StopByData(pExeList self, void *data) -{ - int iRet; - pDevEntry pDev = NULL; - pIDrivable pDrivInt = NULL; - pICountable pCountInt = NULL; - - iRet = LLDnodePtr2First(self->iList); - while (iRet != 0) { - pDev = (pDevEntry) LLDnodePtr(self->iList); - if (pDev) { - if (pDev->pData == data) { - pDrivInt = pDev->pDescriptor->GetInterface(pDev->pData, DRIVEID); - pCountInt = pDev->pDescriptor->GetInterface(pDev->pData, COUNTID); - if (pDrivInt) { - pDrivInt->Halt(pDev->pData); - } else if (pCountInt) { - pCountInt->Halt(pDev->pData); - } - /* - This is wrong: most devices will require some time - before they really stop. CheckExeList has to run... - This causes core dumps...... - - Mark - - ExeInterest(self, pDev, "finished"); - DevexecLog("FINISHED", pDev->name); - DeleteDevEntry(pDev); - LLDnodeDelete(self->iList); - self->iStatus = DEVDONE; - SCWrite(self->pOwner, "", eFinish); - */ - return 1; - } - } - iRet = LLDnodePtr2Next(self->iList); - } - return 0; + return 1; } /*-------------------------------------------------------------------------*/ int StopExeWait(pExeList self) { StopExe(self, "all"); - while(DevExecLevelRunning(self,RUNRUN)){ + while(isTaskIDRunning(self->pTask, self->lTask)){ TaskYield(self->pTask); } return 1; @@ -996,102 +515,51 @@ int StopExeWait(pExeList self) /*--------------------------------------------------------------------------*/ int PauseExecution(pExeList self) { - int i, iRet, iRes; - pDevEntry pDev = NULL; - pICountable pCountInt = NULL; + int interrupt = 0; + assert(self); + + + TaskSignalGroup(self->pTask, IPAUSE, &interrupt, self->waitID); - /* step through the list */ - iRes = 1; - iRet = LLDnodePtr2First(self->iList); - while (iRet != 0) { - pDev = (pDevEntry) LLDnodePtr(self->iList); - if (pDev) { - pCountInt = pDev->pDescriptor->GetInterface(pDev->pData, COUNTID); - if (pCountInt) { - iRet = pCountInt->Pause(pDev->pData, pDev->pCon); - if (!iRet) { - iRes = 0; - } - } - - } - iRet = LLDnodePtr2Next(self->iList); - } SetStatus(ePaused); - return iRes; + return 1; } -/*------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------ + check, may be obsolete +*/ int IsCounting(pExeList self) { - int iRet; - pDevEntry pDev = NULL; - pICountable pCountInt = NULL; assert(self); /* step through the list */ - iRet = LLDnodePtr2First(self->iList); - while (iRet != 0) { - pDev = (pDevEntry) LLDnodePtr(self->iList); - if (pDev) { - pCountInt = pDev->pDescriptor->GetInterface(pDev->pData, COUNTID); - if (pCountInt) { - return 1; - } - } - iRet = LLDnodePtr2Next(self->iList); - } + if(self->instStatus == eCounting){ + return 1; + } return 0; } /*--------------------------------------------------------------------------*/ int ContinueExecution(pExeList self) { - int i, iRet, iRes; - pDevEntry pDev = NULL; - pICountable pCountInt = NULL; + int interrupt = 0; assert(self); - /* step through the list */ - iRes = 1; - iRet = LLDnodePtr2First(self->iList); - while (iRet != 0) { - pDev = (pDevEntry) LLDnodePtr(self->iList); - if (pDev) { - pCountInt = pDev->pDescriptor->GetInterface(pDev->pData, COUNTID); - if (pCountInt) { - iRet = pCountInt->Continue(pDev->pData, pDev->pCon); - if (!iRet) { - iRes = 0; - } - } - } - iRet = LLDnodePtr2Next(self->iList); - } + TaskSignalGroup(self->pTask, CONTINUE, &interrupt, self->waitID); + SetStatus(eCounting); - return iRes; + return 1; } /*------------------------------------------------------------------------*/ void ClearExecutor(pExeList self) { int iRet; - pDevEntry pDev = NULL; assert(self); - iRet = LLDnodePtr2First(self->iList); - while (iRet != 0) { - pDev = (pDevEntry) LLDnodePtr(self->iList); - if (pDev) { - DeleteDevEntry(pDev); - } - LLDnodeDelete(self->iList); - iRet = LLDnodePtr2Prev(self->iList); - iRet = LLDnodePtr2Next(self->iList); - } if (self->pOwner) { if (SCGetInterrupt(self->pOwner) > eContinue) { self->iStatus = DEVINT; @@ -1099,8 +567,8 @@ void ClearExecutor(pExeList self) SCDeleteConnection(self->pOwner); } self->pOwner = NULL; - self->iEnd = 1; self->lTask = -1; + self->waitID = -1; self->iRun = 0; self->iLock = 0; } @@ -1125,10 +593,6 @@ int StopCommand(SConnection * pCon, SicsInterp * pSics, void *pData, argtolower(argc, argv); self = (pExeList) pData; - if (argc < 2) { - ListPending(self, pCon); - return 1; - } iRet = StopExe(self, argv[1]); if (!iRet) { @@ -1151,7 +615,37 @@ static int DrivStatCallback(int iEvent, void *text, void *pCon) SCWrite(pCon, text, eLog); return 1; } +/*---------------------------------------------------------------------------*/ +int ListPending(pExeList self, SConnection *pCon) +{ + pDynString buffer; + pTaskHead it = NULL; + long id; + if(self->lTask < 0){ + SCWrite(pCon,"Machine Idle",eValue); + return 1; + } + + buffer = CreateDynString(128,128); + if(buffer == NULL){ + SCWrite(pCon,"ERROR: out of memory in Listpending",eError); + return 0; + } + + for(it = TaskIteratorStart(self->pTask); it != NULL; it = TaskIteratorNext(it)){ + id = GetGroupID(it); + if(id == self->waitID || id == self->runID){ + DynStringConcat(buffer,(char *)GetTaskName(it)); + DynStringConcatChar(buffer,'\n'); + } + } + + SCWrite(pCon,GetCharArray(buffer),eValue); + DeleteDynString(buffer); + return 1; + +} /*--------------------------------------------------------------------------*/ int ListExe(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) @@ -1354,70 +848,37 @@ SConnection *GetExeOwner(pExeList self) return self->pOwner; } - /*--------------------------------------------------------------------------*/ int DevExecTask(void *pData) { pExeList self = NULL; - char pBueffel[132], pInterrupt[80]; - int iRet, iInterrupt; - self = (pExeList) pData; - /* am I bound to end ? */ - if (self->iEnd) { - self->lTask = -1; - SetStatus(eEager); - return 0; - } + assert(self != NULL); - if (self->taskRunning == 1) { - printf("DevexecTask reentrant protection triggered\n"); + if(isTaskGroupRunning(self->pTask,self->waitID) + || isTaskGroupRunning(self->pTask,self->runID)){ + self->iStatus = DEVBUSY; return 1; } + /* - * CheckExeList may cause waits and thus reentrant calls to - * this. Which can cause trouble - */ - self->taskRunning = 1; - iRet = CheckExeList(self); - self->taskRunning = 0; - - - self->lastRun = time(NULL); - switch (iRet) { - case -1: /* some problem */ - iInterrupt = SCGetInterrupt(self->pOwner); - if (iInterrupt != eContinue) { - if (iInterrupt > 1) { - self->taskRunning = 1; - StopExe(self, "all"); - self->taskRunning = 0; - } -#ifdef DEBUG - printf("DevExecTask found an error\n"); -#endif - return 1; - } else { - return 1; - } - break; - case 1: /* Success */ - self->lTask = -1; - self->iEnd = 1; - SetStatus(eEager); -#ifdef DEBUG - printf("DevExecTask finishes on success\n"); -#endif - return 0; - break; - default: /* continue, still busy */ - return 1; + We are done, clean up + */ + self->waitID = -1; + self->lTask = -1; + self->instStatus = eEager; + SetStatus(eEager); + if(SCGetInterrupt(self->pOwner) != eContinue){ + self->iStatus = DEVINT; + } else { + self->iStatus = DEVDONE; } - /* should not get here */ - return 1; -} + SCDeleteConnection(self->pOwner); + self->pOwner = NULL; + return 0; +} /*---------------------------------------------------------------------------*/ void DevExecSignal(void *pEL, int iSignal, void *pSigData) { @@ -1428,34 +889,14 @@ void DevExecSignal(void *pEL, int iSignal, void *pSigData) self = (pExeList) pEL; assert(self); - if (iSignal == SICSINT) { - iInt = (int *) pSigData; - if (*iInt != eContinue) { - if (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(pCon, *iInt); - SCSetInterrupt(self->pOwner, *iInt); - SCDeleteConnection(pCon); - } - } - StopExe(self, "all"); - } - } + TaskSignalGroup(self->pTask,iSignal, pSigData, self->waitID); } - /*--------------------------------------------------------------------*/ void LockDeviceExecutor(pExeList self) { assert(self); self->iLock = 1; } - /*--------------------------------------------------------------------*/ void UnlockDeviceExecutor(pExeList self) { diff --git a/devexec.h b/devexec.h index 3a8a1668..da926660 100644 --- a/devexec.h +++ b/devexec.h @@ -184,5 +184,7 @@ */ void *GetExecutorCallback(pExeList self); /*----------------------- Logging -----------------------------------------*/ - void DevexecLog(char *op, char *device); + void DevexecLog(char *op, char *device); + void ExeInterest(pExeList pExe, char *name, char *action); + void InvokeNewTarget(pExeList pExe, char *name, float fTarget); #endif diff --git a/devexec.tex b/devexec.tex index 1539537a..708e2f1a 100644 --- a/devexec.tex +++ b/devexec.tex @@ -373,7 +373,9 @@ to the global SICS device executor. \mbox{}\verb@ */ @\\ \mbox{}\verb@ void *GetExecutorCallback(pExeList self);@\\ \mbox{}\verb@/*----------------------- Logging -----------------------------------------*/@\\ -\mbox{}\verb@ void DevexecLog(char *op, char *device); @\\ +\mbox{}\verb@ void DevexecLog(char *op, char *device);@\\ +\mbox{}\verb@ void ExeInterest(pExeList pExe, char *name, char *action); @\\ +\mbox{}\verb@ void InvokeNewTarget(pExeList pExe, char *name, float fTarget);@\\ \mbox{}\verb@#endif @\\ \mbox{}\verb@@$\Diamond$ \end{list} diff --git a/devexec.w b/devexec.w index 0f2cca05..62426a56 100644 --- a/devexec.w +++ b/devexec.w @@ -319,7 +319,9 @@ to the global SICS device executor. */ void *GetExecutorCallback(pExeList self); /*----------------------- Logging -----------------------------------------*/ - void DevexecLog(char *op, char *device); + void DevexecLog(char *op, char *device); + void ExeInterest(pExeList pExe, char *name, char *action); + void InvokeNewTarget(pExeList pExe, char *name, float fTarget); #endif @} diff --git a/difrac.c b/difrac.c deleted file mode 100644 index 8b3213fd..00000000 --- a/difrac.c +++ /dev/null @@ -1,481 +0,0 @@ -/*------------------------------------------------------------------------- - D I F R A C - - A four-circle diffractometer requires sophicticated procedures for - searching peaks, orienting crystals and for performing data collection. - Rather then invent all of this again the DIFRAC-F77 program written by - Peter White and Eric Gabe has been incoporated into SICS. This module - provides the C-language side of the interface between DIFRAC and SICS. - DIFRAC can only be included once into SICS, it is not possible to have - more then one copy of this. This is why there is file static global data - here. - - copyright: see copyright.h - - Mark Koennecke, November 1999 - --------------------------------------------------------------------------*/ -#include -#include -#include -#include "fortify.h" -#include "sics.h" -#include "motor.h" -#include "counter.h" -#include "status.h" -#include "splitter.h" -#include "difrac.h" - -/*-------------------------------------------------------------------------- - In order to deal with multiple request to the DIFRAC subsystem we need to - keep the connection objects on a stack. This stack is defined here. - ---------------------------------------------------------------------------*/ -#define MAXSTACK 50 - -static SConnection *ConStack[MAXSTACK]; -static int iConStackPtr = -1; - -/*-------------------------------------------------------------------------- - In order to do the four circle work we need to know the motors of the - eulerian cradle and access to the counter. Furthermore we need to know - about the omega2theta motor and the scanning routine. - These data structures are initialized by the installation routine. - ---------------------------------------------------------------------------*/ - -static pMotor pTTH, pOM, pCHI, pPHI; -static pCounter counter; -/*--------------------------------------------------------------------------- - The following routines will be called from F77. Their names take care of the - system dependent name mangling scheme for calling C from F77. This may - need adjustment when porting to another system - ---------------------------------------------------------------------------*/ -/*========= read angles */ -void sicsanget_(float *fTH, float *fOM, float *fCHI, float *fPHI) -{ - int iRet; - - /* this is just security, may never happen */ - if (iConStackPtr < 0) { - return; - } - if (ConStack[iConStackPtr] == NULL) { - return; - } - - iRet = MotorGetSoftPosition(pTTH, ConStack[iConStackPtr], fTH); - if (iRet != 1) { - SCWrite(ConStack[iConStackPtr], - "ERROR: failed to read two theta, DIFRAC may be confused now", - eError); - } - iRet = MotorGetSoftPosition(pOM, ConStack[iConStackPtr], fOM); - if (iRet != 1) { - SCWrite(ConStack[iConStackPtr], - "ERROR: failed to read omega, DIFRAC may be confused now", - eError); - } - iRet = MotorGetSoftPosition(pCHI, ConStack[iConStackPtr], fCHI); - if (iRet != 1) { - SCWrite(ConStack[iConStackPtr], - "ERROR: failed to read chi, DIFRAC may be confused now", - eError); - } - iRet = MotorGetSoftPosition(pPHI, ConStack[iConStackPtr], fPHI); - if (iRet != 1) { - SCWrite(ConStack[iConStackPtr], - "ERROR: failed to read two theta, DIFRAC may be confused now", - eError); - } -} - -#define ABS(x) (x < 0 ? -(x) : (x)) -/*=========== check angles */ -void sicsangcheck_(float *fTH, float *fOM, float *fCHI, float *fPHI, - int *iInvalid) -{ - int iRet; - SConnection *pCon = NULL; - float fHard; - char pBueffel[256], pError[131]; - - /* this is just security, may never happen */ - if (iConStackPtr < 0) { - return; - } - if (ConStack[iConStackPtr] == NULL) { - return; - } - pCon = ConStack[iConStackPtr]; - - *iInvalid = 0; - iRet = MotorCheckBoundary(pTTH, *fTH, &fHard, pError, 131); - if (iRet != 1) { - sprintf(pBueffel, - "ERROR: %6.2f %6.2f %6.2f %6.2f violates twotheta limits", - *fTH, *fOM, *fCHI, *fPHI); - SCWrite(pCon, pBueffel, eError); - *iInvalid = 4; - return; - } - iRet = MotorCheckBoundary(pOM, *fOM, &fHard, pError, 131); - if (iRet != 1) { - sprintf(pBueffel, - "ERROR: %6.2f %6.2f %6.2f %6.2f violates omega limits", - *fTH, *fOM, *fCHI, *fPHI); - SCWrite(pCon, pBueffel, eError); - *iInvalid = 4; - return; - } - iRet = MotorCheckBoundary(pCHI, *fCHI, &fHard, pError, 131); - if (iRet != 1) { - sprintf(pBueffel, - "ERROR: %6.2f %6.2f %6.2f %6.2f violates chi limits", - *fTH, *fOM, *fCHI, *fPHI); - SCWrite(pCon, pBueffel, eError); - *iInvalid = 4; - return; - } - iRet = MotorCheckBoundary(pPHI, *fPHI, &fHard, pError, 131); - if (iRet != 1) { - sprintf(pBueffel, - "ERROR: %6.2f %6.2f %6.2f %6.2f violates phi limits", - *fTH, *fOM, *fCHI, *fPHI); - SCWrite(pCon, pBueffel, eError); - *iInvalid = 4; - return; - } -} - -/*======== set angles */ -void sicsangset_(float *fTTH, float *fOM, float *fCHI, float *fPHI, - int *icol) -{ - pDummy pDum; - int iRet; - SConnection *pCon = NULL; - float fT1, fT2, fT3, fT4; - - *icol = 0; - - /* this is just security, may never happen */ - if (iConStackPtr < 0) { - return; - } - if (ConStack[iConStackPtr] == NULL) { - return; - } - pCon = ConStack[iConStackPtr]; - - - /* check if this is possible, if not complain */ - sicsangcheck_(fTTH, fOM, fCHI, fPHI, &iRet); - if (iRet >= 4) { - *icol = 1; - return; - } - - /* start */ - pDum = (pDummy) pTTH; - iRet = StartDevice(pServ->pExecutor, "TTH", - pDum->pDescriptor, pDum, pCon, *fTTH); - if (!iRet) { - SCWrite(pCon, "ERROR: cannot start two theta motor", eError); - StopExe(pServ->pExecutor, "all"); - *icol = 10; - } - pDum = (pDummy) pOM; - iRet = StartDevice(pServ->pExecutor, "OM", - pDum->pDescriptor, pDum, pCon, *fOM); - if (!iRet) { - SCWrite(pCon, "ERROR: cannot start omega motor", eError); - StopExe(pServ->pExecutor, "all"); - *icol = 10; - } - pDum = (pDummy) pCHI; - iRet = StartDevice(pServ->pExecutor, "CHI", - pDum->pDescriptor, pDum, pCon, *fCHI); - if (!iRet) { - SCWrite(pCon, "ERROR: cannot start chi motor", eError); - StopExe(pServ->pExecutor, "all"); - *icol = 10; - } - pDum = (pDummy) pPHI; - iRet = StartDevice(pServ->pExecutor, "PHI", - pDum->pDescriptor, pDum, pCon, *fPHI); - if (!iRet) { - SCWrite(pCon, "ERROR: cannot start two theta motor", eError); - StopExe(pServ->pExecutor, "all"); - *icol = 10; - } - - /* wait for end of it */ - iRet = Wait4Success(pServ->pExecutor); - switch (iRet) { - case DEVINT: - if (SCGetInterrupt(pCon) == eAbortOperation) { - SCSetInterrupt(pCon, eContinue); - SCSetError(pCon, OKOK); - } - break; - case DEVDONE: - break; - default: - break; - } - - /* - As TRICS has such a shitty cradle check angles and report error - if bad - */ - sicsanget_(&fT1, &fT2, &fT3, &fT4); - if (ABS(fT1 - *fTTH) > .2) { - *icol = 10; - } - if (ABS(fT2 - *fOM) > .2) { - *icol = 10; - } - if (ABS(fT3 - *fCHI) > .2) { - *icol = 10; - } - if (ABS(fT4 - *fPHI) > .2) { - *icol = 10; - } -} - -/*=========== count */ -void sicscount_(float *fPreset, float *fCounts) -{ - pDummy pDum; - int iRet; - SConnection *pCon = NULL; - long lTask; - - /* this is just security, may never happen */ - if (iConStackPtr < 0) { - return; - } - if (ConStack[iConStackPtr] == NULL) { - return; - } - pCon = ConStack[iConStackPtr]; - - pDum = (pDummy) counter; - SetCounterPreset(counter, *fPreset); - iRet = StartDevice(pServ->pExecutor, - "DifracCount", - pDum->pDescriptor, counter, pCon, *fPreset); - if (!iRet) { - SCWrite(pCon, "ERROR: Failed to start counting ", eError); - return; - } - SetStatus(eCounting); - /* wait for finish */ - lTask = GetDevexecID(pServ->pExecutor); - if (lTask > 0); - { - TaskWait(pServ->pTasker, lTask); - } - *fCounts = (float) GetCounts(counter, pCon); -} - -/*========= sicswrite */ -void sicswrite_(int *iText, int *iLen) -{ - SConnection *pCon = NULL; - char pBueffel[256]; - int i; - - if (*iLen > 255) - return; - - for (i = 0; i < *iLen; i++) { - pBueffel[i] = (char) iText[i]; - } - pBueffel[i] = '\0'; - - /* this is just security, may never happen */ - if (iConStackPtr < 0) { - puts(pBueffel); - return; - } - if (ConStack[iConStackPtr] == NULL) { - puts(pBueffel); - return; - } - pCon = ConStack[iConStackPtr]; - - SCWrite(pCon, pBueffel, eValue); -} - -/*========== sicsgetline */ -void sicsgetline_(int *iText, int *iLen) -{ - SConnection *pCon = NULL; - char pBueffel[256]; - int i, iRet; - - /* this is just security, may never happen */ - if (iConStackPtr < 0) { - return; - } - if (ConStack[iConStackPtr] == NULL) { - return; - } - pCon = ConStack[iConStackPtr]; - - iRet = SCPrompt(pCon, "Enter data please >>", pBueffel, 255); - /* difrac cannot handle an interrupted input operation */ - if (iRet == 0) { - SCSetInterrupt(pCon, eContinue); - } - for (i = 0; i < strlen(pBueffel); i++) { - iText[i] = (int) pBueffel[i]; - } - *iLen = strlen(pBueffel); -} - -/*============= checkint */ -void checkint_(int *iK) -{ - SConnection *pCon = NULL; - char pBueffel[256]; - int i; - - /* this is just security, may never happen */ - if (iConStackPtr < 0) { - *iK = 0; - return; - } - if (ConStack[iConStackPtr] == NULL) { - return; - } - pCon = ConStack[iConStackPtr]; - - if (SCGetInterrupt(pCon) >= eAbortScan) { - *iK = 0; - } else { - *iK = 1; - } -} - -/*-------------------------------------------------------------------------- - DifracAction is the interface routine between the SICS interpreter and - the DIFRAC subsystem. What it basically does is: pop the connection onto - the stack. Concatenate all pending command line data to a string. Then - call DIFRAC with this string as an parameter. On return, remove the - connection from the stack again and return. - -------------------------------------------------------------------------*/ -/* some protoypes for things defined in F77 */ - -extern void difini_(void); -extern void difint_(int *iText, int *iLen); - -int DifracAction(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]) -{ - char pInput[256]; - int iInput[256]; - int iLen, i; - - - if (argc < 2) { - SCWrite(pCon, "ERROR: dif expects at least one argument", eError); - return 0; - } - - /* user privilege required */ - if (!SCMatchRights(pCon, usUser)) { - return 0; - } - - /* steal: redirect the I/O to me */ - strcpy(pInput, argv[1]); - strtolower(pInput); - if (strcmp(pInput, "steal") == 0) { - if (iConStackPtr >= 0) { - ConStack[iConStackPtr] = pCon; - } - SCSendOK(pCon); - return 1; - } - - iConStackPtr++; - ConStack[iConStackPtr] = pCon; - - Arg2Text(argc - 1, &argv[1], pInput, 255); - iLen = strlen(pInput); - for (i = 0; i < iLen; i++) { - iInput[i] = toupper((int) pInput[i]); - } - - /* do difrac */ - difint_(iInput, &iLen); - SCWrite(pCon, "Difrac subsystem finished", eWarning); - - iConStackPtr--; - if (SCGetInterrupt(pCon) != eContinue) { - return 0; - } else { - return 1; - } -} - -/*-------------------- The initialization routine ----------------------*/ -int MakeDifrac(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]) -{ - CommandList *pCom = NULL; - pICountable pCts = NULL; - int iRet; - - if (argc < 6) { - SCWrite(pCon, - "ERROR: Insufficient number of arguments to MakeDifrac", - eError); - return 0; - } - - /* find motors */ - pTTH = FindMotor(pSics, argv[1]); - if (!pTTH) { - SCWrite(pCon, "ERROR: cannot find two theta motor", eError); - return 0; - } - pOM = FindMotor(pSics, argv[2]); - if (!pOM) { - SCWrite(pCon, "ERROR: cannot find omega motor", eError); - return 0; - } - pCHI = FindMotor(pSics, argv[3]); - if (!pTTH) { - SCWrite(pCon, "ERROR: cannot find chi motor", eError); - return 0; - } - pPHI = FindMotor(pSics, argv[4]); - if (!pTTH) { - SCWrite(pCon, "ERROR: cannot find phi motor", eError); - return 0; - } - - /* locate counter */ - pCom = FindCommand(pSics, argv[5]); - if (pCom == NULL) { - SCWrite(pCon, "ERROR: counter not found in MakeDifrac", eError); - return 0; - } - pCts = GetCountableInterface(pCom->pData); - if (!pCts) { - SCWrite(pCon, "ERROR: argument to MakeDifrac is no counter", eError); - return 0; - } - counter = (pCounter) pCom->pData; - - /* initialize difrac */ - difini_(); - - /* install command */ - iRet = AddCommand(pSics, "dif", DifracAction, NULL, NULL); - if (!iRet) { - SCWrite(pCon, "ERROR: duplicate command dif NOT created", eError); - } - return iRet; -} diff --git a/difrac.h b/difrac.h deleted file mode 100644 index 35ef1515..00000000 --- a/difrac.h +++ /dev/null @@ -1,14 +0,0 @@ -/*-------------------------------------------------------------------------- - D I F R A C - - Header file for the interface between SICS and the F77 package - DIFRAC. Only the factory routine is defined. - - Mark Koennecke, November 1999 - --------------------------------------------------------------------------*/ -#ifndef DIFRAC -#define DIFRAC - -int MakeDifrac(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]); -#endif diff --git a/drive.c b/drive.c index ef076664..03a16bab 100644 --- a/drive.c +++ b/drive.c @@ -160,7 +160,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name, /* check if user is allowed to drive */ if (!SCMatchRights(pCon, usUser)) { - snprintf(pBueffel,511, "Insuficient Privilege to drive %s", name); + snprintf(pBueffel,511, "ERROR: Insuficient Privilege to drive %s", name); SCWrite(pCon, pBueffel, eError); return 0; } @@ -168,7 +168,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name, /* first try to find the thing to drive */ pObject = FindCommand(pInter, name); if (!pObject) { - snprintf(pBueffel,511, "Cannot find %s to drive ", name); + snprintf(pBueffel,511, "ERROR: Cannot find %s to drive ", name); SCWrite(pCon, pBueffel, eError); return 0; } @@ -179,7 +179,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name, pDum = (Dummy *) pObject->pData; pDes = pDum->pDescriptor; if (!pDes) { - snprintf(pBueffel,511, "%s is NOT drivable!", pDes->name); + snprintf(pBueffel,511, "ERROR: %s is NOT drivable!", pDes->name); SCWrite(pCon, pBueffel, eError); return 0; } @@ -189,14 +189,14 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name, */ pInt = pDes->GetInterface(pDum, DRIVEID); if (!pInt) { - snprintf(pBueffel,511, "%s is NOT drivable!", pDes->name); + snprintf(pBueffel,511, "ERROR: %s is NOT drivable!", pDes->name); SCWrite(pCon, pBueffel, eError); return 0; } if (pInt) { iRet = pInt->CheckLimits(pDum, fNew, pBueffel, 511); if (!iRet) { - SCWrite(pCon, pBueffel, eError); + SCPrintf(pCon, eError, "ERROR: %s", pBueffel); SCSetInterrupt(pCon, eAbortOperation); return 0; } @@ -207,7 +207,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name, return 1; } } else { - snprintf(pBueffel,511, "%s is NOT drivable", pDes->name); + snprintf(pBueffel,511, "ERROR: %s is NOT drivable", pDes->name); SCWrite(pCon, pBueffel, eError); return 0; } @@ -426,7 +426,72 @@ int RunWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, } return 1; } +/*---------------------------------------------------------------------------*/ +int MoveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + Tcl_Interp *tcl_interp; + int iRet, i; + double dTarget; + float curPos; + char pBueffel[512]; + Status eOld; + long groupID, taskID; + void *obj; + assert(pCon); + assert(pSics); + tcl_interp = InterpGetTcl(pSics); + /* check Status */ + eOld = GetStatus(); + + + /* check no of args */ + if (argc < 3) { + snprintf(pBueffel,511, "Insufficient number of args. Usage %s name val", + argv[0]); + SCWrite(pCon, pBueffel, eError); + return 0; + } + + /* check authorisation */ + if (!SCMatchRights(pCon, usUser)) { + SCWrite(pCon, + "ERROR: You are not authorized to use the mv command", + eError); + return 0; + } + groupID = GetTaskGroupID(pServ->pTasker); + for (i = 1; i < argc; i += 2) { + if (argv[i + 1] == NULL) { + snprintf(pBueffel,511, "ERROR: no value found for driving %s", argv[i]); + SCWrite(pCon, pBueffel, eError); + SetStatus(eOld); + return 0; + } + iRet = Tcl_GetDouble(tcl_interp, argv[i + 1], &dTarget); + if (iRet == TCL_ERROR) { + SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError); + StopExe(GetExecutor(), "ALL"); + SetStatus(eOld); + return 0; + } + obj = FindCommandData(pSics,argv[i],NULL); + if(obj == NULL || GetDrivableInterface(obj) == NULL){ + SCPrintf(pCon,eError, "ERROR: %s not found, not started",argv[i]); + break; + } + GetDrivablePosition(obj,pCon,&curPos); + dTarget = curPos + dTarget; + taskID = StartDriveTask(obj, pCon, argv[i], (float)dTarget); + AddTaskToGroup(pServ->pTasker,taskID,groupID); + } + while(isTaskGroupRunning(pServ->pTasker,groupID)){ + TaskYield(pServ->pTasker); + } + SCSendOK(pCon); + return 0; +} /*---------------------------------------------------------------------------*/ int MakeDrive(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) @@ -457,5 +522,17 @@ int MakeDrive(SConnection * pCon, SicsInterp * pSics, void *pData, SCWrite(pCon, pBueffel, eError); return 0; } + + if (argc > 3) { + iRet = AddCommand(pSics, argv[2], MoveWrapper, NULL, NULL); + } else { + iRet = AddCommand(pSics, "mv", MoveWrapper, NULL, NULL); + } + if (!iRet) { + sprintf(pBueffel, "ERROR: duplicate command mv not created"); + SCWrite(pCon, pBueffel, eError); + return 0; + } + return 1; } diff --git a/ecbcounter.c b/ecbcounter.c deleted file mode 100644 index e616c4d6..00000000 --- a/ecbcounter.c +++ /dev/null @@ -1,622 +0,0 @@ -/*---------------------------------------------------------------------------- - This is a single counter implemented on top of the Risoe ECB electronic - - copyright: see file COPYRIGHT - - Mark Koennecke, January-February 2003 - ---------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include -#include -#include "fortify.h" -#include "sics.h" -#include "status.h" -#include "psi/ecb.h" -#include "countdriv.h" - -/*------------------ our private data structure ------------------------*/ -typedef struct { - pECB ecb; /* the ECB system we talk to */ - unsigned char prescaler[8]; /* an array for the prescaler values */ - int tfreq; /* timer frequency */ - unsigned char control; /* marks the control monitor */ - int state; /* current counting state */ -} ECBCounter, *pECBCounter; - -/*----------------- private defines ------------------------------------*/ -#define STFRD 137 -#define STREAD 138 -#define STOPS 136 -#define STCLEA 134 -#define PRELOA 139 -#define STLOAD 156 -#define STCPRE 133 -#define STARTS 135 -#define SPCSTA 169 - -/*------------------ state codes --------------------------------------*/ -#define IDLE 0 -#define COUNT 2 -#define NOBEAM 3 -/*--------------------------------------------------------------------*/ -#define MAX_COUNT 4294967295.0 -/*------------------ error codes --------------------------------------*/ -#define COMMERROR -300 -#define TOMANYCOUNTS -301 -#define NOSEND -302 -#define INVALIDCOUNTER -304 -#define INVALIDPRESCALER -305 -#define BADFREQ -306 -/*======================================================================*/ -static int readScaler(pECBCounter pPriv, int scaler, int *count) -{ - int status; - Z80_reg in, out; - Ecb_pack data; - - in.c = (unsigned char) scaler; - status = ecbExecute(pPriv->ecb, STREAD, in, &out); - if (status != 1) { - return COMMERROR; - } - - data.b.byt3 = out.c; - data.b.byt2 = out.b; - data.b.byt1 = out.d; - data.b.byt0 = out.e; - if (scaler == 0) { - *count = data.result / pPriv->tfreq; - } else { - *count = data.result; - } - - return 1; -} - -/*---------------------------------------------------------------------*/ -static int check4Beam(struct __COUNTER *pCter, int *beam) -{ - Z80_reg in, out; - pECBCounter self = NULL; - int status; - - self = (pECBCounter) pCter->pData; - assert(self); - - in.c = 1; - status = ecbExecute(self->ecb, SPCSTA, in, &out); - if (status != 1) { - pCter->iErrorCode = COMMERROR; - return HWFault; - } - *beam = (int) out.d; - return 1; -} - -/*----------------------------------------------------------------------*/ -static int stopScalers(pECBCounter self) -{ - int status; - Z80_reg in, out; - - status = ecbExecute(self->ecb, STOPS, in, &out); - if (status != 1) { - return COMMERROR; - } - return 1; -} - -/*======================================================================== - These two functions currently rely on the idea that the ECB stops - and starts without clearing counters in between. The sequence of - things necessary to start it, suggests this. If this is not the case then - this will not work. -===========================================================================*/ -static int ECBPause(struct __COUNTER *self) -{ - int status; - pECBCounter pPriv = NULL; - - assert(self); - pPriv = (pECBCounter) self->pData; - assert(pPriv); - - if ((status = stopScalers(pPriv)) <= 0) { - self->iErrorCode = status; - return HWFault; - } - return OKOK; -} - -/*=======================================================================*/ -static int ECBContinue(struct __COUNTER *self) -{ - int status; - pECBCounter pPriv = NULL; - Z80_reg in, out; - - assert(self); - pPriv = (pECBCounter) self->pData; - assert(pPriv); - - status = ecbExecute(pPriv->ecb, STARTS, in, &out); - if (status != 1) { - self->iErrorCode = status; - return HWFault; - } - - return OKOK; -} - -/*-----------------------------------------------------------------------*/ -static int ECBGetStatus(struct __COUNTER *self, float *fControl) -{ - pECBCounter pPriv = (pECBCounter) self->pData; - int status, result, scaler; - Z80_reg in, out; - int count, beam; - - assert(pPriv); - - /* - This can happen after a stop - */ - if (pPriv->state == IDLE) { - ECBTransfer(self); - return HWIdle; - } - - /* - read status bit - */ - status = ecbExecute(pPriv->ecb, STFRD, in, &out); - if (status != 1) { - self->iErrorCode = COMMERROR; - pPriv->state = IDLE; - return HWFault; - } - /* - read beam status - */ - status = check4Beam(self, &beam); - if (status != 1) { - self->iErrorCode = COMMERROR; - return HWFault; - } - beam &= 1; - - /* - sophisticated logic in order to keep track of the various states - the thing can be in. Complicated by the fact that the status becomes - idle (out.d = 0) when the measurement is paused due to the lack of - beam. - */ - if (pPriv->state == COUNT && beam == 1) { - ECBPause(self); - pPriv->state = NOBEAM; - SetStatus(eOutOfBeam); - result = HWNoBeam; - } - if (pPriv->state == NOBEAM && beam == 0) { - ECBContinue(self); - pPriv->state = COUNT; - SetStatus(eCounting); - return HWBusy; - } - if (pPriv->state == NOBEAM && beam == 1) { - return HWNoBeam; - } - if (out.d == 0 && pPriv->state == COUNT) { - result = HWIdle; - ECBTransfer(self); - pPriv->state = IDLE; - } else { - result = HWBusy; - } - - - /* - select which scaler to read - */ - if (self->eMode == eTimer) { - scaler = 0; - } else { - scaler = pPriv->control; - } - - readScaler(pPriv, scaler, &count); - /* - ignore errors on this one - */ - *fControl = (float) count; - - return result; -}exit - - -/*=====================================================================*/ -static int clearScalers(pECBCounter self) -{ - int status; - Z80_reg in, out; - - status = ecbExecute(self->ecb, STCLEA, in, &out); - if (status != 1) { - return COMMERROR; - } - return 1; -} - -/*----------------------------------------------------------------------*/ -static int loadPrescalers(pECBCounter self) -{ - Z80_reg in, out; - int status, i; - - for (i = 0; i < 8; i++) { - in.c = (unsigned char) i; - in.d = self->prescaler[i]; - status = ecbExecute(self->ecb, PRELOA, in, &out); - if (status != 1) { - return COMMERROR; - } - } - return 1; -} - -/*----------------------------------------------------------------------*/ -static int loadPreset(pECBCounter self, int preset, unsigned char control) -{ - Z80_reg in, out; - Ecb_pack data; - int status, i; - - data.result = preset; - - in.c = data.b.byt3; - in.b = data.b.byt2; - in.e = data.b.byt1; - in.d = data.b.byt0; - status = ecbExecute(self->ecb, STLOAD, in, &out); - if (status != 1) { - return COMMERROR; - } - - in.b = data.b.byt2; - in.e = data.b.byt1; - in.d = data.b.byt0; - in.c = 4 * control; - status = ecbExecute(self->ecb, STCPRE, in, &out); - if (status != 1) { - return COMMERROR; - } - return 1; -} - -/*-----------------------------------------------------------------------*/ -static int ECBStart(struct __COUNTER *self) -{ - pECBCounter pPriv = NULL; - int preset, status, controlUnit; - Z80_reg in, out; - - assert(self); - pPriv = (pECBCounter) self->pData; - assert(pPriv); - - /* - check if the preset is permissible - */ - preset = (int) rint(self->fPreset); - if (preset > MAX_COUNT) { - self->iErrorCode = TOMANYCOUNTS; - return HWFault; - } - if (self->eMode == eTimer) { - controlUnit = 0; - preset *= pPriv->tfreq; - if (preset > MAX_COUNT) { - self->iErrorCode = TOMANYCOUNTS; - return HWFault; - } - } else { - controlUnit = pPriv->control; - } - - if ((status = stopScalers(pPriv)) <= 0) { - self->iErrorCode = status; - return HWFault; - } - - if ((status = clearScalers(pPriv)) <= 0) { - self->iErrorCode = status; - return HWFault; - } - - if ((status = loadPrescalers(pPriv)) <= 0) { - self->iErrorCode = status; - return HWFault; - } - - if ((status = - loadPreset(pPriv, preset, (unsigned char) controlUnit)) <= 0) { - self->iErrorCode = status; - return HWFault; - } - - status = ecbExecute(pPriv->ecb, STARTS, in, &out); - if (status != 1) { - self->iErrorCode = status; - return HWFault; - } - - pPriv->state = COUNT; - return OKOK; -} - -/*=======================================================================*/ -static int ECBHalt(struct __COUNTER *self) -{ - int status; - pECBCounter pPriv = NULL; - - assert(self); - pPriv = (pECBCounter) self->pData; - assert(pPriv); - - pPriv->state = IDLE; - if ((status = stopScalers(pPriv)) <= 0) { - self->iErrorCode = status; - return HWFault; - } - return OKOK; -} - -/*=======================================================================*/ -static int ECBTransfer(struct __COUNTER *self) -{ - int status, count, i; - pECBCounter pPriv = NULL; - - assert(self); - pPriv = (pECBCounter) self->pData; - assert(pPriv); - - /* - read time - */ - status = readScaler(pPriv, 0, &count); - if (status <= 0) { - self->iErrorCode = COMMERROR; - return HWFault; - } - self->fTime = (float) count; - - /* - read other scalers - */ - for (i = 1; i < 8; i++) { - status = readScaler(pPriv, i, &count); - if (status <= 0) { - self->iErrorCode = COMMERROR; - return HWFault; - } - self->lCounts[i - 1] = count; - } - return OKOK; -} - -/*======================================================================*/ -static int ECBGetError(struct __COUNTER *self, int *iCode, - char *errorText, int errlen) -{ - char pBueffel[132]; - - *iCode = self->iErrorCode; - switch (self->iErrorCode) { - case COMMERROR: - strlcpy(errorText, "Communication error with ECB", errlen); - break; - case TOMANYCOUNTS: - strlcpy(errorText, "Preset is to high!", errlen); - break; - case NOSEND: - strlcpy(errorText, "Cannot send naked data to ECB", errlen); - break; - case UNKNOWNPAR: - strlcpy(errorText, "parameter unknown", errlen); - break; - case INVALIDCOUNTER: - strlcpy(errorText, "Invalid counter number requested, 0-7 allowed", - errlen); - break; - case INVALIDPRESCALER: - strlcpy(errorText, "Invalid prescaler value, allowed 1 or 10", errlen); - break; - case BADFREQ: - strlcpy(errorText, "Bad timer frequency: 10 or 1000 allowed", errlen); - break; - default: - sprintf(pBueffel, "Unknown error code %d", self->iErrorCode); - strlcpy(errorText, pBueffel, errlen); - break; - } - return 1; -} - -/*=======================================================================*/ -static int ECBFixIt(struct __COUNTER *self, int iCode) -{ - return COTERM; -} - -/*======================================================================*/ - -/******************************************************************************* -* Load the parameters 'dot' and 'divide' for a motor or an encoder. -* 'dot' specifies the placement of a punctuation mark on the display -* of f.ex a motor position. 'divide' specifies how many times the po- -* sition is to be divided by two before it is displayed. -******************************************************************************/ -static void Dot_divide(int device, int data, pECB ecb) -{ - int function, dot, divide; - Z80_reg x_inreg, out; - - if (data == 0) /* If zero, dont send dot/divide) */ - return; - - dot = 0; - while ((data % 10) == 0) { - dot++; - data /= 10; - } - divide = 0; - while ((data % 2) == 0) { - divide++; - data /= 2; - } - if (data != 1) /* If != 1, not a binary No. */ - return; - if (dot > 0) - dot = 8 - dot; - x_inreg.c = 0; /* Specify input */ - x_inreg.b = (unsigned char) device; - x_inreg.d = (unsigned char) dot; /* Dot position */ - x_inreg.e = (unsigned char) divide; /* No. of times to divide by 2 */ - - ecbExecute(ecb, 170, x_inreg, &out); - return; -} - -/*-----------------------------------------------------------------------*/ -static int ECBSet(struct __COUNTER *self, char *name, - int iCter, float fVal) -{ - pECBCounter pPriv = NULL; - int iVal; - - assert(self); - pPriv = (pECBCounter) self->pData; - assert(pPriv); - - iVal = (int) rint(fVal); - - if (strcmp(name, "prescaler") == 0) { - if (iCter < 0 || iCter > 7) { - self->iErrorCode = INVALIDCOUNTER; - return HWFault; - } - if (iVal != 1 && iVal != 10) { - self->iErrorCode = INVALIDPRESCALER; - return HWFault; - } - pPriv->prescaler[iCter] = (unsigned char) iVal; - return OKOK; - } else if (strcmp(name, "tfreq") == 0) { - if (fVal == 1000) { - pPriv->prescaler[0] = 1; - pPriv->tfreq = 1000; - Dot_divide(64, 1000, pPriv->ecb); - return OKOK; - } else if (fVal == 10) { - pPriv->tfreq = 10; - pPriv->prescaler[0] = 10; - Dot_divide(64, 10, pPriv->ecb); - return OKOK; - } else { - self->iErrorCode = BADFREQ; - return HWFault; - } - } else { - self->iErrorCode = UNKNOWNPAR; - return HWFault; - } -} - -/*===================================================================*/ -static int ECBGet(struct __COUNTER *self, char *name, - int iCter, float *fVal) -{ - pECBCounter pPriv = NULL; - - assert(self); - pPriv = (pECBCounter) self->pData; - assert(pPriv); - - if (strcmp(name, "prescaler") == 0) { - *fVal = (float) pPriv->prescaler[iCter]; - return OKOK; - } else if (strcmp(name, "tfreq") == 0) { - *fVal = (float) pPriv->tfreq; - return OKOK; - } else { - self->iErrorCode = UNKNOWNPAR; - return HWFault; - } -} - -/*=====================================================================*/ -static int ECBSend(struct __COUNTER *self, char *text, - char *reply, int replylen) -{ - strlcpy(reply, "ECB does not feast on ASCII strings, refused!", - replylen); - return OKOK; -} - -/*====================================================================*/ -pCounterDriver MakeECBCounter(char *ecb) -{ - pECBCounter pPriv = NULL; - pCounterDriver self = NULL; - int i; - - /* - memory for everybody - */ - self = CreateCounterDriver("ecb", "ecb"); - pPriv = (pECBCounter) malloc(sizeof(ECBCounter)); - if (self == NULL || pPriv == NULL) { - return NULL; - } - memset(pPriv, 0, sizeof(ECBCounter)); - - /* - initialize private data structure - */ - pPriv->ecb = (pECB) FindCommandData(pServ->pSics, ecb, "ECB"); - if (pPriv->ecb == NULL) { - DeleteCounterDriver(self); - free(pPriv); - return NULL; - } - for (i = 0; i < 8; i++) { - pPriv->prescaler[i] = 1; - } - pPriv->tfreq = 1000; - pPriv->control = 1; - - - /* - assign function pointers - */ - self->GetStatus = ECBGetStatus; - self->Start = ECBStart; - self->Pause = ECBPause; - self->Continue = ECBContinue; - self->Halt = ECBHalt; - self->ReadValues = ECBTransfer; - self->GetError = ECBGetError; - self->TryAndFixIt = ECBFixIt; - self->Set = ECBSet; - self->Get = ECBGet; - self->Send = ECBSend; - self->KillPrivate = NULL; - - self->pData = pPriv; - return self; -} diff --git a/ecbcounter.h b/ecbcounter.h deleted file mode 100644 index cbfad223..00000000 --- a/ecbcounter.h +++ /dev/null @@ -1,17 +0,0 @@ -/*------------------------------------------------------------------------- - Header file for the counter driver for the Risoe ECB system. - - copyright: see file COPYRIGHT - - Mark Koennecke, January 2003 - -------------------------------------------------------------------------*/ - -#ifndef ECBCOUNTER -#define ECBCOUNTER - -#include "countdriv.h" - -pCounterDriver MakeECBCounter(char *ecb); -void KillECBCounter(CounterDriver * pDriv); - -#endif diff --git a/epicsmotor.c b/epicsmotor.c new file mode 100644 index 00000000..f15a7764 --- /dev/null +++ b/epicsmotor.c @@ -0,0 +1,313 @@ +/** + * This is a very basic first generation SICS EPICS motor driver for testing. + * It should be replaced by a second generation version when SINQ gets serious + * about EPICS and SICS. + * + * Mark Koennecke, February 2012 + */ +#include +#include +#include + +/* EPICS stuff */ +#include +#include +#include +#include +#include +#include +#include + +typedef struct __epicsMoDriv{ + /* general motor driver interface + fields. REQUIRED! + */ + float fUpper; /* upper limit */ + float fLower; /* lower limit */ + char *name; + int (*GetPosition)(void *self, float *fPos); + int (*RunTo)(void *self,float fNewVal); + int (*GetStatus)(void *self); + void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen); + int (*TryAndFixIt)(void *self, int iError,float fNew); + int (*Halt)(void *self); + int (*GetDriverPar)(void *self, char *name, + float *value); + int (*SetDriverPar)(void *self,SConnection *pCon, + char *name, float newValue); + void (*ListDriverPar)(void *self, char *motorName, + SConnection *pCon); + void (*KillPrivate)(void *self); + /* your drivers private fields follow below */ + char *motBaseName; + char *ezcaError; + int ezcaCode; + int connectCount; + } epicsMotorDriver; + +/*================================================================ + GetPos returns OKOK on success, HWFault on failure +------------------------------------------------------------------*/ +static int epicsGetPos(void *data, float *fPos){ + epicsMotorDriver *self = NULL; + char fullName[132]; + int status; + double position; + + self = (epicsMotorDriver *)data; + snprintf(fullName,sizeof(fullName),"%s.DRBV",self->motBaseName); + status = ezcaGet(fullName,ezcaDouble,1, &position); + if(status == EZCA_OK){ + *fPos =(float) position; + self->connectCount = 0; + return OKOK; + } else { + ezcaGetErrorString("ERROR: EPICS: ", &self->ezcaError); + self->ezcaCode = status; + return HWFault; + } +} +/*-------------- dummy callback for runto -------------------------*/ +static void RunToDummy(struct event_handler_args d) +{ +} +/*---------------------------------------------------------------- + RunTo starts the motor running. Returns OKOK on success, HWfault + on Errors +------------------------------------------------------------------*/ +static int epicsRunTo(void *data, float newValue){ + epicsMotorDriver *self = NULL; + char fullName[132]; + double position = newValue; + int status; + chid *cid; + + self = (epicsMotorDriver *)data; + snprintf(fullName,sizeof(fullName),"%s.DVAL",self->motBaseName); + ezcaPvToChid(fullName,&cid); + status = ca_put_callback(DBR_DOUBLE,*cid,&position, RunToDummy,NULL); + if(status != ECA_NORMAL){ + snprintf(fullName, sizeof(fullName),"Bad CA status %d", status); + self->ezcaError = strdup(fullName); + self->ezcaCode = status; + return HWFault; + } else { + ca_pend_event(.05); + self->connectCount = 0; + return OKOK; + } + +} +/*------------------------------------------------------------------ + CheckStatus queries the sattus of a running motor. Possible return + values can be: + HWBusy : motor still running + HWFault : motor error detected + HWPosFault : motor finished, but position not reached + HWIdle : motor finished OK + HWWarn : motor issued warning +--------------------------------------------------------------------*/ +static int epicsCheckStatus(void *data){ + epicsMotorDriver *self = NULL; + char fullName[132]; + short smov, stat; + int status; + + self = (epicsMotorDriver *)data; + snprintf(fullName,sizeof(fullName),"%s.DMOV",self->motBaseName); + status = ezcaGet(fullName,ezcaShort,1, &smov); + if(status == EZCA_OK){ + self->connectCount = 0; + if(smov == 0){ + return HWBusy; + } else { + snprintf(fullName,sizeof(fullName),"%s.STAT",self->motBaseName); + status = ezcaGet(fullName,ezcaShort,1, &stat); + if(stat != menuAlarmStatNO_ALARM){ + snprintf(fullName,sizeof(fullName),"EPICS ALARM: %s", epicsAlarmConditionStrings[stat]); + self->ezcaError = strdup(fullName); + return HWFault; + } else { + return HWIdle; + } + } + } else { + ezcaGetErrorString("ERROR: EPICS: ", &self->ezcaError); + self->ezcaCode = status; + return HWFault; + } +} +/*------------------------------------------------------------------ + GetError gets more information about error which occurred + *iCode is an integer error code to be used in TryFixIt as indicator + buffer is a buffer for a text description of the problem + iBufLen is the length of buffer +--------------------------------------------------------------------*/ +static void epicsGetError(void *data, int *iCode, char *buffer, + int iBufLen){ + epicsMotorDriver *self = NULL; + + self = (epicsMotorDriver *)data; + if(self->ezcaError != NULL){ + strncpy(buffer,self->ezcaError,iBufLen); + ezcaFree(self->ezcaError); + self->ezcaError = NULL; + } +} +/*------------------------------------------------------------------ + TryAndFixIt tries everything which is possible in software to fix + a problem. iError is the error code from GetError, newValue is + the target value for the motor + Possible retrun values are: + MOTOK : everything fixed + MOTREDO : try again + MOTFAIL : cannot fix this +--------------------------------------------------------------------*/ +static int epicsFixIt(void *data, int iError, float newValue){ + epicsMotorDriver *self = NULL; + + self = (epicsMotorDriver *)data; + if(self->ezcaCode == EZCA_NOTCONNECTED && self->connectCount < 2) { + self->connectCount++; + return MOTREDO; + } + return MOTFAIL; +} +/*------------------------------------------------------------------- + Halt tries to stop the motor. Halt errors are ignored. + + For some as yet unknown reasons, I cannot send the stop on the + same CA line then the rest. But with a new thread which just sends + the stop, it works. This is a straightforward use of a thread: + do your thing and terminate. Do not interact with other parts + of the program. +---------------------------------------------------------------------*/ +static void HaltThreadFunc(void *param) +{ + char *pvName = (char *)param; + short stop = 1; + chid cid; + + ca_context_create(ca_disable_preemptive_callback); + ca_create_channel(pvName,NULL,NULL,10,&cid); + ca_pend_io(5.); + ca_put(DBR_SHORT,cid,&stop); + ca_pend_io(5.0); + free(pvName); + printf("HaltThread ends\n"); + +} +/*-------------------------------------------------------------------*/ +static int epicsHalt(void *data){ + epicsMotorDriver *self = NULL; + char fullName[132]; + short stop =1; + chid *cid; + int status; + + self = (epicsMotorDriver *)data; + snprintf(fullName,sizeof(fullName),"%s.STOP",self->motBaseName); + /* ezcaStartGroup(); */ + /* ezcaPut(fullName,ezcaShort,1,&stop); */ + /* ezcaEndGroup(); */ + /* ezcaPvToChid(fullName,&cid); */ + /* status = ca_put_callback(DBR_SHORT,*cid,&stop, RunToDummy,NULL); */ + /* printf("Halt status %d\n", status); */ + /* ca_flush_io(); */ + /* printf("Halt after poll\n"); */ + epicsThreadCreate("Hugo", + epicsThreadPriorityHigh, + epicsThreadStackMedium, + HaltThreadFunc, + (void *)strdup(fullName)); + + return 1; +} +/*-------------------------------------------------------------------- + GetDriverPar retrieves the value of a driver parameter. + Name is the name of the parameter, fValue the value when found. + Returns 0 on success, 0 else +-----------------------------------------------------------------------*/ +static int epicsGetDriverPar(void *data, char *name, float *value){ + epicsMotorDriver *self = NULL; + + self = (epicsMotorDriver *)data; + return 0; +} +/*---------------------------------------------------------------------- + SetDriverPar sets a driver parameter. Returns 0 on failure, 1 on + success. Name is the parameter name, pCon the connection to report + errors too, value the new value +------------------------------------------------------------------------*/ +static int epicsSetDriverPar(void *data, SConnection *pCon, + char *name, float value){ + epicsMotorDriver *self = NULL; + + self = (epicsMotorDriver *)data; + return 0; +} +/*----------------------------------------------------------------------- + ListDriverPar lists the names and values of driver parameters to + pCon. Motorname is the name of the motor ro prefix to the listing. +-------------------------------------------------------------------------*/ +static void epicsListDriverPar(void *data, char *motorname, + SConnection *pCon){ + epicsMotorDriver *self = NULL; + + self = (epicsMotorDriver *)data; +} +/*----------------------------------------------------------------------- + KillPrivate has the task to delete possibly dynamically allocated + memory in the private part of the driver structure +------------------------------------------------------------------------*/ +static void epicsKillPrivate(void *data){ + epicsMotorDriver *self = NULL; + + self = (epicsMotorDriver *)data; + if(self->ezcaError != NULL){ + ezcaFree(self->ezcaError); + } + if(self->motBaseName != NULL){ + free(self->motBaseName); + } +} +/*=======================================================================*/ +MotorDriver *epicsMakeMotorDriver(char *baseName) { + epicsMotorDriver *pNew = NULL; + char fullName[132]; + double limit; + + pNew = malloc(sizeof(epicsMotorDriver)); + if(pNew == NULL){ + return NULL; + } + memset(pNew,0,sizeof(epicsMotorDriver)); + pNew->motBaseName = strdup(baseName); + snprintf(fullName,sizeof(fullName),"%s.DRBV",pNew->motBaseName); + ezcaSetMonitor(fullName,ezcaDouble,1); + snprintf(fullName,sizeof(fullName),"%s.DMOV",pNew->motBaseName); + ezcaSetMonitor(fullName,ezcaShort,1); + snprintf(fullName,sizeof(fullName),"%s.STAT",pNew->motBaseName); + ezcaSetMonitor(fullName,ezcaShort,1); + + snprintf(fullName,sizeof(fullName),"%s.HLM",pNew->motBaseName); + ezcaGet(fullName,ezcaDouble,1, &limit); + pNew->fUpper = limit; + snprintf(fullName,sizeof(fullName),"%s.LLM",pNew->motBaseName); + ezcaGet(fullName,ezcaDouble,1, &limit); + pNew->fLower = limit; + + pNew->GetPosition = epicsGetPos; + pNew->RunTo = epicsRunTo; + pNew->Halt = epicsHalt; + pNew->GetStatus = epicsCheckStatus; + pNew->GetError = epicsGetError; + pNew->TryAndFixIt = epicsFixIt; + pNew->GetDriverPar = epicsGetDriverPar; + pNew->SetDriverPar = epicsSetDriverPar; + pNew->ListDriverPar = epicsListDriverPar; + pNew->KillPrivate = epicsKillPrivate; + + /* ezcaTraceOn(); */ + return (MotorDriver *)pNew; +} diff --git a/event.c b/event.c index 233dd792..0d64b6e3 100644 --- a/event.c +++ b/event.c @@ -71,6 +71,8 @@ static char *pEvent[] = { "STATEEND", "NEWTARGET", "DIMCHANGE", + "PAUSE", + "CONTINUE", NULL }; diff --git a/event.h b/event.h index ef9dbabf..9142b2e2 100644 --- a/event.h +++ b/event.h @@ -1,5 +1,5 @@ -#line 103 "event.w" +#line 108 "event.w" /*---------------------------------------------------------------------------- E V E N T @@ -18,7 +18,7 @@ int Text2Event(char *pText); -#line 116 "event.w" +#line 121 "event.w" @@ -49,8 +49,10 @@ #define STEND 22 #define NEWTARGET 23 #define DIMCHANGE 24 +#define IPAUSE 25 +#define CONTINUE 26 -#line 118 "event.w" +#line 123 "event.w" /*----------------- event data structure for the NEWTARGET event ---------*/ @@ -60,7 +62,7 @@ typedef struct { } NewTarget, *pNewTarget; /*--------------- Signals for the Signalfunction of each task ------------*/ -#line 85 "event.w" +#line 90 "event.w" #define SICSINT 300 #define SICSBROADCAST 301 @@ -69,6 +71,6 @@ typedef struct { #define COMLOG 304 #define CRONLIST 305 -#line 126 "event.w" +#line 131 "event.w" #endif diff --git a/event.tex b/event.tex index 34aef4fb..3d3fade1 100644 --- a/event.tex +++ b/event.tex @@ -60,6 +60,8 @@ $\langle$VE {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@#define STEND 22@\\ \mbox{}\verb@#define NEWTARGET 23@\\ \mbox{}\verb@#define DIMCHANGE 24@\\ +\mbox{}\verb@#define IPAUSE 25@\\ +\mbox{}\verb@#define CONTINUE 26@\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} @@ -99,8 +101,11 @@ operation. \item[HDBVAL] The Hdb is notified of a value change. The eventData will be the object on which the data changed. \item[NEWTARGET] is invoked when a new target has been set on a drivable. +\item[PAUSE] Pause counting +\item[CONTINUE] Continue counting \end{description} + Furthermore event contains system wide signal codes which are interpreted in the signal functions provided by each SICS task. These code are evaluated by the TaskSignalFunction which may be configured for each diff --git a/event.w b/event.w index 6f4ed0c0..5b53b7c1 100644 --- a/event.w +++ b/event.w @@ -43,6 +43,8 @@ if the event code is not known, else the apropriate event code. #define STEND 22 #define NEWTARGET 23 #define DIMCHANGE 24 +#define IPAUSE 25 +#define CONTINUE 26 @} \begin{description} \item[VALUECHANGE] This is a variable changing its value. As event data a pointer to the @@ -74,8 +76,11 @@ operation. \item[HDBVAL] The Hdb is notified of a value change. The eventData will be the object on which the data changed. \item[NEWTARGET] is invoked when a new target has been set on a drivable. +\item[PAUSE] Pause counting +\item[CONTINUE] Continue counting \end{description} + Furthermore event contains system wide signal codes which are interpreted in the signal functions provided by each SICS task. These code are evaluated by the TaskSignalFunction which may be configured for each diff --git a/hdbtable.c b/hdbtable.c index abdc7efc..ca241960 100644 --- a/hdbtable.c +++ b/hdbtable.c @@ -17,6 +17,10 @@ * copyright: see file COPYRIGHT * * Mark Koennecke, March 2009 + * + * Added CountTblCmd + * + * Mark Koennecke, march 2013 */ #include #include "sicshipadaba.h" @@ -75,6 +79,20 @@ static int ClearTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, return 1; } /*----------------------------------------------------------------------*/ +int CountTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + pHdb node; + int nRows = 0; + + node = GetHipadabaNode(self->objectNode,"data"); + if(node != NULL){ + nRows = CountHdbChildren(node); + } + SCPrintf(pCon,eValue,"rows = %d", nRows); + return 1; +} +/*----------------------------------------------------------------------*/ static int AddTblRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, pHdb par[], int nPar) { @@ -470,6 +488,9 @@ pSICSOBJ MakeHdbTable(char *name, char *hdbclass) SetHdbProperty(node,"priv","user"); AddHipadabaChild(cmd,node, NULL); + cmd = AddSICSHdbPar(result->objectNode, "count", usSpy, + MakeSICSFunc(CountTblCmd)); + return result; } /*---------------------------------------------------------------------------*/ diff --git a/histmem.c b/histmem.c index 2e086bda..c3c40724 100644 --- a/histmem.c +++ b/histmem.c @@ -208,8 +208,8 @@ static int HistStartCount(void *pData, SConnection * pCon) iRet = self->pDriv->Start(self->pDriv, pCon); if (iRet == OKOK) { /* send a COUNTSTART event */ + clearHMData(self->pDriv->data); InvokeCallBack(self->pCall, COUNTSTART, pCon); - updateHMData(self->pDriv->data); return iRet; } else { iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79); @@ -350,9 +350,9 @@ static int HistCountStatus(void *pData, SConnection * pCon) return HWBusy; } } - if (eCt == HWBusy){ - updateHMData(self->pDriv->data); - } + /* if (eCt == HWBusy){ */ + /* updateHMData(self->pDriv->data); */ + /* } */ if (eCt == HWIdle) { /* force an update of local histogram data with next @@ -879,7 +879,7 @@ int GetHistogram(pHistMem self, SConnection * pCon, eWarning); iEnd = (iDataLen / sizeof(HistInt)) - 1; } - return getHMDataHistogram(self, pCon, i, iStart, iEnd, lData); + return getHMDataHistogram(self, pCon, i, iStart, iEnd-iStart, lData); } /*-------------------------------------------------------------------------*/ @@ -1335,6 +1335,22 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData, } else { return 0; } + } else if (strcmp(argv[1], "clearhm") == 0) { + /* + clear the local copy of the HM. Assumes that the HM + clears itself on start. Which it does. + */ + if (SCMatchRights(pCon, usUser)) { + if(self->pDriv->data != NULL){ + clearHMData(self->pDriv->data); + SCSendOK(pCon); + return 1; + } else { + return 0; + } + } else { + return 0; + } } else if (strcmp(argv[1], "list") == 0) { HMListOption(self, pCon); return 1; @@ -1798,4 +1814,5 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData, SCWrite(pCon, pBueffel, eError); return 0; } + return 0; } diff --git a/hkl.c b/hkl.c index b4030f8b..f5c3cb41 100644 --- a/hkl.c +++ b/hkl.c @@ -26,6 +26,10 @@ Heavily reworked to fit into the new four circle setup Mark Koennecke, July 2008 + + Added calculation of angles between reflection + + Mark Koennecke, March 2013 -----------------------------------------------------------------------------*/ #include #include @@ -687,6 +691,47 @@ static int HKLCalculateTheta(pHKL self, float fHKL[3], double *stt) *stt = 2. * theta; return status; } +/*-------------------------------------------------------------------------*/ +static int HKLAngle(SConnection *pCon, int argc, char *argv[]) +{ + reflection r1, r2; + lattice direct; + const double *cell; + MATRIX B; + double ang; + + if(argc < 8){ + SCWrite(pCon,"ERROR: insufficient no of arguments to hkl angle",eError); + return 0; + } + r1.h = atof(argv[2]); + r1.k = atof(argv[3]); + r1.l = atof(argv[4]); + + r2.h = atof(argv[5]); + r2.k = atof(argv[6]); + r2.l = atof(argv[7]); + + cell = SXGetCell(); + direct.a = cell[0]; + direct.b = cell[1]; + direct.c = cell[2]; + direct.alpha = cell[3]; + direct.beta = cell[4]; + direct.gamma = cell[5]; + + B = mat_creat(3,3,ZERO_MATRIX); + if(B == NULL){ + SCWrite(pCon,"ERROR: out of memory in HKL angle",eError); + return 0; + } + + calculateBMatrix(direct,B); + ang = angleBetweenReflections(B,r1,r2); + SCPrintf(pCon,eValue,"angle = %f", ang); + mat_free(B); + return 1; +} /*--------------------------------------------------------------------------*/ static int HandleBiToNB(SConnection *pCon, int argc, char *argv[]) { @@ -993,6 +1038,10 @@ int HKLAction(SConnection * pCon, SicsInterp * pSics, void *pData, SCPrintf(pCon, eValue, "two-theta = %lf", stt); return 1; } + /*--------------- calculate angle */ + else if (strcmp(argv[1], "angle") == 0) { + return HKLAngle(pCon,argc,argv); + } /*------------------ run */ else if (strcmp(argv[1], "run") == 0) { if (!SCMatchRights(pCon, usUser)) { diff --git a/hmdata.c b/hmdata.c index cc801e8c..1f05263d 100644 --- a/hmdata.c +++ b/hmdata.c @@ -59,6 +59,7 @@ void clearHMData(pHMdata self) size *= getNoOfTimebins(self); } memset(self->localBuffer, 0, size * sizeof(HistInt)); + self->nextUpdate = time(NULL) + self->updateIntervall; } /*----------------------------------------------------------------------*/ @@ -313,7 +314,7 @@ static int updateHMbuffer(pHistMem hist, int bank, SConnection * pCon) } if (status == OKOK) { return 1; - } else { + } else { return HWFault; } } diff --git a/intcli.c b/intcli.c deleted file mode 100644 index f26a5607..00000000 --- a/intcli.c +++ /dev/null @@ -1,79 +0,0 @@ -/*--------------------------------------------------------------------------- - Client side implementation of the Interrupt interface. - - - - Mark Koennecke, December 1996 - - Copyright: - - Labor fuer Neutronenstreuung - Paul Scherrer Institut - CH-5423 Villigen-PSI - - - The authors hereby grant permission to use, copy, modify, distribute, - and license this software and its documentation for any purpose, provided - that existing copyright notices are retained in all copies and that this - notice is included verbatim in any distributions. No written agreement, - license, or royalty fee is required for any of the authorized uses. - Modifications to this software may be copyrighted by their authors - and need not follow the licensing terms described here, provided that - the new terms are clearly indicated on the first page of each file where - they apply. - - IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY - FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY - DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, - INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE - IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE - NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - MODIFICATIONS. -------------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include "fortify.h" -#include "network.h" -#include "interrupt.h" - -static mkChannel *pChannel = NULL; - -/*---------------------------------------------------------------------------*/ -int ClientSetupInterrupt(char *host, int iPort) -{ - pChannel = UDPConnect(host, iPort); - if (pChannel == NULL) { - return 0; - } else { - return 1; - } -} - -/*---------------------------------------------------------------------------*/ -void ClientStopInterrupt(void) -{ - if (pChannel) { - NETClosePort(pChannel); - free(pChannel); - } -} - -/*---------------------------------------------------------------------------*/ -void SendInterrupt(int iCode) -{ - char pBueffel[132]; - - if ((iCode < 0)) { - return; - } - - snprintf(pBueffel,sizeof(pBueffel)-1, "SICSINT %d", iCode); - UDPWrite(pChannel, pBueffel, strlen(pBueffel)); -} diff --git a/interface.c b/interface.c index c0f8ebf2..238136ee 100644 --- a/interface.c +++ b/interface.c @@ -1,4 +1,4 @@ -/*-------------------------------------------------------------------------- + /*-------------------------------------------------------------------------- I N T E R F A C E @@ -12,6 +12,11 @@ Paul Scherrer Institut CH-5423 Villigen-PSI + Extended over time with utility functions + + Added Drivable and Countable task functions + + Mark Koennecke, February 2013 The authors hereby grant permission to use, copy, modify, distribute, and license this software and its documentation for any purpose, provided @@ -42,6 +47,7 @@ #include "fortify.h" #include "sics.h" #include "motor.h" +#include /*========================================================================= Empty driveable interface functions ==========================================================================*/ @@ -168,7 +174,107 @@ int GetDrivablePosition(void *pObject, SConnection * pCon, float *fPos) *fPos = value; return 1; } +/*--------------------------------------------------------------------------*/ +typedef struct { + void *obj; + pIDrivable pDriv; + SConnection *pCon; + char *name; +}DriveTaskData; +/*-------------------------------------------------------------------------*/ +static void KillDriveTaskData(void *data) +{ + DriveTaskData *taskData = (DriveTaskData *)data; + if(taskData == NULL){ + return; + } + if(taskData->name != NULL){ + free(taskData->name); + } + if(taskData->pCon != NULL){ + SCDeleteConnection(taskData->pCon); + } +} +/*-------------------------------------------------------------------------*/ +static void DriveTaskSignal(void *data, int iSignal, void *pSigData) +{ + DriveTaskData *taskData = (DriveTaskData *)data; + int *interrupt; + + assert(taskData != NULL); + + if(iSignal == SICSINT){ + interrupt = (int *)pSigData; + if(*interrupt != eContinue){ + SCPrintf(taskData->pCon,eLogError,"ERROR: Interrupting %s", taskData->name); + taskData->pDriv->Halt(taskData->obj); + SCSetInterrupt(taskData->pCon,*interrupt); + } + } +} +/*--------------------------------------------------------------------------*/ +static int DriveTaskFunc(void *data) +{ + DriveTaskData *taskData = (DriveTaskData *)data; + int status; + + assert(taskData != NULL); + + + status = taskData->pDriv->CheckStatus(taskData->obj,taskData->pCon); + if(status == HWBusy){ + return 1; + } + DevexecLog("STOP",taskData->name); + if(status == HWIdle || status == OKOK){ + ExeInterest(pServ->pExecutor,taskData->name, "finished"); + } else { + ExeInterest(pServ->pExecutor,taskData->name, "finished with problem"); + } + return 0; +} +/*--------------------------------------------------------------------------*/ +long StartDriveTask(void *obj, SConnection *pCon, char *name, float fTarget) +{ + pIDrivable pDriv = NULL; + char error[132], buffer[132]; + DriveTaskData *taskData = NULL; + + pDriv = GetDrivableInterface(obj); + if(pDriv == NULL){ + SCPrintf(pCon,eError,"ERROR: %s is not drivable", name); + return 1; + } + if(pDriv->CheckLimits(obj,fTarget,error,sizeof(error)) != OKOK){ + SCPrintf(pCon,eError,"ERROR: %s cannot reach %f, reason %s", name, + fTarget, error); + return -1; + } + taskData = calloc(1,sizeof(DriveTaskData)); + if(taskData == NULL){ + SCPrintf(pCon,eError,"ERROR: out of memory starting %s", name); + return -1; + } + if(pDriv->SetValue(obj,pCon,fTarget) != OKOK){ + return -1; + } + ExeInterest(pServ->pExecutor,name,"started"); + DevexecLog("START",name); + InvokeNewTarget(pServ->pExecutor,name,fTarget); + + taskData->obj = obj; + taskData->pDriv = pDriv; + taskData->pCon = SCCopyConnection(pCon); + taskData->name = strdup(name); + + return TaskRegisterN(pServ->pTasker, + name, + DriveTaskFunc, + DriveTaskSignal, + KillDriveTaskData, + taskData,0); +} /*--------------------------------------------------------------------------*/ pICountable GetCountableInterface(void *pObject) { @@ -201,6 +307,112 @@ int isRunning(pICountable self) { return self->running; } +/*--------------------------------------------------------------------------*/ +typedef struct { + void *obj; + pICountable pCount; + SConnection *pCon; + char *name; +}CountTaskData; +/*-------------------------------------------------------------------------*/ +static void KillCountTaskData(void *data) +{ + CountTaskData *taskData = (CountTaskData *)data; + + if(taskData == NULL){ + return; + } + if(taskData->name != NULL){ + free(taskData->name); + } + if(taskData->pCon != NULL){ + SCDeleteConnection(taskData->pCon); + } +} +/*-------------------------------------------------------------------------*/ +static void CountTaskSignal(void *data, int iSignal, void *pSigData) +{ + CountTaskData *taskData = (CountTaskData *)data; + int *interrupt; + + assert(taskData != NULL); + + if(iSignal == SICSINT){ + interrupt = (int *)pSigData; + if(*interrupt != eContinue){ + SCPrintf(taskData->pCon,eLogError,"ERROR: Interrupting %s", taskData->name); + taskData->pCount->Halt(taskData->obj); + SCSetInterrupt(taskData->pCon,*interrupt); + } + } else if(iSignal == IPAUSE){ + taskData->pCount->Pause(taskData->obj,taskData->pCon); + } else if(iSignal == CONTINUE){ + taskData->pCount->Continue(taskData->obj,taskData->pCon); + } +} +/*--------------------------------------------------------------------------*/ +static int CountTaskFunc(void *data) +{ + CountTaskData *taskData = (CountTaskData *)data; + int status; + + assert(taskData != NULL); + + status = taskData->pCount->CheckCountStatus(taskData->obj,taskData->pCon); + if(status == HWBusy) { + SetStatus(eCounting); + return 1; + } else if(status == HWNoBeam){ + SetStatus(eOutOfBeam); + return 1; + } else if(status == HWPause){ + SetStatus(ePaused); + return 1; + } + + DevexecLog("STOP",taskData->name); + if(status == HWIdle || status == OKOK){ + ExeInterest(pServ->pExecutor,taskData->name, "finished"); + } else { + ExeInterest(pServ->pExecutor,taskData->name, "finished with problem"); + } + return 0; +} +/*--------------------------------------------------------------------------*/ +long StartCountTask(void *obj, SConnection *pCon, char *name) +{ + pICountable pCount = NULL; + char error[132], buffer[132]; + CountTaskData *taskData = NULL; + + pCount = FindInterface(obj,COUNTID); + if(pCount == NULL){ + SCPrintf(pCon,eError,"ERROR: %s is not countable", name); + return 1; + } + taskData = calloc(1,sizeof(CountTaskData)); + if(taskData == NULL){ + SCPrintf(pCon,eError,"ERROR: out of memory starting %s", name); + return -1; + } + if(pCount->StartCount(obj,pCon) != OKOK){ + return -1; + } + ExeInterest(pServ->pExecutor,name,"started"); + DevexecLog("START",name); + + taskData->obj = obj; + taskData->pCount = pCount; + taskData->pCon = SCCopyConnection(pCon); + taskData->name = strdup(name); + + return TaskRegisterN(pServ->pTasker, + name, + CountTaskFunc, + CountTaskSignal, + KillCountTaskData, + taskData,0); +} /*--------------------------------------------------------------------------*/ pICallBack GetCallbackInterface(void *pObject) diff --git a/interface.h b/interface.h index b3ede689..c5ac569e 100644 --- a/interface.h +++ b/interface.h @@ -1,5 +1,5 @@ -#line 399 "interface.w" +#line 412 "interface.w" /*--------------------------------------------------------------------------- I N T E R F A C E S @@ -30,107 +30,113 @@ #line 121 "interface.w" -typedef struct { - int ID; - int (*Halt) (void *self); - int (*CheckLimits) (void *self, float fVal, char *error, int iErrLen); - long (*SetValue) (void *self, SConnection * pCon, float fVal); - int (*CheckStatus) (void *self, SConnection * pCon); - float (*GetValue) (void *self, SConnection * pCon); - int iErrorCount; - int drivableStatus; -} IDrivable, *pIDrivable; + typedef struct { + int ID; + int (*Halt)(void *self); + int (*CheckLimits)(void *self, float fVal, + char *error, int iErrLen); + long (*SetValue)(void *self, SConnection *pCon, + float fVal); + int (*CheckStatus)(void *self, SConnection *pCon); + float (*GetValue)(void *self, SConnection *pCon); + int iErrorCount; + int drivableStatus; + } IDrivable, *pIDrivable; -pIDrivable GetDrivableInterface(void *pObject); -int GetDrivablePosition(void *pObject, SConnection * pCon, float *fPos); + pIDrivable GetDrivableInterface(void *pObject); + int GetDrivablePosition(void *pObject, SConnection *pCon, + float *fPos); + long StartDriveTask(void *self, SConnection *pCon, char *name, float fTarget); -#line 425 "interface.w" - - -pIDrivable CreateDrivableInterface(void); - -/* ------------------------ The countable interface ---------------------*/ - -#line 188 "interface.w" - -typedef struct { - int ID; - int running; - int (*Halt) (void *self); - void (*SetCountParameters) (void *self, float fPreset, - CounterMode eMode); - int (*StartCount) (void *self, SConnection * pCon); - int (*CheckCountStatus) (void *self, SConnection * pCon); - int (*Pause) (void *self, SConnection * pCon); - int (*Continue) (void *self, SConnection * pCon); - int (*TransferData) (void *self, SConnection * pCon); -} ICountable, *pICountable; - -pICountable GetCountableInterface(void *pObject); -int GetCountLock(pICountable self, SConnection * pCon); -void ReleaseCountLock(pICountable self); -int isRunning(pICountable self); - -#line 430 "interface.w" - - -pICountable CreateCountableInterface(void); - -/* ------------------------- The CallBack Interface --------------------*/ - -#line 253 "interface.w" - -typedef void (*KillFuncIT) (void *pData); -typedef int (*SICSCallBack) (int iEvent, void *pEventData, - void *pUserData); - -#line 435 "interface.w" - - -#line 275 "interface.w" - -typedef struct __ICallBack *pICallBack; - - /* event source side */ -pICallBack CreateCallBackInterface(void); -void DeleteCallBackInterface(pICallBack self); -int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData); - - /* callback client side */ -long RegisterCallback(pICallBack pInterface, - int iEvent, SICSCallBack pFunc, - void *pUserData, KillFuncIT pKill); -int RemoveCallback(pICallBack pInterface, long iID); -int RemoveCallback2(pICallBack pInterface, void *pUserData); -int RemoveCallbackCon(pICallBack pInterface, SConnection * pCon); - -int CallbackScript(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]); - -pICallBack GetCallbackInterface(void *pData); - -#line 436 "interface.w" - -/*---------------------- The Environment Interface --------------------*/ - -#line 353 "interface.w" - -typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode; -typedef struct { - int iID; - EVMode(*GetMode) (void *self); - int (*IsInTolerance) (void *self); - int (*HandleError) (void *self); -} EVInterface, *pEVInterface; #line 438 "interface.w" -#line 379 "interface.w" + pIDrivable CreateDrivableInterface(void); -pEVInterface CreateEVInterface(void); +/* ------------------------ The countable interface ---------------------*/ -#line 439 "interface.w" +#line 195 "interface.w" + + typedef struct { + int ID; + int running; + int (*Halt)(void *self); + void (*SetCountParameters)(void *self, float fPreset, + CounterMode eMode);\ + int (*StartCount)(void *self, SConnection *pCon); + int (*CheckCountStatus)(void *self, SConnection *pCon); + int (*Pause)(void *self, SConnection *pCon); + int (*Continue)(void *self, SConnection *pCon); + int (*TransferData)(void *self, SConnection *pCon); + } ICountable, *pICountable; + + pICountable GetCountableInterface(void *pObject); + int GetCountLock(pICountable self, SConnection *pCon); + void ReleaseCountLock(pICountable self); + int isRunning(pICountable self); + long StartCountTask(void *self, SConnection *pCon, char *name); + +#line 443 "interface.w" + + + pICountable CreateCountableInterface(void); + +/* ------------------------- The CallBack Interface --------------------*/ + +#line 266 "interface.w" + + typedef void (*KillFuncIT)(void *pData); + typedef int (*SICSCallBack)(int iEvent, void *pEventData, + void *pUserData); + +#line 448 "interface.w" + + +#line 288 "interface.w" + + typedef struct __ICallBack *pICallBack; + + /* event source side */ + pICallBack CreateCallBackInterface(void); + void DeleteCallBackInterface(pICallBack self); + int InvokeCallBack(pICallBack pInterface, int iEvent, void *pEventData); + + /* callback client side */ + long RegisterCallback(pICallBack pInterface, + int iEvent, SICSCallBack pFunc, + void *pUserData, KillFuncIT pKill); + int RemoveCallback(pICallBack pInterface, long iID); + int RemoveCallback2(pICallBack pInterface, void *pUserData); + int RemoveCallbackCon(pICallBack pInterface, SConnection *pCon); + + int CallbackScript(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); + + pICallBack GetCallbackInterface(void *pData); + +#line 449 "interface.w" + +/*---------------------- The Environment Interface --------------------*/ + +#line 366 "interface.w" + + typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode; + typedef struct { + int iID; + EVMode (*GetMode)(void *self); + int (*IsInTolerance)(void *self); + int (*HandleError)(void *self); + } EVInterface, *pEVInterface; + +#line 451 "interface.w" + + +#line 392 "interface.w" + + pEVInterface CreateEVInterface(void); + +#line 452 "interface.w" #endif diff --git a/interface.tex b/interface.tex index 663fefd9..43da4e3b 100644 --- a/interface.tex +++ b/interface.tex @@ -154,6 +154,8 @@ $\langle$driv {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int GetDrivablePosition(void *pObject, SConnection *pCon,@\\ \mbox{}\verb@ float *fPos);@\\ \mbox{}\verb@@\\ +\mbox{}\verb@ long StartDriveTask(void *self, SConnection *pCon, char *name, float fTarget);@\\ +\mbox{}\verb@@\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} @@ -206,6 +208,11 @@ will be returned. object. If the device is a motor corrections for zero points and signs will be applied. Returns 1 on success and 0 on failure} +{\bf StartDriveTask starts a drivable in a new task. If the task can be started, its +task ID is returned. -1 is returned on failure. +} + + \subsubsection{The Countable Interface} This is an interface for interacting with anything which counts. @@ -233,6 +240,7 @@ $\langle$count {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ int GetCountLock(pICountable self, SConnection *pCon);@\\ \mbox{}\verb@ void ReleaseCountLock(pICountable self);@\\ \mbox{}\verb@ int isRunning(pICountable self);@\\ +\mbox{}\verb@ long StartCountTask(void *self, SConnection *pCon, char *name);@\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} @@ -273,6 +281,11 @@ will be returned. {\bf ReleaseCountLock} release the count lock. {\bf isRunning} returns the running flag. + +{\bf StartCountTask starts a countable in a new task. If the task can be started, its +task ID is returned. -1 is returned on failure. +} + \subsubsection{The Callback Interface} The Callback Interface is SICS suport for component behaviour for objects. diff --git a/interface.w b/interface.w index 9aa75d36..3b66d74b 100644 --- a/interface.w +++ b/interface.w @@ -137,6 +137,8 @@ environment controllers fit this bill as well. int GetDrivablePosition(void *pObject, SConnection *pCon, float *fPos); + long StartDriveTask(void *self, SConnection *pCon, char *name, float fTarget); + @} The first member of this structure is an ID which can be used in order to check if the right datastructure has been obtained. @@ -181,6 +183,11 @@ will be returned. object. If the device is a motor corrections for zero points and signs will be applied. Returns 1 on success and 0 on failure} +{\bf StartDriveTask starts a drivable in a new task. If the task can be started, its +task ID is returned. -1 is returned on failure. +} + + \subsubsection{The Countable Interface} This is an interface for interacting with anything which counts. @@ -203,6 +210,7 @@ This is an interface for interacting with anything which counts. int GetCountLock(pICountable self, SConnection *pCon); void ReleaseCountLock(pICountable self); int isRunning(pICountable self); + long StartCountTask(void *self, SConnection *pCon, char *name); @} {\bf running } Is a flag which says if the counter is operating or not. @@ -236,6 +244,11 @@ will be returned. {\bf ReleaseCountLock} release the count lock. {\bf isRunning} returns the running flag. + +{\bf StartCountTask starts a countable in a new task. If the task can be started, its +task ID is returned. -1 is returned on failure. +} + \subsubsection{The Callback Interface} The Callback Interface is SICS suport for component behaviour for objects. diff --git a/intserv.c b/intserv.c index ba6c9bc3..e0a92e0f 100644 --- a/intserv.c +++ b/intserv.c @@ -8,6 +8,10 @@ Mark Koennecke, November 1996 Revised: Mark Koennecke, September 1997 + + Removed unused UDP interrupt port stuff + + Mark Koennecke, February 2013 Copyright: see copyright.h @@ -22,10 +26,7 @@ #include #include "fortify.h" -#include "conman.h" -#include "SCinter.h" -#include "nserver.h" -#include "obdes.h" +#include "sics.h" #include "network.h" #include "interrupt.h" #include "status.h" @@ -40,8 +41,6 @@ #define MAXINTERRUPT 7 #define INTERUPTWAIT 5 -static mkChannel *IntPort = NULL; -static pTaskMan pTask = NULL; /*----------------------------------------------------------------------------*/ static char *pIntText[] = { "continue", @@ -53,35 +52,6 @@ static char *pIntText[] = { "end", NULL }; - -/*---------------------------------------------------------------------------*/ -int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker) -{ - int i; - - - pTask = pTasker; - /* setup interrupt port */ - IntPort = UDPOpen(iPort); - if (IntPort == NULL) { - return 0; - } else { - NetReadRegister(pNet, IntPort, udp, NULL); - return 1; - } -} - -/*--------------------------------------------------------------------------*/ -void ServerStopInterrupt(void) -{ - - /* close the port */ - if (IntPort) { - NETClosePort(IntPort); - free(IntPort); - } -} - /*-------------------------------------------------------------------------*/ void SetInterrupt(int iCode) { @@ -89,7 +59,7 @@ void SetInterrupt(int iCode) iInt = iCode; - TaskSignal(pTask, SICSINT, &iInt); + TaskSignal(pServ->pTasker, SICSINT, &iInt); } /*--------------------------------------------------------------------------*/ diff --git a/make_gen b/make_gen index b4b61b56..2c280282 100644 --- a/make_gen +++ b/make_gen @@ -5,11 +5,13 @@ # Markus Zolliker March 2003 #--------------------------------------------------------------------------- +EPICSOBJ=epicsmotor.o + COBJ = Sclient.o network.o ifile.o intcli.o $(FORTIFYOBJ) SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ servlog.o sicvar.o nserver.o SICSmain.o motorlist.o\ sicsexit.o costa.o task.o $(FORTIFYOBJ) testprot.o\ - macro.o ofac.o obpar.o obdes.o drive.o status.o intserv.o \ + macro.o ofac.o obpar.o obdes.o drive.o status.o intserv.o \ devexec.o mumo.o mumoconf.o selector.o selvar.o fupa.o lld.o \ lld_blob.o strrepl.o lin2ang.o fomerge.o napi5.o napi4.o\ script.o o2t.o alias.o napi.o stringdict.o sdynar.o \ @@ -42,13 +44,13 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \ rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \ histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\ - singlebinb.o taskobj.o sctcomtask.o + singlebinb.o taskobj.o sctcomtask.o tasmono.o MOTOROBJ = motor.o simdriv.o COUNTEROBJ = countdriv.o simcter.o counter.o VELOOBJ = velo.o velosim.o -OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA) +OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA) $(EPICSOBJ) .SUFFIXES: .SUFFIXES: .tcl .htm .c .o .tc @@ -65,7 +67,7 @@ all: libmat libhlib libtecsl libpsi SICServer full: purge all SICServer: $(OBJ) $(SUBLIBS) - $(CC) -g -o SICServer $(OBJ) $(LIBS) + $(CC) $(DBG) -o SICServer $(OBJ) $(LIBS) matrix/libmatrix.a: libmat diff --git a/makefile_slinux b/makefile_slinux index 3602a289..3c4c5ed5 100644 --- a/makefile_slinux +++ b/makefile_slinux @@ -11,19 +11,21 @@ NI= -DHAVENI NIOBJ= nigpib.o NILIB=$(SINQDIR)/sl6/lib/cib.o +EPICSLIBS=-L$(SINQDIR)/sl6/lib/linux-x86 -lezca -lca -lCom + include sllinux_def CC = gcc CFLAGS = -I$(HDFROOT)/include -DNXXML -DHDF5 $(NI) \ -Ipsi/hardsup -I. -MMD \ - -Werror -DCYGNUS -DNONINTF -g $(DFORTIFY) \ + -Werror -DCYGNUS -DNONINTF $(DBG) $(DFORTIFY) \ -Wall -Wno-unused -Wunused-value -Wno-comment -Wno-switch BINTARGET = bin EXTRA=nintf.o SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \ psi/tecs/libtecsl.a -LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\ +LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB) $(EPICSLIBS) \ -ltcl $(HDFROOT)/lib/libhdf5.a \ $(HDFROOT)/lib/libsz.a \ $(HDFROOT)/lib/libjson.a \ diff --git a/motor.c b/motor.c index 67ddd2af..ccf5fc65 100644 --- a/motor.c +++ b/motor.c @@ -992,6 +992,7 @@ int MotorCheckPosition(void *sulf, SConnection * pCon) */ extern MotorDriver *MakePiPiezo(Tcl_Interp * pTcl, char *pArray); +extern MotorDriver *epicsMakeMotorDriver(char *baseName); int MotorCreate(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) @@ -1052,6 +1053,23 @@ int MotorCreate(SConnection * pCon, SicsInterp * pSics, void *pData, SCWrite(pCon, pBueffel, eLogError); return 0; } + } else if (strcmp(argv[2], "epics") == 0) { + if(argc > 3){ + pDriver = epicsMakeMotorDriver(argv[3]); + if (!pDriver) { + return 0; + } + } else { + SCWrite(pCon,"ERROR: missing basename argument to create EPICS motor",eError); + return 0; + } + /* create the motor */ + pNew = MotorInit("regress", argv[1], pDriver); + if (!pNew) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Failure to create motor %s", argv[1]); + SCWrite(pCon, pBueffel, eLogError); + return 0; + } } else { site = getSite(); if (site != NULL) { diff --git a/multicounter.c b/multicounter.c index ed129a69..078d556d 100644 --- a/multicounter.c +++ b/multicounter.c @@ -37,6 +37,7 @@ typedef struct { pICountable slaves[MAXSLAVE]; char *transferScript; int nSlaves; + int checkSlaves; } MultiCounter, *pMultiCounter; /*--------------------------------------------------------------------------*/ static void KillMultiDriver(struct __COUNTER *data) @@ -106,10 +107,12 @@ static int MMCCStart(void *pData, SConnection * pCon) pCount->isUpToDate = 0; pCount->tStart = time(NULL); InvokeCallBack(pCount->pCall, COUNTSTART, pCon); + self->checkSlaves = 0; return OKOK; } /*-------------------------------------------------------------------------*/ + static int MMCCStatus(void *pData, SConnection * pCon) { int status, i; @@ -129,25 +132,46 @@ static int MMCCStatus(void *pData, SConnection * pCon) return HWFault; } - status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon); - pMaster = (pCounter)self->slaveData[0]; - pCount->pDriv->fLastCurrent = GetControlValue(pMaster); - if (status == HWIdle || status == HWFault) { - /* - stop counting on slaves when finished or when an error - occurred. - */ - InvokeCallBack(pCount->pCall, COUNTEND, pCon); - MMCCHalt(pCount); - } - for (i = 1; i < MAXSLAVE; i++) { - if (self->slaves[i] != NULL) { - pDum = (pDummy) self->slaveData[i]; - if (strcmp(pDum->pDescriptor->name, "HistMem") == 0) { - HistDirty((pHistMem) self->slaveData[i]); - } - ReleaseCountLock(self->slaves[i]); + if(self->checkSlaves == 0) { + status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon); + if (status == HWIdle || status == HWFault) { + /* + stop counting on slaves when finished or when an error + occurred. + */ + MMCCHalt(pData); + ReleaseCountLock(pCount->pCountInt); + self->checkSlaves = 1; + status = HWBusy; } + } else { + /* + * wait for the detectors to report finish too. Otherwise, with the second + * generation HM data may not be fully transferred. + */ + for(i = 1; i < self->nSlaves; i++){ + status = self->slaves[i]->CheckCountStatus(self->slaveData[i], pCon); + if(!(status == HWIdle || status == HWFault)){ + return status; + } + } + /* + Warning: this assumes that slaves 1 - MAXSLAVE are histogram memories. + If this assumption does not hold, change this code to check if this + is really a histogram memory. + */ + for (i = 1; i < self->nSlaves; i++) { + if (self->slaves[i] != NULL) { + pDum = (pDummy)self->slaveData[i]; + if (strcmp(pDum->pDescriptor->name, "HistMem") == 0) { + HistDirty((pHistMem) self->slaveData[i]); + } + ReleaseCountLock(self->slaves[i]); + } + } + status = HWIdle; + InvokeCallBack(pCount->pCall, COUNTEND, pCon); + self->checkSlaves = 0; } return status; } diff --git a/nserver.c b/nserver.c index 5d730c2d..6356a6e8 100644 --- a/nserver.c +++ b/nserver.c @@ -39,10 +39,6 @@ #include "sicshipadaba.h" #include "commandlog.h" -int ServerSetupInterrupt(int iPort, pNetRead pNet, pTaskMan pTasker); - /* - configures a port for listening for interrupts - */ extern void StopExit(void); /* in SICSmain.c */ @@ -236,10 +232,6 @@ int InitServer(char *file, pServer * pServ) IFDeleteOptions(pSICSOptions); return 0; } - iRet = ServerSetupInterrupt(iPort, pReader, self->pTasker); - if (!iRet) { - SCWrite(pCon, "WARNING: UDP interrupt port not initialized", eWarning); - } /* install a secret fully priviledged entry point for ME */ AddUser("Achterbahn", "Kiel", usInternal); @@ -346,10 +338,6 @@ void StopServer(pServer self) /* remove the in memory password database */ KillPasswd(); - - /* close Interrupt system */ - ServerStopInterrupt(); - /* Remove Status Callback */ KillStatus(NULL); @@ -481,6 +469,13 @@ int UserWait(SConnection * pCon, SicsInterp * pSics, void *pData, } } /*--------------------------------------------------------------------------*/ +int UserYield(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + TaskYield(pServ->pTasker); + return 1; +} +/*--------------------------------------------------------------------------*/ int SicsWait(long lTime) { pTaskMan pTasker = NULL; diff --git a/obdes.h b/obdes.h index d1477dc0..fd738465 100644 --- a/obdes.h +++ b/obdes.h @@ -1,5 +1,5 @@ -#line 385 "interface.w" +#line 398 "interface.w" #line 29 "interface.w" @@ -25,19 +25,19 @@ #include #include -typedef struct { - char *name; - int (*SaveStatus) (void *self, char *name, FILE * fd); - void *(*GetInterface) (void *self, int iInterfaceID); - IPair *pKeys; - pHdb parNode; -} ObjectDescriptor, *pObjectDescriptor; + typedef struct { + char *name; + int (*SaveStatus)(void *self, char *name,FILE *fd); + void *(*GetInterface)(void *self, int iInterfaceID); + IPair *pKeys; + pHdb parNode; + } ObjectDescriptor, *pObjectDescriptor; /*---------------------------------------------------------------------------*/ -pObjectDescriptor CreateDescriptor(char *name); -void DeleteDescriptor(pObjectDescriptor self); -pObjectDescriptor FindDescriptor(void *pData); - + pObjectDescriptor CreateDescriptor(char *name); + void DeleteDescriptor(pObjectDescriptor self); + pObjectDescriptor FindDescriptor(void *pData); + /*============================================================================ Objects which do not carry data need a dummy descriptor. Otherwise drive or scan will protection fault when trying to drive something @@ -45,26 +45,26 @@ pObjectDescriptor FindDescriptor(void *pData); */ typedef struct { - pObjectDescriptor pDescriptor; -} Dummy, *pDummy; + pObjectDescriptor pDescriptor; + }Dummy, *pDummy; + + pDummy CreateDummy(char *name); + void KillDummy(void *pData); -pDummy CreateDummy(char *name); -void KillDummy(void *pData); + int iHasType(void *pData, char *Type); + +#endif -int iHasType(void *pData, char *Type); - -#endif - -#line 386 "interface.w" +#line 399 "interface.w" /*--------------------------------------------------------------------------*/ /* Additional properties used by the ANSTO site to provide more information * about each object instance, especially devices. */ -void SetDescriptorKey(pObjectDescriptor self, char *keyName, char *value); -void SetDescriptorGroup(pObjectDescriptor self, char *group); -void SetDescriptorDescription(pObjectDescriptor self, char *description); -char *GetDescriptorKey(pObjectDescriptor self, char *keyName); -char *GetDescriptorGroup(pObjectDescriptor self); -char *GetDescriptorDescription(pObjectDescriptor self); + void SetDescriptorKey(pObjectDescriptor self, char *keyName, char *value); + void SetDescriptorGroup(pObjectDescriptor self, char *group); + void SetDescriptorDescription(pObjectDescriptor self, char *description); + char * GetDescriptorKey(pObjectDescriptor self, char *keyName); + char * GetDescriptorGroup(pObjectDescriptor self); + char * GetDescriptorDescription(pObjectDescriptor self); diff --git a/ofac.c b/ofac.c index 88286c92..521f45bd 100644 --- a/ofac.c +++ b/ofac.c @@ -17,6 +17,8 @@ #include "site.h" #include "sicshipadaba.h" +static unsigned int killStartupCommands = 1; + extern void DevExecInit(void); /* devexec.c */ /*--------------------------------------------------------------------------*/ static void InitGeneral(void) @@ -44,6 +46,7 @@ static void InitGeneral(void) INIT(AddGenBinProtocoll); INIT(AddSyncedProt); INIT(MakeTrace); + INIT(InitTaskOBJ); INIT(SiteInit); /* site specific initializations */ } @@ -111,6 +114,7 @@ static void InitIniCommands(SicsInterp * pInter) PCMD("TclReplaceDrivable", TclReplaceDrivable); PCMD("transact", TransactAction); PCMD("wait", UserWait); + PCMD("yield", UserYield); PCMD("checksum", CheckSum); /* startup commands in alphabetic order */ @@ -169,7 +173,6 @@ static void InitIniCommands(SicsInterp * pInter) SCMD("SicsAlias", SicsAlias); SCMD("SicsUser", PWSicsUser); SCMD("TokenInit", TokenInit); - SCMD("MakeTask", TaskOBJFactory); SCMD("UpdateFactory", UpdateFactory); SCMD("VarMake", VarFactory); SCMD("VelocitySelector", VelSelFactory); @@ -229,7 +232,13 @@ int InitObjectCommands(pServer pServ, char *file) if (site != NULL && site->RemoveSiteCommands != NULL) { site->RemoveSiteCommands(pSics); } - - RemoveStartupCommands(); + if(killStartupCommands){ + RemoveStartupCommands(); + } return 1; } +/*---------------------------------------------------------------------------------*/ +void KeepStartupCommands() +{ + killStartupCommands = 0; +} diff --git a/ofac.h b/ofac.h index fd13d0f2..55ec03a2 100644 --- a/ofac.h +++ b/ofac.h @@ -21,5 +21,4 @@ #include "sics.h" int InitObjectCommands(pServer pServ, char *file); - #endif diff --git a/reflist.c b/reflist.c index dd2e81bd..0f0833e1 100644 --- a/reflist.c +++ b/reflist.c @@ -24,6 +24,10 @@ static char undef[] = "Undefined"; #define IDXFMT " %8.4f" #define ANGFMT " %8.2f" + +int CountTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, + pHdb par[], int nPar); /* from hdbtable.c */ + /*----------------------------------------------------------------------*/ typedef struct { int idxCount; @@ -549,6 +553,10 @@ pSICSOBJ CreateReflectionList(SConnection * pCon, SicsInterp * pSics, SetHdbProperty(cmd,"priv","user"); AddSICSHdbPar(cmd, "id", usUser, MakeHdbText("")); + + cmd = AddSICSHdbPar(pNew->objectNode, "count", usUser, + MakeSICSFunc(CountTblCmd)); + AddCommand(pSics, name, InterInvokeSICSOBJ, KillSICSOBJ, pNew); return pNew; } diff --git a/scan.c b/scan.c index 07eb4a3a..c7504866 100644 --- a/scan.c +++ b/scan.c @@ -644,6 +644,7 @@ int DoScan(pScanData self, int iNP, int iMode, float fPreset, return 0; } + self->iActive = 1; self->iNP = iNP; self->iMode = iMode; self->fPreset = fPreset; @@ -661,7 +662,6 @@ int DoScan(pScanData self, int iNP, int iMode, float fPreset, } - self->iActive = 1; iRet = ScanLoop(self); ScriptScanFinish(self); InvokeCallBack(self->pCall, SCANEND, self); diff --git a/sctdriveobj.c b/sctdriveobj.c index f98f65f5..894fda32 100644 --- a/sctdriveobj.c +++ b/sctdriveobj.c @@ -148,7 +148,7 @@ static long SCTDRIVSetValue(void *data, SConnection * pCon, float val) } pPriv->pCon = SCCopyConnection(pCon); - StopByData(pServ->pExecutor, data); + /* StopByData(pServ->pExecutor, data); */ v = MakeHdbFloat(val); SetHdbProperty(self->objectNode, "writestatus", "start"); diff --git a/sicsdata.c b/sicsdata.c index d3d23f02..f00784e7 100644 --- a/sicsdata.c +++ b/sicsdata.c @@ -711,8 +711,13 @@ static int copyHM(pSICSData self, int argc, char *argv[], SCWrite(pCon, "ERROR: out of memory in SICSData copyhm", eError); return 0; } - GetHistogramDirect(pHist, pCon, 0, start, end, iData, + if(end > GetHistLength(pHist)){ + GetHistogramDirect(pHist, pCon, 0, start, end, iData, (end - start) * sizeof(int)); + } else { + GetHistogram(pHist, pCon, 0, start, end, iData, + (end - start) * sizeof(int)); + } assignType(self, pos, pos + (end - start), INTTYPE); SCSendOK(pCon); return 1; diff --git a/singlex.c b/singlex.c index 60cbff71..56a80fe2 100644 --- a/singlex.c +++ b/singlex.c @@ -284,7 +284,7 @@ static hdbCallbackReturn SetModeCB(pHdb node, void *userData, priv->mode = Bisecting; initializeSingleBisectingOrion(priv->diffractometer); free(set->v->v.text); - set->v->v.text = strdup("bi"); + set->v->v.text = strdup("bio"); return hdbContinue; break; case NB: diff --git a/sllinux_def b/sllinux_def index 31af4a94..1116d6fb 100644 --- a/sllinux_def +++ b/sllinux_def @@ -10,4 +10,6 @@ MFLAGS=-f makefile_linux$(DUMMY) HDFROOT=/afs/psi.ch/project/sinq/sl6 -TCLINC=. \ No newline at end of file +TCLINC=. + +DBG= -g \ No newline at end of file diff --git a/tacov.c b/tacov.c deleted file mode 100644 index e0126ffd..00000000 --- a/tacov.c +++ /dev/null @@ -1,627 +0,0 @@ -/* tacov.f -- translated by f2c (version 20000817). - You must link the resulting object file with the libraries: - -lf2c -lm (in that order) -*/ - -#include "f2c.h" - -/* Common Block Declarations */ - -struct { - integer inx; - real c1rx, c2rx, rmin, rmax, cl1r; -} curve_; - -#define curve_1 curve_ - -/* Table of constant values */ - -static doublereal c_b7 = 1.; -static doublereal c_b9 = 360.; - -/* ----------------------------------------------------------------------- */ -/* FILE T_CONV */ -/* SUBROUTINE T_CONV(EI,AKI,EF,AKF,QHKL,EN,HX,HY,HZ,IF1,IF2,LDK,LDH,LDF */ -/* 1 LPA,DM,DA,HELM,F1H,F1V,F2H,F2V,F,IFX,ISS,ISM,ISA, */ -/* 2 T_A,T_RM,T_ALM,LDRA,LDR_RM,LDR_ALM,P_IH,C_IH,IER) */ -/* SUBROUTINE EX_CASE(DX,ISX,AKX,AX1,AX2,RX,ALX,IER) */ -/* SUBROUTINE SAM_CASE(QT,QM,QS,AKI,AKF,AX3,AX4,ISS,IER) */ -/* SUBROUTINE HELM_CASE(HX,HY,HZ,P_IH,AKI,AKF,A4,QM,HELM,IER) */ -/* SUBROUTINE FLIP_CASE(IF1,IF2,P_IH,F1V,F1H,F2V,F2H,AKI,AKF,IER) */ -/* ----------------------------------------------------------------------- */ -/* Subroutine */ int t_conv__(real * ei, real * aki, real * ef, real * akf, - real * - qhkl, real * en, real * hx, real * hy, - real * hz, integer * if1, integer * if2, - logical * ldk, logical * ldh, logical * ldf, - logical * lpa, real * dm, real * da, - real * helm, real * f1h, real * f1v, - real * f2h, real * f2v, real * f, - integer * ifx, integer * iss, integer * ism, - integer * isa, real * t_a__, real * t_rm__, - real * t_alm__, real * qm, logical * ldra, - logical * ldr_rm__, logical * ldr_alm__, - real * p_ih__, real * c_ih__, integer * ier) -{ - /* System generated locals */ - doublereal d__1; - - /* Builtin functions */ - double sqrt(doublereal); - - /* Local variables */ - static doublereal edef[2], dakf, daki; - static integer imod; - extern /* Subroutine */ int sam_case__(doublereal *, doublereal *, - doublereal *, doublereal *, - doublereal *, doublereal *, - doublereal *, integer *, - integer *); - static integer i__; - static doublereal akdef[2]; - extern /* Subroutine */ int helm_case__(real *, real *, real *, real *, - real *, real *, real *, - doublereal *, real *, real *, - integer *); - static doublereal dqhkl[3]; - extern /* Subroutine */ int flip_case__(integer *, integer *, real *, - real *, real *, real *, real *, - real *, real *, integer *); - static logical lmoan[2]; - static doublereal a1, a2, a3, a4, a5, a6; - static integer id; - static doublereal ra; - extern /* Subroutine */ int rl2spv_(doublereal *, doublereal *, - doublereal *, doublereal *, - integer *); - static integer iq; - static doublereal rm; - static logical lqhkle; - extern /* Subroutine */ int erreso_(integer *, integer *); - static doublereal dda, ala, def, dei, ddm, alm, dqm; - extern /* Subroutine */ int ex_case__(doublereal *, integer *, doublereal - *, doublereal *, doublereal *, - doublereal *, doublereal *, - integer *); - static doublereal dqt[3], dqs; - -/* ----------------------------------------------------------------------- */ - -/* INPUT */ -/* EI,AKI,EF,AKF,QHKL,EN,HX,HY,HZ : POTENTIAL TARGETS */ -/* IF1,IF2 Status of flippers On (1) Off (0) */ -/* LDK(8) LOGICAL INDICATING IF (ENERGY,K OR Q) ARE DRIVEN */ -/* LDH,LDF LOGICAL INDICATING IF (HX,HY,HZ) OR (F1,F2) ARE DRIVEN */ - -/* configuration of the machine */ -/* LPA LOGICAL TRUE IF MACHINE IN POLARIZATION MODE */ -/* DM,DA,HELM,F1H,F1V,F2H,F2V,F,IFX,ISS,ISM,ISA,QM (F ENERGY UNIT) */ - -/* OUTPUT */ -/* T_A TARGETS OF ANGLES A1-A6 */ -/* T_RM,T_ALM TARGETS OF RM ,LM */ -/* QM TARGETS OF QM */ -/* LDRA LOGICAL INDICATING WHICH ANGLES ARE TO BE DRIVEN */ -/* LDR_RM,LDR_ALM LOGICAL INDICATING IF RM OR ALM ARE TO BE DRIVEN */ -/* P_IH TARGETS OF CURRENTS FOR FLIPPERS AND HELMOTZ (8 CURRENTS) */ -/* C_IH CONVERSION FACTORS FOR HELMOTZ (4 CURRENTS) */ - -/* SPECIAL OUTPUTS */ -/* TARGET OF EI(EF) IS UPDATED IS KI(KF) IS DRIVEN */ -/* TARGET OF VARIABLE ENERGY IS UPDATED IF EN IS DRIVEN */ -/* ----------------------------------------------------------------------- */ -/* ----------------------------------------------------------------------- */ -/* PASSED PARAMETERS */ -/* ----------------------------------------------------------------------- */ -/* LOCAL VARIABLES */ - -/* ----------------------------------------------------------------------- */ -/* SET UP */ -/* IMOD INDEX FOR ERROR TREATMENAT BY ERRESO */ -/* LDQHKLE : LOGICAL INDICATING THAT WE ARE DEALING WITH A MOVE */ -/* IN RECIPROCICAL SPACE */ -/* WE REMAP THE ENERGY PB AS FIXED ENERGY IN EDEF(1) */ -/* AND VARIABLE ENERGY IN EDEF(2) */ -/* IF ISA IS NUL SET IFX TO 1 AND PUT EF,KF, EQUAL TO EI,KI */ - - /* Parameter adjustments */ - --c_ih__; - --p_ih__; - --ldra; - --t_a__; - --ldk; - --qhkl; - - /* Function Body */ - imod = 3; - ddm = *dm; - dda = *da; - for (i__ = 1; i__ <= 2; ++i__) { - lmoan[i__ - 1] = FALSE_; - } - lqhkle = FALSE_; - for (iq = 5; iq <= 8; ++iq) { - lqhkle = lqhkle || ldk[iq]; - } - daki = *aki; - dakf = *akf; - if (*isa == 0) { - *ifx = 1; - } - edef[*ifx - 1] = *ei; - akdef[*ifx - 1] = *aki; - edef[3 - *ifx - 1] = *ef; - akdef[3 - *ifx - 1] = *akf; - if (*isa == 0) { - edef[1] = edef[0]; - akdef[1] = akdef[0]; - ldk[3] = TRUE_; - ldk[4] = TRUE_; - t_a__[5] = 0.f; - t_a__[6] = 0.f; - ldra[5] = TRUE_; - ldra[6] = TRUE_; - } -/* ----------------------------------------------------------------------- */ -/* FIRST TAKE IN ACCOUNT THE FIXED ENERGY PB */ - - if (ldk[(*ifx << 1) - 1] || ldk[*ifx * 2]) { - lmoan[*ifx - 1] = TRUE_; - if (ldk[(*ifx << 1) - 1]) { - *ier = 1; - if (edef[0] < .1) { - goto L999; - } - *ier = 0; - akdef[0] = sqrt(edef[0] / *f); - } else { - *ier = 1; - if (akdef[0] < .1) { - goto L999; - } - *ier = 0; -/* Computing 2nd power */ - d__1 = akdef[0]; - edef[0] = *f * (d__1 * d__1); - } - } -/* ----------------------------------------------------------------------- */ -/* NOW TAKE IN ACCOUNT THE VARIABLE ENERGY PB */ -/* VARIABLE ENERGUY IS DRIVEN EITHER EXPLICITLY */ -/* E.G. BY DRIVING EI OR KI WITH IFX=2 */ -/* ( AND WE MUST CALCULATE EN FROM EVAR) */ -/* THE RULE IS : EI=EF+EN : EN IS THE ENERGY LOSS OF NEUTRONS */ -/* OR ENERGY GAIN OF SAMPLE */ -/* OR IMPLICITLY BY DRIVING THE TRANSFERED ENERGY EN */ -/* ( AND WE MUST CALCULATE EVAR FROM EN) */ -/* IF KI IS CONSTANT USE THE CURRENT VALUE CONTAINED IN POSN ARRAY */ -/* TO CALCULATE THE NON-"CONSTANT" K. */ -/* IF KF IS CONSTANT USE ALWAYS THE VALUE IN TARGET AND */ -/* DO A DRIVE OF KF TO KEEP A5/A6 IN RIGHT POSITION */ - - if (ldk[5 - (*ifx << 1)] || ldk[6 - (*ifx << 1)]) { - lmoan[3 - *ifx - 1] = TRUE_; - if (ldk[5 - (*ifx << 1)]) { - *ier = 1; - if (edef[1] < 1e-4) { - goto L999; - } - *ier = 0; - akdef[1] = sqrt(edef[1] / *f); - } else { - *ier = 1; - if (akdef[1] < 1e-4) { - goto L999; - } - *ier = 0; -/* Computing 2nd power */ - d__1 = akdef[1]; - edef[1] = *f * (d__1 * d__1); - } - *en = (3 - (*ifx << 1)) * (edef[0] - edef[1]); - } else if (lqhkle) { - lmoan[3 - *ifx - 1] = TRUE_; - edef[1] = edef[0] + ((*ifx << 1) - 3) * *en; - *ier = 1; - if (edef[1] < 1e-4) { - goto L999; - } - *ier = 0; - akdef[1] = sqrt(edef[1] / *f); - } -/* ----------------------------------------------------------------------- */ -/* CALCULATE MONOCHROMATOR AND ANALYSER ANGLES */ - - if (lmoan[0]) { - dei = edef[*ifx - 1]; - daki = akdef[*ifx - 1]; - ex_case__(&ddm, ism, &daki, &a1, &a2, &rm, &alm, ier); - if (*ier == 0) { - *aki = daki; - *ei = dei; - t_a__[1] = a1; - t_a__[2] = a2; - *t_rm__ = rm; - *t_alm__ = alm; - ldra[1] = TRUE_; - ldra[2] = TRUE_; - *ldr_rm__ = TRUE_; - *ldr_alm__ = TRUE_; - } else { - goto L999; - } - } - if (lmoan[1]) { - def = edef[3 - *ifx - 1]; - dakf = akdef[3 - *ifx - 1]; - ex_case__(&dda, isa, &dakf, &a5, &a6, &ra, &ala, ier); - if (*ier == 0) { - *akf = dakf; - *ef = def; - t_a__[5] = a5; - t_a__[6] = a6; - ldra[5] = TRUE_; - ldra[6] = TRUE_; - } else { - goto L999; - } - } -/* ----------------------------------------------------------------------- */ -/* USE (QH,QK,QL) TO CALCULATE A3 AND A4 */ -/* CALCULATE Q1 AND Q2 IN SCATTERING PLANE */ - - imod = 2; - if (lqhkle) { - for (id = 1; id <= 3; ++id) { - dqhkl[id - 1] = qhkl[id]; - } - rl2spv_(dqhkl, dqt, &dqm, &dqs, ier); - if (*ier != 0) { - goto L999; - } - sam_case__(dqt, &dqm, &dqs, &daki, &dakf, &a3, &a4, iss, ier); - if (*ier == 0) { - t_a__[3] = a3; - t_a__[4] = a4; - ldra[3] = TRUE_; - ldra[4] = TRUE_; - *qm = dqm; - } else { - goto L999; - } - } -/* ----------------------------------------------------------------------- */ -/* DEAL WITH FLIPPERS AND HELMOTZ COILS IF LPA */ - - if (*lpa && (lmoan[0] || lmoan[1])) { - if (*ldf) { - flip_case__(if1, if2, &p_ih__[1], f1v, f1h, f2v, f2h, aki, akf, ier); - } - if (*ldh) { - helm_case__(hx, hy, hz, &p_ih__[1], &c_ih__[1], aki, akf, &a4, qm, - helm, ier); - } - } -/* ----------------------------------------------------------------------- */ -L999: - if (*ier != 0) { - erreso_(&imod, ier); - } - return 0; -} /* t_conv__ */ - -/* Subroutine */ int ex_case__(doublereal * dx, integer * isx, - doublereal * akx, - doublereal * ax1, doublereal * ax2, - doublereal * rx, doublereal * alx, - integer * ier) -{ - /* System generated locals */ - doublereal d__1, d__2; - - /* Builtin functions */ - double asin(doublereal), sin(doublereal), cos(doublereal), - sqrt(doublereal); - - /* Local variables */ - static doublereal dcl1r, dc1rx, dc2rx, drmin, drmax, arg; - -/* ----------------------------------------------------------------------- */ -/* CALCULATE ANGLES ON MONO/ANALYSER */ -/* CALCULATE AX1 AX2 */ -/* CALCULATE RX LX MONO CURVATURE AND LM FOR IN8 */ - -/* INPUT */ -/* DX D-SPACINGS */ -/* ISX SENS OF SCATTERING ON CRYSTAL */ -/* AKX TARGET OF MOMENTUM */ -/* OUTPUT */ -/* AX1 AX2 THETA 2*THETA ANGLES */ -/* RX MONO OR ANALYSER CURVATURE */ -/* ALX SPECIAL TRANSLATION FOR IN8 */ -/* IER */ -/* 1 ' KI OR KF CANNOT BE OBTAINED CHECK D-SPACINGS', */ -/* 2 ' KI OR KF TOO SMALL', */ -/* 3 ' KI OR KF TOO BIG', */ - -/* ----------------------------------------------------------------------- */ -/* Values of parameters */ - -/* INX=1 IN8 , INX=0 others instruments */ -/* C1RX C2RX constants values to calculate RM on all instruments */ -/* RMIN, RMAX min max on RNM */ -/* CL1R constant value to calculate LM for IN8 */ - -/* ----------------------------------------------------------------------- */ -/* ----------------------------------------------------------------------- */ -/* PASSED PARAMETERS */ -/* ----------------------------------------------------------------------- */ -/* LOCAL VAR */ -/* ----------------------------------------------------------------------- */ -/* INIT AND TEST */ - - *ier = 0; - dc1rx = curve_1.c1rx; - dc2rx = curve_1.c2rx; - drmin = curve_1.rmin; - drmax = curve_1.rmax; - dcl1r = curve_1.cl1r; - if (*dx < .1f) { - *ier = 1; - } - if (*akx < .1f) { - *ier = 2; - } - arg = 3.1415926535897932384626433832795f / (*dx * *akx); - if (abs(arg) > 1.f) { - *ier = 3; - } - if (*ier != 0) { - goto L999; - } -/* ----------------------------------------------------------------------- */ -/* CALCULATION OF THE TWO ANGLES */ - - *ax1 = asin(arg) * *isx * 57.29577951308232087679815481410517f; - *ax2 = *ax1 * 2.; -/* ----------------------------------------------------------------------- */ -/* CALCULATION OF MONO CURVATURE RM OR ANALYSER CURVATURE RA */ -/* STANDARD LAW IS C1RX+C2RX/SIN(A1/RD) */ -/* C1RX AND C2RX ARE CONSTANTS DEPENDING ON MONO AND MACHINES */ - -/* C1RX=.47 */ -/* C2RX=.244 */ -/* RMIN=0. */ -/* RMAX=20. */ -/* IN1/IN3/IN12/IN14/IN20 CASE */ - if (curve_1.inx == 0) { -/* Computing MIN */ -/* Computing MAX */ - d__2 = dc1rx + dc2rx / sin(abs(*ax1) / - 57.29577951308232087679815481410517f); - d__1 = max(d__2, drmin); - *rx = min(d__1, drmax); - } else { -/* IN8 CASE */ - *alx = - dcl1r / sin(*ax2 / 57.29577951308232087679815481410517f) * - cos(*ax2 / 57.29577951308232087679815481410517f); - *rx = dc2rx * sqrt(sin(*ax2 / 57.29577951308232087679815481410517f)) - - dc1rx; - } -/* ----------------------------------------------------------------------- */ -L999: - return 0; -} /* ex_case__ */ - -/* ========================================================================= */ -/* Subroutine */ int sam_case__(doublereal * qt, doublereal * qm, - doublereal * - qs, doublereal * aki, doublereal * akf, - doublereal * ax3, doublereal * ax4, - integer * iss, integer * ier) -{ - /* System generated locals */ - doublereal d__1, d__2; - - /* Builtin functions */ - double acos(doublereal), atan2(doublereal, doublereal), d_sign(doublereal - *, - doublereal - *), - d_mod(doublereal *, doublereal *); - - /* Local variables */ - static doublereal arg, sax3; - -/* ----------------------------------------------------------------------- */ -/* DEAL WITH SAMPLE ANGLES CALCULATION FROM Q VERTOR IN C-N PLANE */ -/* CALCULATE A3 AND A4 */ -/* INPUT */ -/* QT Q-VECTOR IN SCATTERING PLANE */ -/* QM,QS Q MODULUS AND QMODULUS SQUARED */ -/* AKI,AKF MOMEMTA ON MONO AND ANYLSER */ -/* ISS SENS OF SCATTERING ON SAMPLE */ - -/* OUTPUT */ -/* AX3 AX4 ANGLES ON SAMPLES */ -/* IER SAME ERROR AS RL2SPV */ -/* IER */ -/* 1 ' MATRIX S NOT OK', */ -/* 2 ' Q NOT IN SCATTERING PLANE', */ -/* 3 ' Q MODULUS TOO SMALL', */ -/* 4 ' Q MODULUS TOO BIG', */ -/* ----------------------------------------------------------------------- */ -/* ----------------------------------------------------------------------- */ -/* PASSED PARAMETERS */ -/* ----------------------------------------------------------------------- */ -/* INIT AND TEST */ - - /* Parameter adjustments */ - --qt; - - /* Function Body */ - *ier = 0; - if (abs(*qs) < 1e-6 || abs(*qm) < .001) { - *ier = 3; - goto L999; - } -/* ----------------------------------------------------------------------- */ -/* CALCULATE A3 AND MOVE IT INTHE -180 ,+180 INTERVAL */ - -/* Computing 2nd power */ - d__1 = *aki; -/* Computing 2nd power */ - d__2 = *akf; - arg = (d__1 * d__1 + d__2 * d__2 - *qs) / (*aki * 2. * *akf); - if (abs(arg) > 1.) { - *ier = 4; - goto L999; - } else { - *ax4 = acos(arg) * *iss * 57.29577951308232087679815481410517; - } -/* Computing 2nd power */ - d__1 = *akf; -/* Computing 2nd power */ - d__2 = *aki; - *ax3 = - (-atan2(qt[2], qt[1]) - - acos((d__1 * d__1 - *qs - - d__2 * d__2) / (*qm * -2. * *aki)) * d_sign(&c_b7, - ax4)) * - 57.29577951308232087679815481410517; - sax3 = d_sign(&c_b7, ax3); - d__1 = *ax3 + sax3 * 180.; - *ax3 = d_mod(&d__1, &c_b9) - sax3 * 180.; - -/* IF(LPLATE) AX3=-ATAN(SIN(AX4/RD)/(LSA*TAN(AX5/RD)/(ALMS*C */ -/* 1 TAN(AX1/RD))*(AKI/KF)**2-COS(AX4/RD)))*RD !PLATE FOCALIZATION OPTION */ -/* IF(AXX3.GT.180.D0) AX3=AX3-360.D0 */ -/* IF( A3.LT.-180.D0) AX3=AX3+360.D0 */ -/* IF(LPLATE.AND.A3.GT.0.0) AX3=AX3-180 */ -/* C----------------------------------------------------------------------- */ -L999: - return 0; -} /* sam_case__ */ - -/* ============================================================================ */ -/* Subroutine */ int helm_case__(real * hx, real * hy, real * hz, - real * t_ih__, - real * c_ih__, real * aki, real * akf, - doublereal * a4, real * qm, real * helm, - integer * ier) -{ - /* System generated locals */ - real r__1, r__2; - - /* Builtin functions */ - double cos(doublereal), sin(doublereal), atan2(doublereal, doublereal), - sqrt(doublereal); - - /* Local variables */ - static real hrad, hdir, qpar, hdir2, qperp; - static integer ic; - static real phi; - -/* ----------------------------------------------------------------------- */ -/* DEAL WITH HELMOTZ COIL FIELD CALCULATIONS */ -/* CALCULATE HX HY HZ */ -/* ----------------------------------------------------------------------- */ -/* ----------------------------------------------------------------------- */ -/* PASSED PARAMETERS */ -/* ----------------------------------------------------------------------- */ -/* INIT AND TEST */ - - /* Parameter adjustments */ - --c_ih__; - --t_ih__; - - /* Function Body */ - *ier = 1; - if (dabs(*qm) < 1e-4f) { - goto L999; - } - *ier = 0; - for (ic = 1; ic <= 4; ++ic) { - if (c_ih__[ic] < 1e-4f) { - *ier = 2; - } - } - if (*ier != 0) { - goto L999; - } -/* ----------------------------------------------------------------------- */ -/* CALCULATE MODULE AND ANGLES OF IN PLANE FIELD H */ -/* PHI !ANGLE BETWEEN Q AND KI */ -/* HRAD !RADIAL COMP. OF H */ -/* HDIR !DIRECTION OF H (IN RADIANS) */ -/* HDIR2 !ANGLE BETWEEN FIELD AND AXE OF COIL 1 */ - - qpar = *aki - *akf * cos(*a4 / 57.29577951308232087679815481410517f); - qperp = *akf * sin(*a4 / 57.29577951308232087679815481410517f); - phi = atan2(qpar, qperp); -/* Computing 2nd power */ - r__1 = *hx; -/* Computing 2nd power */ - r__2 = *hy; - hrad = sqrt(r__1 * r__1 + r__2 * r__2); - if (hrad > 1e-4f) { - hdir = atan2(*hy, *hx); - } - hdir2 = phi + hdir + *helm / 57.29577951308232087679815481410517f + - 1.5707963267948966f; -/* ----------------------------------------------------------------------- */ -/* !CALC CURRENTS */ -/* !POSITION OF PSP FOR COIL I */ - - for (ic = 1; ic <= 3; ++ic) { - t_ih__[ic + 4] = cos(hdir2 + (ic - 1) * 2.f * - 3.1415926535897932384626433832795f / 3.f) * hrad / - c_ih__[ic] - / 1.5f; - } - t_ih__[8] = *hz / c_ih__[4]; -/* ----------------------------------------------------------------------- */ -L999: - return 0; -} /* helm_case__ */ - -/* Subroutine */ int flip_case__(integer * if1, integer * if2, - real * t_ih__, - real * f1v, real * f1h, real * f2v, - real * f2h, real * aki, real * akf, - integer * ier) -{ -/* ----------------------------------------------------------------------- */ -/* DEAL WITH FLIPPER COIL CALCULATIONS */ -/* CALCULATE P_IF CURRENTS FOR THE TWO FLIPPERS */ -/* ----------------------------------------------------------------------- */ -/* PASSED PARAMETERS */ -/* ----------------------------------------------------------------------- */ -/* INIT AND TEST */ - - /* Parameter adjustments */ - --t_ih__; - - /* Function Body */ - *ier = 0; -/* ----------------------------------------------------------------------- */ - - if (*if1 == 1) { - t_ih__[1] = *f1v; - t_ih__[2] = *aki * *f1h; - } else { - t_ih__[1] = 0.f; - t_ih__[2] = 0.f; - } - if (*if2 == 1) { - t_ih__[3] = *f2v; - t_ih__[4] = *akf * *f2h; - } else { - t_ih__[3] = 0.f; - t_ih__[4] = 0.f; - } -/* ----------------------------------------------------------------------- */ -/* L999: */ - return 0; -} /* flip_case__ */ diff --git a/tasdrive.c b/tasdrive.c index 76737ca9..044a419b 100644 --- a/tasdrive.c +++ b/tasdrive.c @@ -227,7 +227,16 @@ static int TASHalt(void *pData) if (self->math->tasMode == ELASTIC) { length = 8; } - for (i = 0; i < length; i++) { + + /* + stop monochromator + */ + self->math->mono->Halt(self->math->monoData); + + /* + stop rest + */ + for (i = 4; i < length; i++) { if (self->math->motors[i] != NULL) { pDriv = GetDrivableInterface(self->math->motors[i]); pDriv->Halt(self->math->motors[i]); @@ -295,8 +304,8 @@ static int startTASMotor(pMotor mot, SConnection * pCon, char *name, to force updates on targets */ InvokeNewTarget(pServ->pExecutor, name, target); + writeMotPos(pCon, silent, name, val, target); } - writeMotPos(pCon, silent, name, val, target); return status; } @@ -313,39 +322,43 @@ static int startMotors(ptasMot self, tasAngles angles, /* monochromator */ - status = startTASMotor(self->math->motors[A1], pCon, "a1", - angles.monochromator_two_theta / 2., silent, stopFixed); - if (status != OKOK) { + /* status = startTASMotor(self->math->motors[A1], pCon, "a1", */ + /* angles.monochromator_two_theta / 2., silent, stopFixed); */ + /* if (status != OKOK) { */ + /* return status; */ + /* } */ + /* status = startTASMotor(self->math->motors[A2], pCon, "a2", */ + /* angles.monochromator_two_theta, silent,stopFixed); */ + /* if (status != OKOK) { */ + /* return status; */ + /* } */ + + /* if (self->math->motors[MCV] != NULL) { */ + /* curve = maCalcVerticalCurvature(self->math->machine.monochromator, */ + /* angles.monochromator_two_theta); */ + /* status = startTASMotor(self->math->motors[MCV], pCon, "mcv", */ + /* curve, silent,stopFixed); */ + /* if (status != OKOK) { */ + /* SCWrite(pCon,"WARNING: monochromator vertical curvature motor failed to start", eLog); */ + /* SCSetInterrupt(pCon,eContinue); */ + /* } */ + /* } */ + + /* if (self->math->motors[MCH] != NULL) { */ + /* curve = maCalcHorizontalCurvature(self->math->machine.monochromator, */ + /* angles.monochromator_two_theta); */ + /* status = startTASMotor(self->math->motors[MCH], pCon, "mch", */ + /* curve, silent,stopFixed); */ + /* if (status != OKOK) { */ + /* SCWrite(pCon,"WARNING: monochromator horizontal curvature motor failed to start", eLog); */ + /* SCSetInterrupt(pCon,eContinue); */ + /* } */ + /* } */ + status = self->math->mono->SetValue(self->math->monoData, + pCon,angles.monochromator_two_theta); + if(status != OKOK){ return status; } - status = startTASMotor(self->math->motors[A2], pCon, "a2", - angles.monochromator_two_theta, silent,stopFixed); - if (status != OKOK) { - return status; - } - - if (self->math->motors[MCV] != NULL) { - curve = maCalcVerticalCurvature(self->math->machine.monochromator, - angles.monochromator_two_theta); - status = startTASMotor(self->math->motors[MCV], pCon, "mcv", - curve, silent,stopFixed); - if (status != OKOK) { - SCWrite(pCon,"WARNING: monochromator vertical curvature motor failed to start", eLog); - SCSetInterrupt(pCon,eContinue); - } - } - - if (self->math->motors[MCH] != NULL) { - curve = maCalcHorizontalCurvature(self->math->machine.monochromator, - angles.monochromator_two_theta); - status = startTASMotor(self->math->motors[MCH], pCon, "mch", - curve, silent,stopFixed); - if (status != OKOK) { - SCWrite(pCon,"WARNING: monochromator horizontal curvature motor failed to start", eLog); - SCSetInterrupt(pCon,eContinue); - } - } - /* analyzer @@ -491,24 +504,24 @@ static int calculateAndDrive(ptasMot self, SConnection * pCon) switch (status) { case ENERGYTOBIG: - SCWrite(pCon, "ERROR: desired energy to big", eError); + SCWrite(pCon, "ERROR: desired energy to big", eLogError); return HWFault; break; case UBNOMEMORY: - SCWrite(pCon, "ERROR: out of memory calculating angles", eError); + SCWrite(pCon, "ERROR: out of memory calculating angles", eLogError); driveQ = 0; break; case BADRMATRIX: SCWrite(pCon, "ERROR: bad crystallographic parameters or bad UB", - eError); + eLogError); driveQ = 0; break; case BADUBORQ: - SCWrite(pCon, "ERROR: bad UB matrix or bad Q-vector", eError); + SCWrite(pCon, "ERROR: bad UB matrix or bad Q-vector", eLogError); driveQ = 0; break; case TRIANGLENOTCLOSED: - SCWrite(pCon, "ERROR: cannot close scattering triangle", eError); + SCWrite(pCon, "ERROR: cannot close scattering triangle", eLogError); driveQ = 0; break; } @@ -546,7 +559,7 @@ static int calculateAndDrive(ptasMot self, SConnection * pCon) if (driveQ == 0 && self->math->mustDriveQ == 1) { SCWrite(pCon, "WARNING: NOT driving Q-vector because of errors", - eError); + eLogError); } /* * reset the Q flag @@ -577,7 +590,20 @@ static int checkMotors(ptasMot self, SConnection * pCon) mask[SGL] = 0; } - for (i = 0; i < 12; i++) { + /* + check monochromator + */ + status = self->math->mono->CheckStatus(self->math->monoData,pCon); + if(status == HWIdle){ + for(i = 0; i < 4; i++){ + busy[i] = 0; + } + } + + /* + check the rest + */ + for (i = 4; i < 12; i++) { if(self->math->motors[i] == NULL){ busy[i] = 0; } else { @@ -635,35 +661,39 @@ static int startQMMotors(ptasMot self, tasAngles angles, /* monochromator */ - status = startTASMotor(self->math->motors[A1], pCon, "a1", - angles.monochromator_two_theta / 2., silent,stopFixed); - if (status != OKOK) { - return status; - } - status = startTASMotor(self->math->motors[A2], pCon, "a2", - angles.monochromator_two_theta, silent,stopFixed); - if (status != OKOK) { - return status; - } + /* status = startTASMotor(self->math->motors[A1], pCon, "a1", */ + /* angles.monochromator_two_theta / 2., silent,stopFixed); */ + /* if (status != OKOK) { */ + /* return status; */ + /* } */ + /* status = startTASMotor(self->math->motors[A2], pCon, "a2", */ + /* angles.monochromator_two_theta, silent,stopFixed); */ + /* if (status != OKOK) { */ + /* return status; */ + /* } */ - if (self->math->motors[MCV] != NULL) { - curve = maCalcVerticalCurvature(self->math->machine.monochromator, - angles.monochromator_two_theta); - status = startTASMotor(self->math->motors[MCV], pCon, "mcv", - curve, silent,stopFixed); - if (status != OKOK) { - return status; - } - } + /* if (self->math->motors[MCV] != NULL) { */ + /* curve = maCalcVerticalCurvature(self->math->machine.monochromator, */ + /* angles.monochromator_two_theta); */ + /* status = startTASMotor(self->math->motors[MCV], pCon, "mcv", */ + /* curve, silent,stopFixed); */ + /* if (status != OKOK) { */ + /* return status; */ + /* } */ + /* } */ - if (self->math->motors[MCH] != NULL) { - curve = maCalcHorizontalCurvature(self->math->machine.monochromator, - angles.monochromator_two_theta); - status = startTASMotor(self->math->motors[MCH], pCon, "mch", - curve, silent,stopFixed); - if (status != OKOK) { - return status; - } + /* if (self->math->motors[MCH] != NULL) { */ + /* curve = maCalcHorizontalCurvature(self->math->machine.monochromator, */ + /* angles.monochromator_two_theta); */ + /* status = startTASMotor(self->math->motors[MCH], pCon, "mch", */ + /* curve, silent,stopFixed); */ + /* if (status != OKOK) { */ + /* return status; */ + /* } */ + /* } */ + status = self->math->mono->SetValue(self->math->monoData,pCon,angles.analyzer_two_theta); + if(status != OKOK){ + return status; } diff --git a/task.c b/task.c index 1bacf1df..aa7e5524 100644 --- a/task.c +++ b/task.c @@ -68,7 +68,8 @@ static pTaskHead MakeTaskHead(char *name, TaskFunc pTask, SignalFunc pSignal, pNew->pSignal = pSignal; pNew->pData = pData; pNew->pKill = pKill; - pNew->lID = lIDMama++; + lIDMama++; + pNew->lID = lIDMama; pNew->iStatus = READY; if(lIDMama < 0){ @@ -455,6 +456,25 @@ int isTaskRunning(pTaskMan self, char *name) return 0; } /*-----------------------------------------------------------------------------*/ +int isTaskIDRunning(pTaskMan self, long lID) +{ + int iRet; + pTaskHead pCurrent, pNext; + + if (self == NULL) return 0; + assert(self->iID == TASKERID); + + pNext = self->pHead->pNext; /* skip dummy task */ + while (pNext != NULL) { + pCurrent = pNext; + pNext = pCurrent->pNext; + if (pCurrent->lID == lID) { + return 1; + } + } + return 0; +} +/*-----------------------------------------------------------------------------*/ pTaskHead TaskIteratorStart(pTaskMan self) { if (self == NULL) return NULL; @@ -502,6 +522,21 @@ char *TaskDescription(pTaskHead it) } /*------------------------------------------------------------------------------*/ +long GetTaskID(pTaskHead it) +{ + return it->lID; +} +/*------------------------------------------------------------------------------*/ +long GetGroupID(pTaskHead it) +{ + return it-> groupID; +} +/*------------------------------------------------------------------------------*/ +const char * GetTaskName(pTaskHead it) +{ + return (const char*)it->name; +} +/*------------------------------------------------------------------------------*/ long GetTaskGroupID(pTaskMan self) { lIDMama++; diff --git a/task.h b/task.h index ffc84a79..4cd0c729 100644 --- a/task.h +++ b/task.h @@ -6,7 +6,10 @@ a yield and a primitive form of inter task communication is implemented. Mark Koennecke, September 1997 - + + extended to suuport task groups + Mark Koennecke, December 2012 + copyright: see implementation file -----------------------------------------------------------------------------*/ #ifndef TASKOMAT @@ -144,6 +147,11 @@ int TaskSignal(pTaskMan self, int iSignal, void *pSigData); /* returns 1 when task name is running, 0 else */ +/*--------------------------------------------------------------------------*/ + int isTaskIDRunning(pTaskMan self, long lID); +/* + returns 1 when task name is running, 0 else +*/ /*=========================================================================== Iterating the task list. This works like: @@ -177,6 +185,19 @@ char *TaskDescription(pTaskHead it); get a description of the task at the current iterator You are responsible for deleting the returned character array. */ +long GetTaskID(pTaskHead it); +/* + get the ID of the current task +*/ +long GetGroupID(pTaskHead it); +/* + get the group ID of the current task +*/ +const char *GetTaskName(pTaskHead it); +/* + get the name of the current task. Do not delete the returned pointer. +*/ + /*============================================================================= Task Groups. The implementation has the limit that any given task can only be member of one task group diff --git a/taskobj.c b/taskobj.c index ee176043..28bdd58f 100644 --- a/taskobj.c +++ b/taskobj.c @@ -61,6 +61,10 @@ static int KillCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, return 0; } + if(!SCMatchRights(pCon,usMugger)){ + return 0; + } + status = StopTask(pServ->pTasker,par[0]->value.v.text); if(status == 0) { SCWrite(pCon,"ERROR: cannot commit suicide!", eError); @@ -183,3 +187,37 @@ int TaskOBJFactory(SConnection *pCon, SicsInterp *pSics, void *pData, return 1; } +/*-------------------------------------------------------------------*/ +void InitTaskOBJ() +{ + pSICSOBJ pNew = NULL; + pHdb cmd = NULL, node; + + + pNew = MakeSICSOBJv("task", "TaskOBJ", HIPNONE, usInternal); + if (pNew == NULL) { + SCWrite(pServ->dummyCon, "ERROR: out of memory creating new SICS object", eError); + return; + } + + cmd = AddSICSHdbPar(pNew->objectNode, "ps", usSpy, + MakeSICSFunc(ListCmd)); + + cmd = AddSICSHdbPar(pNew->objectNode, "kill", usSpy, + MakeSICSFunc(KillCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","spy"); + node = MakeSICSHdbPar("task",usSpy,MakeHdbText("banana")); + AddHipadabaChild(cmd,node,NULL); + + cmd = AddSICSHdbPar(pNew->objectNode, "run", usSpy, + MakeSICSFunc(RunCmd)); + SetHdbProperty(cmd,"type","command"); + SetHdbProperty(cmd,"priv","spy"); + node = MakeSICSHdbPar("script",usSpy,MakeHdbText("banana")); + AddHipadabaChild(cmd,node,NULL); + + AddCommand(pServ->pSics, + "task", InterInvokeSICSOBJ, KillSICSOBJ, pNew); + +} diff --git a/tasmono.c b/tasmono.c new file mode 100644 index 00000000..f538d989 --- /dev/null +++ b/tasmono.c @@ -0,0 +1,234 @@ +/** + * Triple axis monochromator module + * EIGER made it necessary to abstract out the monochromator. This is + * the default implementation for a sane, normal TAS. This implements a + * drivable interface. It gets an A2 value from the tasub module and is + * supposed to drive and monitor all the dependent monochromator motors. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, February 2013 + */ +#include +#include "tasmono.h" +#include "tasub.h" + +#define MOTPREC .01 +#define A1 0 +#define A2 1 +#define MCV 2 +#define MCH 3 +#define NOTSTARTED -100 + + +#define ABS(x) (x < 0 ? -(x) : (x)) + +/*---------------------------------------------------------------- + This routine can return either OKOK or HWFault when thing + go wrong. However, the return value of Halt is usually ignored! +------------------------------------------------------------------*/ +static int TAMOHalt(void *data) { + ptasUB self = NULL; + pIDrivable pDriv; + int i; + + self = (ptasUB)data; + for(i = 0; i < 4; i++){ + if (self->motors[i] != NULL) { + pDriv = GetDrivableInterface(self->motors[i]); + pDriv->Halt(self->motors[i]); + } + } + return OKOK; +} +/*---------------------------------------------------------------- + This routine can return either 1 or 0. 1 means the position can + be reached, 0 NOT + If 0, error shall contain up to errlen characters of information + about which limit was violated +------------------------------------------------------------------*/ +static int TAMOCheckLimits(void *data, float val, + char *error, int errlen){ + ptasUB self = NULL; + + self = (ptasUB)data; + + /* + Not meaningful in this context + */ + return 1; +} +/*---------------------------------------------------------------- + This routine can return 0 when a limit problem occurred + OKOK when the motor was successfully started + HWFault when a problem occured starting the device + Possible errors shall be printed to pCon + For real motors, this is supposed to try at least three times + to start the motor in question + val is the value to drive the motor too +------------------------------------------------------------------*/ +static void writeMotPos(SConnection * pCon, int silent, char *name, + float val, float target) +{ + char pBueffel[132]; + + if (silent != 1) { + snprintf(pBueffel, 131, "Driving %5s from %8.3f to %8.3f", + name, val, target); + SCWrite(pCon, pBueffel, eLog); + } +} +/*--------------------------------------------------------------------------*/ +static long startTASMotor(pMotor mot, SConnection * pCon, char *name, + double target, int silent, int stopFixed) +{ + float val, fixed, precision = MOTPREC; + long status = NOTSTARTED; + char buffer[132]; + pIDrivable pDriv = NULL; + pDummy dum = NULL; + pDynString mes = NULL; + + + dum = (pDummy)mot; + GetDrivablePosition(mot, pCon,&val); + if(strcmp(dum->pDescriptor->name,"Motor") == 0){ + MotorGetPar(mot,"precision",&precision); + MotorGetPar(mot, "fixed", &fixed); + if (ABS(fixed - 1.0) < .1) { + if(stopFixed == 0){ + snprintf(buffer, 131, "WARNING: %s is FIXED", name); + SCWrite(pCon, buffer, eLog); + } + return NOTSTARTED; + } + } + mot->stopped = 0; + if (ABS(val - target) > precision) { + status = StartDriveTask(mot, pCon, name, (float)target); + if(status < 0){ + SCPrintf(pCon,eLog,"ERROR: failed to drive %s to %f", name, target); + } + /* + to force updates on targets + */ + InvokeNewTarget(pServ->pExecutor, name, target); + writeMotPos(pCon, silent, name, val, target); + return status; + } else { + return NOTSTARTED; + } +} +/*-------------------------------------------------------------------------*/ +static long TAMOSetValue(void *data, SConnection *pCon, float val){ + ptasUB self = NULL; + self = (ptasUB)data; + int stopFixed = 0; + double curve; + int status; + + self->monoTaskID = GetTaskGroupID(pServ->pTasker); + + status = startTASMotor(self->motors[A1], pCon, "a1", + val / 2., self->silent, stopFixed); + if (status < 0 && status != NOTSTARTED) { + return HWFault; + } + if(status != NOTSTARTED){ + AddTaskToGroup(pServ->pTasker,status, self->monoTaskID); + } + + status = startTASMotor(self->motors[A2], pCon, "a2", + val, self->silent,stopFixed); + if (status < 0 && status != NOTSTARTED) { + return HWFault; + } + if(status != NOTSTARTED){ + AddTaskToGroup(pServ->pTasker,status, self->monoTaskID); + } + + + if (self->motors[MCV] != NULL) { + curve = maCalcVerticalCurvature(self->machine.monochromator, + val); + status = startTASMotor(self->motors[MCV], pCon, "mcv", + curve, self->silent,stopFixed); + if (status < 0 && status != NOTSTARTED) { + SCWrite(pCon,"WARNING: monochromator vertical curvature motor failed to start", eLog); + SCSetInterrupt(pCon,eContinue); + } else { + AddTaskToGroup(pServ->pTasker,status, self->monoTaskID); + } + } + + if (self->motors[MCH] != NULL) { + curve = maCalcHorizontalCurvature(self->machine.monochromator, + val); + status = startTASMotor(self->motors[MCH], pCon, "mch", + curve, self->silent,stopFixed); + if (status < 0 && status != NOTSTARTED) { + SCWrite(pCon,"WARNING: monochromator horizontal curvature motor failed to start", eLog); + SCSetInterrupt(pCon,eContinue); + }else { + AddTaskToGroup(pServ->pTasker,status,self->monoTaskID); + } + } + return OKOK; +} +/*---------------------------------------------------------------- + Checks the status of a running motor. Possible return values + HWBusy The motor is still running + OKOK or HWIdle when the motor finished driving + HWFault when a hardware problem ocurred + HWPosFault when the hardware cannot reach a position + Errors are duly to be printed to pCon + For real motors CheckStatus again shall try hard to fix any + issues with the motor +------------------------------------------------------------------*/ +static int TAMOCheckStatus(void *data, SConnection *pCon){ + ptasUB self = NULL; + + self = (ptasUB)data; + if(isTaskGroupRunning(pServ->pTasker,self->monoTaskID)) { + return HWBusy; + } else { + return HWIdle; + } + return 1; +} +/*---------------------------------------------------------------- + GetValue is supposed to read a motor position + On errors, -99999999.99 is returned and messages printed to pCon +------------------------------------------------------------------*/ +static float TAMOGetValue(void *data, SConnection *pCon){ + ptasUB self = NULL; + float val = -99999999.99; + + int status; + + self = (ptasUB)data; + status = GetDrivablePosition(self->motors[A2], pCon, &val); + if (status == 0) { + return -99999999.99; + } + return val; +} +/*---------------------------------------------------------------- + returns NULL on failure, a new datastructure else +------------------------------------------------------------------*/ +pIDrivable MakeTasMono(){ + pIDrivable pDriv; + + pDriv = calloc(1,sizeof(IDrivable)); + if(pDriv == NULL){ + return NULL; + } + pDriv->Halt = TAMOHalt; + pDriv->CheckLimits = TAMOCheckLimits; + pDriv->SetValue = TAMOSetValue; + pDriv->CheckStatus = TAMOCheckStatus; + pDriv->GetValue = TAMOGetValue; + + return pDriv; +} + diff --git a/tasmono.h b/tasmono.h new file mode 100644 index 00000000..b3a40e5b --- /dev/null +++ b/tasmono.h @@ -0,0 +1,19 @@ +/** + * Triple axis monochromator module + * EIGER made it necessary to abstract out the monochromator. This is + * the default implementation for a sane, normal TAS. This implements a + * drivable interface. It gets an A2 value from the tasub module and is + * supposed to drive and monitor all the dependent monochromator motors. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, February 2013 + */ + +#ifndef __TASMONO +#define __TASMONO + +pIDrivable MakeTasMono(); + +#endif + diff --git a/tasub.c b/tasub.c index 0d046f83..32afb64d 100644 --- a/tasub.c +++ b/tasub.c @@ -22,6 +22,7 @@ #include "tasub.h" #include "tasdrive.h" #include "vector.h" +#include "tasmono.h" /*------------------- motor indexes in motor data structure ---------*/ #define A1 0 #define A2 1 @@ -173,6 +174,8 @@ static ptasUB MakeTasUB() pNew->actualEn = .0; pNew->outOfPlaneAllowed = 1; pNew->mustRecalculate = 1; + pNew->mono = MakeTasMono(); + pNew->monoData = pNew; return pNew; } @@ -198,6 +201,9 @@ static void KillTasUB(void *pData) if(self->updater != NULL){ free(self->updater); } + if(self->mono != NULL){ + free(self->mono); + } free(self); } diff --git a/tasub.h b/tasub.h index a60af51f..3c5eab5b 100644 --- a/tasub.h +++ b/tasub.h @@ -30,6 +30,9 @@ int mustDriveQ; pMotor motors[12]; tasReflection r1, r2; + pIDrivable mono; + long monoTaskID; + void *monoData; int ubValid; int silent; int stopFixed; /* flag to stop multiple fixed messages in scans*/ diff --git a/trace.c b/trace.c index ce135f03..e2a33a9b 100644 --- a/trace.c +++ b/trace.c @@ -199,12 +199,20 @@ static int strrepc(char *pszStr, char cFrom, char cTo) /*-----------------------------------------------------------------*/ void traceprint(char *sub, char *id, char *data) { - if(log != NULL && filter(sub,id)){ - strrepc(data,'\n',':'); - strrepc(sub,':','@'); - strrepc(id,':','@'); - fprintf(log,"%s:%s:%lf:%s\n",sub,id,DoubleTime(),data); - } + char *mysub, *myid, *mydata; + + if(log != NULL && filter(sub,id)){ + mysub = strdup(sub); + myid = strdup(id); + mydata = strdup(data); + strrepc(mydata,'\n',':'); + strrepc(mysub,':','@'); + strrepc(myid,':','@'); + fprintf(log,"%s:%s:%lf:%s\n",mysub,myid,DoubleTime(),mydata); + free(mysub); + free(myid); + free(mydata); + } } /*-----------------------------------------------------------------*/ void traceIO(char *id, char *format, ...) diff --git a/ubcalc.c b/ubcalc.c index 41c64eac..58d6ca0e 100644 --- a/ubcalc.c +++ b/ubcalc.c @@ -10,6 +10,10 @@ Heavily reworked to fit into the new four circle system Mark Koennecke, July 2008 + + Added UBfromCell + + Mark Koennecke, March 2013 -----------------------------------------------------------------------*/ #include #include @@ -252,7 +256,39 @@ static int calcUB(pUBCALC self, SConnection * pCon, char *ref1, char *ref2) return 1; } } +/*---------------------------------------------------------------------*/ +static int UBFromCell(pUBCALC self, SConnection *pCon) +{ + const double *cell; + lattice mycell; + MATRIX B; + double ub[9]; + int i; + cell = SXGetCell(); + mycell.a = cell[0]; + mycell.b = cell[1]; + mycell.c = cell[2]; + mycell.alpha = cell[3]; + mycell.beta = cell[4]; + mycell.gamma = cell[5]; + + B = mat_creat(3,3,ZERO_MATRIX); + if(B == NULL){ + SCWrite(pCon,"ERROR: out of memory in UBfromCell",eError); + return 0; + } + + calculateBMatrix(mycell,B); + + if(self->UB != NULL){ + mat_free(self->UB); + } + self->UB = B; + + SCSendOK(pCon); + return 1; +} /*---------------------------------------------------------------------*/ static int sendUBToHKL(SConnection * pCon, SicsInterp * pSics, pHKL hkl, MATRIX UB) @@ -551,6 +587,8 @@ int UBCalcWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, return sendUBToHKL(pCon, pSics, self->hkl, self->UB); } else if (strcmp(argv[1], "index") == 0) { return findIndex(self, pCon, pSics, argc, argv); + } else if (strcmp(argv[1], "fromcell") == 0) { + return UBFromCell(self, pCon); } else { if (argc > 2) { return setUBCalcParameters(self, pCon, argv[1], argv[2]); diff --git a/ubfour.h b/ubfour.h index b87b4558..6a599058 100644 --- a/ubfour.h +++ b/ubfour.h @@ -117,7 +117,7 @@ double angleBetweenReflections(MATRIX B, reflection r1, reflection r2); /** * calculate the length of the scattering vector belonging to r * @param B The B metric matrix to use - * @param r The reflction for which to calculate + * @param r The reflection for which to calculate * @return The length of the scattering vector */ double scatteringVectorLength(MATRIX B, reflection r); diff --git a/velo.c b/velo.c index 94dafb16..35db8584 100644 --- a/velo.c +++ b/velo.c @@ -802,7 +802,7 @@ int VelSelFactory(SConnection * pCon, SicsInterp * pSics, void *pData, } pT = InterpGetTcl(pSics); site = getSite(); - if (site != NULL) { + if (site != NULL && site->CreateVelocitySelector != NULL) { pDriv = site->CreateVelocitySelector(argv[3], argv[4], pT); } if (!pDriv) {