From ad241bd99ebc2b83d4bfa667e00fea64726f4fea Mon Sep 17 00:00:00 2001 From: koennecke Date: Mon, 4 Nov 2013 12:55:15 +0000 Subject: [PATCH] - Added a protocol driver for the munich sputter machine - Added a multicountsersec to teplace hmcontrol and multicounter - Fixed a case sensitivity bug in haddcheck - Made oscillate work with second generation motors for POLDI - Added a time stamper to trace. Now there will be time stamps in trace files which allow to correlate things from the master log with the trace. - Updated polterwrite. - Updated testprot to work with the behave test SKIPPED: psi/make_gen psi/polterwrite.c psi/psi.c psi/sputterprot.c --- conman.c | 49 +++++ conman.h | 1 + countersec.c | 169 ++++++++------- danu.c | 16 +- interface.c | 2 + make_gen | 2 +- multicountersec.c | 520 ++++++++++++++++++++++++++++++++++++++++++++++ ofac.c | 1 + oscillate.c | 35 ++-- sicshipadaba.c | 12 +- sicshipadaba.h | 8 + tasdrive.c | 59 +++--- test/testini.tcl | 12 +- testprot.c | 7 +- trace.c | 126 ++++++----- 15 files changed, 829 insertions(+), 190 deletions(-) create mode 100644 multicountersec.c diff --git a/conman.c b/conman.c index 9b6f4c53..198f2e75 100644 --- a/conman.c +++ b/conman.c @@ -1543,6 +1543,55 @@ int SCPrompt(SConnection * pCon, char *pPrompt, char *pResult, int iLen) CostaLock(master->pStack); return 0; } +/*----------------------------------------------------------------------------*/ +int SCPromptTMO(SConnection * pCon, char *pPrompt, char *pResult, int iLen, int timeout) +{ + + int iRet, i; + char *pPtr = NULL; + char pFrom[50]; + Status eOld; + int oldMode; + SConnection *master = NULL; + + if (!VerifyConnection(pCon)) { + return 0; + } + + SCWrite(pCon, pPrompt, eWarning); + master = SCfindMaster(pCon); + eOld = GetStatus(); + SetStatus(eInput); + CostaUnlock(master->pStack); + for(i = 0; i < timeout; i++) { + /* + wait a second. We want to wait even in a simulation, otherwise + we go into an endless loop. This is why there is the hack with + oldMode and pServ->simMode. + */ + oldMode = pServ->simMode; + pServ->simMode = 0; + SicsWait(1); + pServ->simMode = oldMode; + + /* is there an interrupt pending ? */ + if (SCGetInterrupt(pCon) != eContinue) { + break; + } + /* do we have data ? */ + iRet = CostaPop(master->pStack, &pPtr); + if (iRet == 1) { + SetStatus(eOld); + CostaLock(master->pStack); + strlcpy(pResult, pPtr, iLen); + WriteToCommandLogId(" prompted>", pCon->sockHandle, pPtr); + return 1; + } + } + SetStatus(eOld); + CostaLock(master->pStack); + return 0; +} /*---------------------------------------------------------------------------*/ int SCGetRights(SConnection * self) diff --git a/conman.h b/conman.h index 31e29d55..91befe22 100644 --- a/conman.h +++ b/conman.h @@ -95,6 +95,7 @@ int SCWrite(SConnection * self, char *pBuffer, int iOut); int SCPrintf(SConnection * self, int iOut, char *fmt, ...); int SCRead(SConnection * self, char *pBuffer, int iBufLen); int SCPrompt(SConnection * pCon, char *pPrompt, char *pResult, int iLen); +int SCPromptTMO(SConnection * pCon, char *pPrompt, char *pResult, int iLen, int timeout); int SCSendOK(SConnection * self); int SCnoSock(SConnection * pCon); int SCWriteUUencoded(SConnection * pCon, char *pName, void *iData, diff --git a/countersec.c b/countersec.c index 103d06b6..caff70d1 100644 --- a/countersec.c +++ b/countersec.c @@ -121,96 +121,96 @@ static int SecContinue(void *pData, SConnection *pCon) /*----------------------------------------------------------------------------*/ static int SecCtrCheckStatus(void *pData, SConnection *pCon) { - pCounter self = (pCounter)pData; - pHdb node = NULL, control = NULL; - hdbValue v; - int status; - MonEvent sMon; - float fControl, fPreset; - char error[132]; + pCounter self = (pCounter)pData; + pHdb node = NULL, control = NULL; + hdbValue v; + int status; + MonEvent sMon; + float fControl, fPreset; + char error[132]; - assert(self != NULL); + assert(self != NULL); - node = GetHipadabaNode(self->pDes->parNode,"status"); - assert(node != NULL); - status = GetHipadabaPar(node,&v,pCon); + node = GetHipadabaNode(self->pDes->parNode,"status"); + assert(node != NULL); + status = GetHipadabaPar(node,&v,pCon); - if(status != 1){ - ReleaseCountLock(self->pCountInt); - return HWFault; - } + if(status != 1){ + ReleaseCountLock(self->pCountInt); + return HWFault; + } - if(v.v.text == NULL){ - return HWBusy; - } - if (strstr(v.v.text, "idle") != NULL) { - InvokeCallBack(self->pCall, COUNTEND, NULL); - ReleaseCountLock(self->pCountInt); - status = HWIdle; - } else if (strstr(v.v.text, "run") != NULL) { - status = HWBusy; - } else if (strstr(v.v.text, "nobeam") != NULL) { - status = HWNoBeam; - } else if (strstr(v.v.text, "pause") != NULL) { - status = HWPause; - } else if (strstr(v.v.text, "restart") != NULL) { - SecStartCount(self, pCon); - return HWBusy; - } else if (strstr(v.v.text, "error") != NULL) { - InvokeCallBack(self->pCall, COUNTEND, NULL); - ReleaseCountLock(self->pCountInt); - if(GetHdbProperty(node,"geterror",error,sizeof(error)) == 1){ - SCPrintf(pCon,eError,"ERROR: %s", error); - SecCounterSetError(self,error); - } else { - SecCounterSetError(self,"Undefined counter error: set status geterror"); - SCPrintf(pCon,eError,"ERROR: Unknown counter status error: set status geterror property"); - } - status = HWFault; - } else { - SCPrintf(pCon, eError, "ERROR: unknown counter status %s found", - v.v.text); - ReleaseCountLock(self->pCountInt); - status = HWFault; - } - ReleaseHdbValue(&v); + if(v.v.text == NULL){ + return HWBusy; + } + if (strstr(v.v.text, "idle") != NULL) { + InvokeCallBack(self->pCall, COUNTEND, NULL); + ReleaseCountLock(self->pCountInt); + status = HWIdle; + } else if (strstr(v.v.text, "run") != NULL) { + status = HWBusy; + } else if (strstr(v.v.text, "nobeam") != NULL) { + status = HWNoBeam; + } else if (strstr(v.v.text, "pause") != NULL) { + status = HWPause; + } else if (strstr(v.v.text, "restart") != NULL) { + SecStartCount(self, pCon); + return HWBusy; + } else if (strstr(v.v.text, "error") != NULL) { + InvokeCallBack(self->pCall, COUNTEND, NULL); + ReleaseCountLock(self->pCountInt); + if(GetHdbProperty(node,"geterror",error,sizeof(error)) == 1){ + SCPrintf(pCon,eError,"ERROR: %s", error); + SecCounterSetError(self,error); + } else { + SecCounterSetError(self,"Undefined counter error: set status geterror"); + SCPrintf(pCon,eError,"ERROR: Unknown counter status error: set status geterror property"); + } + status = HWFault; + } else { + SCPrintf(pCon, eError, "ERROR: unknown counter status %s found", + v.v.text); + ReleaseCountLock(self->pCountInt); + status = HWFault; + } + ReleaseHdbValue(&v); - node = GetHipadabaNode(self->pDes->parNode,"control"); - assert(node != NULL); - GetHipadabaPar(node,&v,pCon); - fControl = v.v.doubleValue; - node = GetHipadabaNode(self->pDes->parNode,"preset"); - assert(node != NULL); - GetHipadabaPar(node,&v,pCon); - fPreset = v.v.doubleValue; + node = GetHipadabaNode(self->pDes->parNode,"control"); + assert(node != NULL); + GetHipadabaPar(node,&v,pCon); + fControl = v.v.doubleValue; + node = GetHipadabaNode(self->pDes->parNode,"preset"); + assert(node != NULL); + GetHipadabaPar(node,&v,pCon); + fPreset = v.v.doubleValue; - sMon.fCurrent = fControl; - sMon.fPreset = fPreset; - sMon.pName = self->name; - self->badStatusCount = 0; + sMon.fCurrent = fControl; + sMon.fPreset = fPreset; + sMon.pName = self->name; + self->badStatusCount = 0; - /* - * check for overrun counter boxes - */ - if(self->getMode(self) == eTimer && - (sMon.fCurrent > sMon.fPreset +1) - && self->haltFixFlag == 0){ - SecCtrHalt(self); - self->haltFixFlag = 1; - } + /* + * check for overrun counter boxes + */ + if(self->getMode(self) == eTimer && + (sMon.fCurrent > sMon.fPreset +1) + && self->haltFixFlag == 0){ + SecCtrHalt(self); + self->haltFixFlag = 1; + } - /* - * invoke notifiactions, if necessary - */ - if (self->iCallbackCounter > 20) { - InvokeCallBack(self->pCall, MONITOR, &sMon); - self->iCallbackCounter = 0; - } else { - self->iCallbackCounter++; - } + /* + * invoke notifiactions, if necessary + */ + if (self->iCallbackCounter > 20) { + InvokeCallBack(self->pCall, MONITOR, &sMon); + self->iCallbackCounter = 0; + } else { + self->iCallbackCounter++; + } - return status; + return status; } /*--------------------------------------------------------------------------- * Here is an issue: this ought to wait until data has arrived. Callers @@ -221,6 +221,12 @@ static int SecCtrCheckStatus(void *pData, SConnection *pCon) * - add an update callback which deletes the property when done. * - Check that property or the geterror property here in a loop * until done or we timeout. + * + * Nope! Update October 2013: + * How it is normally done is to read the data through scripcontext when + * counting is finished and not to finish with counting until this has + * been done. The code below is only usefule for non scriptcontext + * drivers. * -----------------------------------------------------------------------*/ static int SecCtrTransferData(void *pData, SConnection *pCon) { @@ -551,6 +557,9 @@ pCounter CreateSecCounter(SConnection *pCon, char *type, char *name, int length) return NULL; } SetHdbProperty(child, "__save", "true"); + SetHdbProperty(child, "values", "timer,monitor"); + PrependHipadabaCallback(child,MakeHipadabaCallback(SICSValueCheckCallback, + NULL,NULL)); AddHipadabaChild(node, child, NULL); child = MakeSICSHdbPar("status", usInternal, MakeHdbText("idle")); diff --git a/danu.c b/danu.c index 8354ccd8..f19410e8 100644 --- a/danu.c +++ b/danu.c @@ -75,7 +75,7 @@ static int readDataNumber(pDataNumber self) } /*-----------------------------------------------------------------------*/ -static int writeDataNumber(pDataNumber self, int iNum) + static int writeDataNumber(pDataNumber self, int iNum) { FILE *fd = NULL; @@ -126,7 +126,18 @@ static int InterestCallback(int iEvent, void *pEvent, void *pUser) } return 1; } - +/*-------------------------------------------------------------------------*/ +static void *GetDanuInterface(void *data, int interfaceID) +{ + pDataNumber self = (pDataNumber)data; + if(self == NULL){ + return NULL; + } + if(interfaceID == CALLBACKINTERFACE){ + return self->pCall; + } + return NULL; +} /*-------------------------------------------------------------------------*/ pDataNumber CreateDataNumber(char *pFileName) { @@ -140,6 +151,7 @@ pDataNumber CreateDataNumber(char *pFileName) memset(pNew, 0, sizeof(DataNumber)); pNew->pDes = CreateDescriptor("DataNumber"); + pNew->pDes->GetInterface = GetDanuInterface; pNew->pCall = CreateCallBackInterface(); if (!pNew->pDes || !pNew->pCall) { free(pNew); diff --git a/interface.c b/interface.c index 9ed96442..c8b9bc4e 100644 --- a/interface.c +++ b/interface.c @@ -376,6 +376,8 @@ static int CountTaskFunc(void *data) return 1; } + taskData->pCount->TransferData(taskData->obj, taskData->pCon); + if(status == HWFault){ SetDevexecStatus(pServ->pExecutor,DEVERROR); } diff --git a/make_gen b/make_gen index ae8169cd..5b3f34df 100644 --- a/make_gen +++ b/make_gen @@ -44,7 +44,7 @@ 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 tasmono.o + singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o MOTOROBJ = motor.o simdriv.o COUNTEROBJ = countdriv.o simcter.o counter.o diff --git a/multicountersec.c b/multicountersec.c new file mode 100644 index 00000000..73fbb025 --- /dev/null +++ b/multicountersec.c @@ -0,0 +1,520 @@ +/** + * This is a second generation multicounter. It coordinates counting multiple + * HM/CCD with the counter box. It also allows to override transfer such that + * such a counter can be used in a scan. As with the ordinary multicounter. + * This one is supposed to become the standard multicounter replacing the old + * multicounter and the hmcontrol module. The other difference is that the task + * mechanism will be used to keep track of counters. + * + * copyright: see file COPYRIGHT + * + * Mark Koennecke, October 2013 + */ +#include +#include +#include +#include +#include +#include "sicshipadaba.h" +/*-------------------------------------------------------------------------*/ +static void SecCounterSetError(pCounter self, char *text) +{ + hdbValue v; + pHdb node; + + node = GetHipadabaNode(self->pDes->parNode, "error"); + if(node != NULL){ + v = MakeHdbText(strdup(text)); + UpdateHipadabaPar(node,v,NULL); + ReleaseHdbValue(&v); + } +} +/*---------------------------------------------------------------------------------*/ +static void doCountCommand(pHdb self, SConnection *pCon, int command) +{ + pHdb master = NULL, slaves = NULL; + char *pPtr, name[80]; + pICountable pCount = NULL; + void *data; + + master = GetHipadabaNode(self,"master"); + slaves = GetHipadabaNode(self,"slaves"); + assert(master != NULL); + assert(slaves != NULL); + + /* + treat master + */ + data = FindCommandData(pServ->pSics,master->value.v.text,NULL); + if(data != NULL){ + pCount = GetCountableInterface(data); + if(pCount != NULL){ + switch(command){ + case 1001: /* stop */ + pCount->Halt(data); + break; + case 1002: /*pause */ + pCount->Pause(data,pCon); + break; + case 1003: /* continue */ + pCount->Continue(data,pCon); + break; + case 1011: + break; + default: + assert(0); + } + } + } + + /* + treat slaves + */ + pPtr = slaves->value.v.text; + while((pPtr = stptok(pPtr,name,sizeof(name),",")) != NULL){ + data = FindCommandData(pServ->pSics,name,NULL); + if(data != NULL){ + pCount = GetCountableInterface(data); + if(pCount != NULL){ + switch(command){ + case 1001: /* stop */ + case 1011: + pCount->Halt(data); + break; + case 1002: /*pause */ + pCount->Pause(data,pCon); + break; + case 1003: /* continue */ + pCount->Continue(data,pCon); + break; + default: + assert(0); + } + } + } + if(data == NULL || pCount == NULL){ + SCPrintf(pCon,eLogError,"ERROR: slave counter %s NOT found or unusable", name); + } + } +} +/*---------------------------------------------------------------------------------*/ +static void startMultiCounting(pHdb self, SConnection *pCon) +{ + pHdb mode = NULL, preset = NULL, master = NULL, slaves = NULL; + pHdb sID, mID; + char *pPtr, name[80]; + pICountable pCount = NULL; + void *data; + long slaveID, masterID; + CounterMode eMode; + hdbValue v; + + mode = GetHipadabaNode(self,"mode"); + preset = GetHipadabaNode(self,"preset"); + master = GetHipadabaNode(self,"master"); + slaves = GetHipadabaNode(self,"slaves"); + sID = GetHipadabaNode(self,"slaveID"); + mID = GetHipadabaNode(self,"masterID"); + assert(mode != NULL); + assert(preset != NULL); + assert(master != NULL); + assert(slaves != NULL); + assert(sID != NULL); + assert(mID != NULL); + + if(strcmp(mode->value.v.text,"timer") == 0) { + eMode = eTimer; + } else { + eMode = ePreset; + } + + /* + start slaves + */ + slaveID = GetTaskGroupID(pServ->pTasker); + pPtr = slaves->value.v.text; + while((pPtr = stptok(pPtr,name,sizeof(name),",")) != NULL){ + data = FindCommandData(pServ->pSics,name,NULL); + if(data != NULL){ + pCount = GetCountableInterface(data); + if(pCount != NULL){ + pCount->SetCountParameters(data,preset->value.v.doubleValue, + eMode); + masterID = StartCountTask(data,pCon,name); + if(masterID < 0) { + SCPrintf(pCon,eLogError,"ERROR: failed to start slave %s, aborting", name); + doCountCommand(self,pCon,1001); + return; + } else { + AddTaskToGroup(pServ->pTasker,masterID, slaveID); + } + } + } + if(data == NULL || pCount == NULL){ + SCPrintf(pCon,eLogError,"ERROR: slave counter %s NOT found or unusable", name); + } + } + + + /* + start master + */ + data = FindCommandData(pServ->pSics,master->value.v.text,NULL); + if(data != NULL){ + pCount = GetCountableInterface(data); + if(pCount != NULL){ + pCount->SetCountParameters(data,preset->value.v.doubleValue, + eMode); + masterID = StartCountTask(data,pCon,master->value.v.text); + } + } + + v = MakeHdbInt(masterID); + UpdateHipadabaPar(mID,v,pCon); + v = MakeHdbInt(slaveID); + UpdateHipadabaPar(sID,v,pCon); + +} +/*---------------------------------------------------------------------------------*/ +static hdbCallbackReturn MultiSecControllCallback(pHdb node, + void *userData, + pHdbMessage message) +{ + pHdbDataMessage mm = NULL; + pHdb self = NULL; + int code; + SConnection *pCon = NULL; + + mm = GetHdbSetMessage(message); + if(mm == NULL){ + return hdbContinue; + } + + code = (int)mm->v->v.doubleValue; + pCon = (SConnection *)mm->callData; + self = node->mama; + assert(self != NULL); + + switch(code){ + case 1000: /* start */ + startMultiCounting(self, pCon); + break; + case 1001: /* stop */ + doCountCommand(self,pCon,code); + break; + case 1002: /*pause */ + doCountCommand(self,pCon,code); + break; + case 1003: /* continue */ + doCountCommand(self,pCon,code); + break; + default: + if(pCon != NULL){ + SCPrintf(pCon,eLogError,"ERROR: control code %d not recognised", code); + return hdbAbort; + } + } + + return hdbContinue; +} +/*-------------------------------------------------------------------------------------*/ +static int isMultiMasterRunning(pCounter self, SConnection *pCon, int *status) +{ + pHdb mID, master, myStatus, control, ccd, stopTime; + hdbValue v; + long mlID; + void *data; + pICountable pCount; + float controlVal; + + mID = GetHipadabaNode(self->objectNode,"masterID"); + master = GetHipadabaNode(self->objectNode,"master"); + myStatus = GetHipadabaNode(self->objectNode,"status"); + control = GetHipadabaNode(self->objectNode,"control"); + ccd = GetHipadabaNode(self->objectNode,"ccd"); + stopTime = GetHipadabaNode(self->objectNode,"stopTime"); + assert(mID != NULL); + assert(master != NULL); + assert(myStatus != NULL); + assert(control != NULL); + assert(ccd != NULL); + assert(stopTime != NULL); + + + mlID = mID->value.v.intValue; + if(mlID == 0) { + return 0; + } + + data = FindCommandData(pServ->pSics,master->value.v.text,NULL); + assert(data != NULL); + pCount = GetCountableInterface(data); + assert(pCount != NULL); + + if(isTaskIDRunning(pServ->pTasker,mlID)) { + *status = pCount->CheckCountStatus(data,pCon); + controlVal = GetControlValue((pCounter)data); + UpdateHipadabaPar(control,MakeHdbFloat(controlVal),pCon); + SecCounterSetError(self,"None"); + switch(*status){ + case HWFault: + UpdateHipadabaPar(myStatus,MakeHdbText("error"),pCon); + UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon); + SecCounterSetError(self,"Master counter errror"); + *status = HWBusy; + break; + case HWPause: + UpdateHipadabaPar(myStatus,MakeHdbText("paused"),pCon); + break; + case HWNoBeam: + UpdateHipadabaPar(myStatus,MakeHdbText("nobeam"),pCon); + break; + default: + *status = HWBusy; + UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); + break; + } + } else { + /* + we recently stopped. Mark it so and stop slaves. + */ + mID->value.v.intValue = 0; + *status = HWBusy; + UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); + UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon); + if(ccd->value.v.intValue != 1) { + doCountCommand(self->objectNode,pCon,1011); + } + } + return 1; +} +/*-------------------------------------------------------------------------------------*/ +static int areSlavesRunning(pCounter self, SConnection *pCon, int *status) +{ + pHdb slaveID, myStatus, stopTime, ccd; + int i; + + slaveID = GetHipadabaNode(self->objectNode,"slaveID"); + myStatus = GetHipadabaNode(self->objectNode,"status"); + stopTime = GetHipadabaNode(self->objectNode,"stopTime"); + ccd = GetHipadabaNode(self->objectNode,"ccd"); + assert(slaveID != NULL); + assert(myStatus != NULL); + assert(stopTime != NULL); + assert(ccd != NULL); + + if(isTaskGroupRunning(pServ->pTasker,slaveID->value.v.intValue)){ + if(ccd->value.v.intValue == 1 && time(NULL) > stopTime->value.v.intValue + 100) { + SCWrite(pCon,"WARNING: CCD overrun, restarting counting...", eLogError); + self->pCountInt->Halt(self); + ReleaseCountLock(self->pCountInt); + for(i = 0; i < 100; i++){ + SicsWait(1); + if(!isTaskGroupRunning(pServ->pTasker,slaveID->value.v.intValue)){ + self->pCountInt->StartCount(self,pCon); + UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); + UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon); + *status = HWBusy; + return 1; + } + } + SCWrite(pCon,"ERROR: failed to stop overrun CCD",eLogError); + *status = HWFault; + return 0; + } else { + *status = HWBusy; + UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); + return 1; + } + } else { + *status = HWIdle; + UpdateHipadabaPar(myStatus,MakeHdbText("idle"),pCon); + return 0; + } + return 1; +} +/*------------------------------------------------------------------------------------*/ +static void multiEndCounting(pCounter self, SConnection *pCon) +{ + + InvokeCallBack(self->pCall, COUNTEND, NULL); + ReleaseCountLock(self->pCountInt); + + +} +/*-------------------------------------------------------------------------------------*/ +static int MultiSecStatus(void *pData, SConnection * pCon) +{ + int status; + void *data; + pICountable pCount = NULL; + pHdb mID = NULL, sID = NULL, master; + pCounter self = (pCounter)pData; + + + if(isMultiMasterRunning(self,pCon, &status)){ + return status; + } + + if(areSlavesRunning(self,pCon, &status)){ + return status; + } + + multiEndCounting(self,pCon); + + return HWIdle; +} +/*--------------------------------------------------------------------------*/ +static int MultiSecTransfer(void *pData, SConnection * pCon) +{ + int i, retVal = OKOK, tclStatus; + char pBueffel[132]; + pCounter pCount = NULL; + pHdb transfer; + + pCount = (pCounter) pData; + + transfer = GetHipadabaNode(pCount->objectNode,"transfer"); + if(transfer != NULL){ + MacroPush(pCon); + tclStatus = Tcl_Eval(InterpGetTcl(pServ->pSics), transfer->value.v.text); + if (tclStatus != TCL_OK) { + snprintf(pBueffel, 131, "ERROR: TransferScript returned: %s", + Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); + SCWrite(pCon, pBueffel, eError); + MacroPop(); + return HWFault; + } + MacroPop(); + } + return retVal; +} + +/*--------------------------------------------------------------------------- + Forward unknown commands to the master counter + -----------------------------------------------------------------------------*/ +static int MultiInvokeSICSOBJ(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + int status; + char buffer[132]; + pHdb master = NULL; + pCounter self = (pCounter)pData; + void *data = NULL; + CommandList *pCom; + + status = InvokeSICSOBJ(pCon, pSics, pData, argc, argv); + if (status == -1) { + master = GetHipadabaNode(self->objectNode,"master"); + assert(master != NULL); + pCom = FindCommand(pSics,master->value.v.text); + if(pCom != NULL){ + status = pCom->OFunc(pCon,pSics,pCom->pData,argc,argv); + } + status = 0; + } + return status; +} +/*-------------------------------------------------------------------------------------*/ +int MakeMultiSec(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pCounter pRes = NULL; + int status, length; + pHdb node, child; + + if(argc < 3) { + SCWrite(pCon,"ERROR: need at least a name and length to create a counter", + eError); + return 0; + } + length = atoi(argv[2]); + + pRes = CreateSecCounter(pCon,"SingleCounter", argv[1], length); + if(pRes == NULL){ + return 0; + } + + pRes->pCountInt->CheckCountStatus = MultiSecStatus; + pRes->pCountInt->TransferData = MultiSecTransfer; + + node = pRes->objectNode; + child = GetHipadabaNode(node,"control"); + AppendHipadabaCallback(child,MakeHipadabaCallback(MultiSecControllCallback,NULL,NULL)); + + child = MakeSICSHdbPar("master", usMugger, MakeHdbText("")); + if (child == NULL) { + SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError); + return 0; + } else { + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + } + + child = MakeSICSHdbPar("transfer", usMugger, MakeHdbText("")); + if (child == NULL) { + SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError); + return 0; + } else { + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + } + + child = MakeSICSHdbPar("error", usMugger, MakeHdbText("None")); + if (child == NULL) { + SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError); + return 0; + } else { + AddHipadabaChild(node, child, NULL); + } + + child = MakeSICSHdbPar("slaves", usMugger, MakeHdbText("")); + if (child == NULL) { + SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError); + return 0; + } else { + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + } + + child = MakeSICSHdbPar("ccd", usMugger, MakeHdbInt(0)); + if (child == NULL) { + SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError); + return 0; + } else { + SetHdbProperty(child, "__save", "true"); + AddHipadabaChild(node, child, NULL); + } + + child = MakeSICSHdbPar("stopTime", usInternal, MakeHdbInt(0)); + if (child == NULL) { + SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError); + return 0; + } else { + AddHipadabaChild(node, child, NULL); + } + + child = MakeSICSHdbPar("masterID", usInternal, MakeHdbInt(0)); + if (child == NULL) { + SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError); + return 0; + } else { + AddHipadabaChild(node, child, NULL); + } + child = MakeSICSHdbPar("slaveID", usInternal, MakeHdbInt(0)); + if (child == NULL) { + SCWrite(pCon,"ERROR: out of memory in MakeMultiCounterSec",eError); + return 0; + } else { + AddHipadabaChild(node, child, NULL); + } + + status = + AddCommand(pSics, argv[1], MultiInvokeSICSOBJ, DeleteCounter, + (void *) pRes); + if (status != 1) { + SCPrintf(pCon,eError, "ERROR: duplicate command %s not created", argv[1]); + return 0; + } + return 1; +} diff --git a/ofac.c b/ofac.c index 521f45bd..441ad23c 100644 --- a/ofac.c +++ b/ofac.c @@ -145,6 +145,7 @@ static void InitIniCommands(SicsInterp * pInter) SCMD("MakeMcStasReader", McStasReaderFactory); SCMD("MakeMono", MonoInit); SCMD("MakeMultiCounter", MakeMultiCounter); + SCMD("MakeMultiSec", MakeMultiSec); SCMD("MakeNXScript", MakeNXScript); SCMD("MakeO2T", CreateO2T); SCMD("MakeOscillator", MakeOscillator); diff --git a/oscillate.c b/oscillate.c index 1aeb6f98..2f5bf772 100644 --- a/oscillate.c +++ b/oscillate.c @@ -4,6 +4,10 @@ copyright: see file COPYRIGHT Mark Koennecke, November 2004 + + Fixed to work with second generation motors too + + Mark Koennecke, September 2013 ------------------------------------------------------------------------*/ #include #include @@ -21,7 +25,7 @@ static void StopOscillation(pOscillator self) { assert(self != NULL); if (self->taskID > 0) { - self->pMot->pDriver->Halt(self->pMot->pDriver); + self->pMot->pDrivInt->Halt(self->pMot); self->stopFlag = 1; self->taskID = -1; } @@ -71,27 +75,20 @@ static int OscillationTask(void *data) return 0; } - status = self->pMot->pDriver->GetStatus(self->pMot->pDriver); + status = self->pMot->pDrivInt->CheckStatus(self->pMot,pServ->dummyCon); switch (status) { case HWFault: case HWPosFault: - self->pMot->pDriver->GetError(self->pMot->pDriver, &code, error, 255); - WriteToCommandLog("oscillator>> ", error); - pos = getCurrentTarget(self); - errStatus = - self->pMot->pDriver->TryAndFixIt(self->pMot->pDriver, code, pos); - self->errorCount++; - if (errStatus == MOTFAIL) { - /* - try driving the other way on a serious error - */ - pos = getNextPos(self); - status = MotorRun(self->pMot, self->pCon, pos); - if (self->debug > 0) { - snprintf(message, 131, "Started oscillation to %f, ret code = %d", - pos, status); - WriteToCommandLog("oscillator>>", message); - } + WriteToCommandLog("oscillator>> ", + "ERROR occurred in oscialltion, try running motor manually to find out more"); + WriteToCommandLog("oscillator>> ", + "Trying to run other direction"); + pos = getNextPos(self); + status = MotorRun(self->pMot, self->pCon, pos); + if (self->debug > 0) { + snprintf(message, 131, "Started oscillation to %f, ret code = %d", + pos, status); + WriteToCommandLog("oscillator>>", message); } break; case HWWarn: diff --git a/sicshipadaba.c b/sicshipadaba.c index 3ff2fe93..b92494e7 100644 --- a/sicshipadaba.c +++ b/sicshipadaba.c @@ -243,12 +243,12 @@ pHdbCallback MakeReadOnlyCallback() return MakeHipadabaCallback(SICSReadOnlyCallback, NULL, NULL); } /*------------------------------------------------------------------------------------*/ -static hdbCallbackReturn SICSValueCheckCallback(pHdb node, void *userData, +hdbCallbackReturn SICSValueCheckCallback(pHdb node, void *userData, pHdbMessage message) { SConnection *pCon = NULL; pHdbDataMessage mm = NULL; - char values[1024], *pPtr, pToken[80]; + char values[1024], *pPtr, pToken[80], *pVal; int status; hdbValue v; @@ -273,11 +273,15 @@ static hdbCallbackReturn SICSValueCheckCallback(pHdb node, void *userData, } pPtr = values; + pVal = strdup(v.v.text); + strtolower(pVal); while((pPtr = stptok(pPtr,pToken,sizeof(pToken),",")) != NULL){ - if(strcmp(pToken,v.v.text) == 0) { + if(strcmp(pToken,pVal) == 0) { + free(pVal); return hdbContinue; } } + free(pVal); if(pCon != NULL){ SCPrintf(pCon,eLogError,"ERROR: %s not allowed as value for %s, allowed are: %s", @@ -3958,7 +3962,7 @@ int InstallSICSHipadaba(SConnection * pCon, SicsInterp * pSics, AddCommand(pSics, "hnotify", AutoNotifyHdbNode, NULL, NULL); AddCommand(pSics, "hdelcb", RemoveHdbCallback, NULL, NULL); AddCommand(pSics, "hinfo", HdbNodeInfo, NULL, NULL); - AddCommand(pSics, "hval", HdbNodeVal, NULL, NULL); + /* AddCommand(pSics, "hval", HdbNodeVal, NULL, NULL);*/ AddCommand(pSics, "hchain", ChainHdbNode, NULL, NULL); AddCommand(pSics, "harray", HdbArrayNode, NULL, NULL); AddCommand(pSics, "hsetprop", SetSICSHdbProperty, NULL, NULL); diff --git a/sicshipadaba.h b/sicshipadaba.h index ad8efee0..527fb250 100644 --- a/sicshipadaba.h +++ b/sicshipadaba.h @@ -149,6 +149,14 @@ pHdbCallback MakeTreeChangeCallback(SConnection * pCon, int id); * make a clalback to invoke a function node */ pHdbCallback MakeSICSFuncCallback(void *obj); +/** + * callback for checking node values against the values property + * @param node The node to for which this callback has been called + * @param userData userData associated with this callback. NULL expected + * @param message The message sent to the node + */ +hdbCallbackReturn SICSValueCheckCallback(pHdb node, void *userData, + pHdbMessage message); /*======================== parameter creation ===================================*/ /** diff --git a/tasdrive.c b/tasdrive.c index 605dc125..5fe1ea3d 100644 --- a/tasdrive.c +++ b/tasdrive.c @@ -272,7 +272,6 @@ static float getMotorValue(pMotor mot, SConnection * pCon) } /*--------------------- In devexec.c --------------------------------------*/ void InvokeNewTarget(pExeList self, char *name, float target); - /*--------------------------------------------------------------------------*/ static int startTASMotor(pMotor mot, SConnection * pCon, char *name, double target, int silent, int stopFixed) @@ -312,7 +311,31 @@ static int startTASMotor(pMotor mot, SConnection * pCon, char *name, } return status; } +/*-------------------------------------------------------------------------*/ +static int StartTASA3(pMotor mot, SConnection *pCon, char *name, + double target, int silent, int stopFixed) +{ + float val; + int status; + char buffer[80]; + val = getMotorValue(mot,pCon); + if(ABS(target-val) > 190) { + SCPrintf(pCon,eLog,"WARNING: driving a3 more then 190 degree: %f, please confirm with y", + ABS(target-val)); + status = SCPromptTMO(pCon,NULL,buffer,sizeof(buffer),120); + if(status == 1){ + if(buffer[0] == 'y'){ + return startTASMotor(mot,pCon,name,target,silent,stopFixed); + } + } + SCWrite(pCon,"ERROR: no or wrong reply, aborting scan",eLogError); + SCSetInterrupt(pCon,eAbortScan); + return HWFault; + } else { + return startTASMotor(mot,pCon,name,target,silent,stopFixed); + } +} /*---------------------------------------------------------------------------*/ static int startMotors(ptasMot self, tasAngles angles, SConnection * pCon, int driveQ, int driveTilt) @@ -326,38 +349,6 @@ 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) { */ - /* 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){ @@ -408,7 +399,7 @@ static int startMotors(ptasMot self, tasAngles angles, /* crystal */ - status = startTASMotor(self->math->motors[A3], pCon, "a3", + status = StartTASA3(self->math->motors[A3], pCon, "a3", angles.a3, silent,stopFixed); if (status != OKOK) { return status; diff --git a/test/testini.tcl b/test/testini.tcl index a108083f..4f3fcddb 100644 --- a/test/testini.tcl +++ b/test/testini.tcl @@ -577,7 +577,7 @@ amorhmsct poll /sics/amorhm/collapse 20 #source ../sim/mars/julcho.tcl -MakeSinqRedirect lnsl15 10500 +#MakeSinqRedirect lnsl15 10500 MakeSingleX singlex configure stt a4 @@ -847,4 +847,12 @@ if {$zwickroll == 1} { # makesctcontroller zwro std pc8977:50370 \r\n 5 \r\n makesctcontroller zwro std localhost:8080 \r\n 5 \n zwickroll::makezwickroll zwro -} \ No newline at end of file +} + +set sputter 1 + +if {$sputter == 1} { + source ../sim/sicscommon/stddrive.tcl + source ../sim/amor_sics/sputter.tcl + SputterInit +} diff --git a/testprot.c b/testprot.c index 91c9a2fc..29b52eb3 100644 --- a/testprot.c +++ b/testprot.c @@ -103,13 +103,18 @@ static void findResponse(Ascon *a) dict = (pStringDict)a->private; status = StringDictGet(dict,GetCharArray(a->wrBuffer),response, sizeof(response)); if(status != 1){ + if(StringDictGet(dict,"echofail",response,sizeof(response)) == 1) { + DynStringConcat(a->rdBuffer,GetCharArray(a->wrBuffer)); + return; + } else { a->state = AsconFailed; DynStringConcat(a->errmsg,"ERROR: no response found in dictionary for "); DynStringConcat(a->errmsg,GetCharArray(a->wrBuffer)); return; + } } /** - Tclescape is an escape string/character which idetifies a response as a tcl invocation. + Tclescape is an escape string/character which identifies a response as a tcl invocation. Thus the algorithm runs: * Find out if there is a Tcl escape * If so: diff --git a/trace.c b/trace.c index cf78f0e1..96364900 100644 --- a/trace.c +++ b/trace.c @@ -17,23 +17,30 @@ * * Created on: Apr 27, 2011 * Author: koennecke + * + * Enhanced to write time stamps any ten minutes. + * + * Mark Koennecke, October 2013 */ +#include +#include #include #include #include #include #include -static FILE *log = NULL; +static FILE *logFD = NULL; static char *logfile = NULL; static int hdbInit = 0; static int filterProv = 0; static int debug = 0; +static int lastTen = -10; /*----------------------------------------------------------------------------------------*/ int traceActive() { - if (log == NULL){ + if (logFD == NULL){ return 0; } else { return 1; @@ -201,14 +208,14 @@ void traceprint(char *sub, char *id, char *data) { char *mysub, *myid, *mydata; - if(log != NULL && filter(sub,id)){ + if(logFD != 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); + fprintf(logFD,"%s:%s:%lf:%s\n",mysub,myid,DoubleTime(),mydata); free(mysub); free(myid); free(mydata); @@ -221,7 +228,7 @@ void traceIO(char *id, char *format, ...) char buffer[1024], *buf = NULL; int len; - if(log != NULL && filter("io","id")){ + if(logFD != NULL && filter("io","id")){ va_start(argptr,format); len = vsnprintf(buffer, sizeof(buffer),format,argptr); va_end(argptr); @@ -247,7 +254,7 @@ void traceDevice(char *id, char *format, ...) char buffer[1024], *buf = NULL; int len; - if(log != NULL && filter("dev","id")){ + if(logFD != NULL && filter("dev","id")){ va_start(argptr,format); len = vsnprintf(buffer, sizeof(buffer),format,argptr); va_end(argptr); @@ -272,7 +279,7 @@ void traceCommand(char *id, char *format, ...) char buffer[1024], *buf = NULL; int len; - if(log != NULL && filter("com","id")){ + if(logFD != NULL && filter("com","id")){ va_start(argptr,format); len = vsnprintf(buffer, sizeof(buffer),format,argptr); va_end(argptr); @@ -297,7 +304,7 @@ void tracePar(char *id, char *format, ...) char buffer[1024], *buf = NULL; int len; - if(log != NULL && filter("par","id")){ + if(logFD != NULL && filter("par","id")){ va_start(argptr,format); len = vsnprintf(buffer, sizeof(buffer),format,argptr); va_end(argptr); @@ -322,7 +329,7 @@ void traceSys(char *id, char *format, ...) char buffer[1024], *buf = NULL; int len; - if(log != NULL && filter("sys","id")){ + if(logFD != NULL && filter("sys","id")){ va_start(argptr,format); len = vsnprintf(buffer, sizeof(buffer),format,argptr); va_end(argptr); @@ -347,7 +354,7 @@ void traceDebug(char *id, char *format, ...) char buffer[1024], *buf = NULL; int len; - if(log != NULL && debug == 1){ + if(logFD != NULL && debug == 1){ va_start(argptr,format); len = vsnprintf(buffer, sizeof(buffer),format,argptr); va_end(argptr); @@ -374,7 +381,7 @@ static void saveInitialParameters() float value; pDummy pDum = NULL; - if(log == NULL){ + if(logFD == NULL){ return; } @@ -387,58 +394,83 @@ static void saveInitialParameters() snprintf(prefix,sizeof(prefix),"par:start:%s", pCom->pName); pDum = (pDummy)pCom->pData; if(pDum != NULL){ - pDum->pDescriptor->SaveStatus(pCom->pData,prefix, log); + pDum->pDescriptor->SaveStatus(pCom->pData,prefix, logFD); pDriv = pDum->pDescriptor->GetInterface(pCom->pData, DRIVEID); if(pDriv != NULL){ value = pDriv->GetValue(pCom->pData,pServ->dummyCon); - fprintf(log,"%s:%f\n", prefix,value); + fprintf(logFD,"%s:%f\n", prefix,value); } } pCom = pCom->pNext; } - fprintf(log,"par:start:EOF\n"); + fprintf(logFD,"par:start:EOF\n"); +} +/*----------------------------------------------------------------*/ +static int TraceLogTask(void *data) +{ + time_t iDate; + struct tm *psTime; + char pBuffer[132]; + int tenmin; + + if(logFD == NULL){ + return 0; + } + iDate = time(NULL); + psTime = localtime(&iDate); + tenmin = (int)floor(1.0*psTime->tm_min/10.); + if(tenmin != lastTen){ + memset(pBuffer, 0, sizeof(pBuffer)); + strftime(pBuffer, sizeof(pBuffer)-1, "%Y-%m-%d@%H-%M-%S", psTime); + lastTen = tenmin; + traceSys("TIMESTAMP",pBuffer); + } + + return 1; } /*----------------------------------------------------------------*/ static int TraceLog(pSICSOBJ ccmd, SConnection * con, - Hdb * cmdNode, Hdb * par[], int nPar) + Hdb * cmdNode, Hdb * par[], int nPar) { char *filename = NULL; if(nPar < 1) { - if(log != NULL){ - SCPrintf(con,eValue,"Tracing to %s", logfile); - } else { - SCWrite(con,"Tracing is off", eValue); - } - return 1; + if(logFD != NULL){ + SCPrintf(con,eValue,"Tracing to %s", logfile); + } else { + SCWrite(con,"Tracing is off", eValue); + } + return 1; } filename = par[0]->value.v.text; if(strcmp(filename,"close") == 0 ){ - if(log != NULL){ - fclose(log); - log = NULL; - SCPrintf(con,eValue,"Tracing to %s closed", logfile); - free(logfile); - } + if(logFD != NULL){ + fclose(logFD); + logFD = NULL; + SCPrintf(con,eValue,"Tracing to %s closed", logfile); + free(logfile); + } } else { - if(log != NULL){ - fclose(log); - free(logfile); - } - log = fopen(filename,"w"); - if(log == NULL){ - SCPrintf(con,eError,"ERROR: failed to open %s for logging", filename); - return 0; - } else { - logfile = strdup(filename); - saveInitialParameters(); - SCPrintf(con,eValue,"Logging to %s", filename); - if(hdbInit == 0){ - TraceObjects(); - hdbInit = 1; - } - } + if(logFD != NULL){ + fclose(logFD); + free(logfile); + } + logFD = fopen(filename,"w"); + if(logFD == NULL){ + SCPrintf(con,eError,"ERROR: failed to open %s for logging", filename); + return 0; + } else { + logfile = strdup(filename); + saveInitialParameters(); + SCPrintf(con,eValue,"Logging to %s", filename); + if(hdbInit == 0){ + TraceObjects(); + hdbInit = 1; + } + TaskRegisterN(pServ->pTasker,"tracestamper", + TraceLogTask, NULL, NULL, NULL, 1); + } } return 1; } @@ -465,10 +497,10 @@ static int TraceFilter(pSICSOBJ ccmd, SConnection * con, /*-----------------------------------------------------------------------------*/ static void KillTrace(void *data) { - if(log != NULL){ - fclose(log); + if(logFD != NULL){ + fclose(logFD); free(logfile); - log = NULL; + logFD = NULL; logfile = NULL; } }