diff --git a/devexec.c b/devexec.c index 91f2b8b9..187a0427 100644 --- a/devexec.c +++ b/devexec.c @@ -398,7 +398,106 @@ int StartDevice(pExeList self, char *name, pObjectDescriptor pDes, } return 0; } +/*------------------------------------------------------------------------ + * This is a hacking thing to bypass the whole access checking thing. I + * need it at POLDI to run the fucking high voltage while the instrument is + * still counting. + */ +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]; + 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 = TaskRegister(self->pTask, + DevExecTask, + DevExecSignal, NULL, self, 1); + self->iEnd = 0; + pCon->conStatus = HWBusy; + } + DevexecLog("START", pNew->name); + 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; +} /*--------------------------------------------------------------------------*/ int StartMotor(pExeList self, SicsInterp * pSics, SConnection * pCon, char *name, int level, float fVal) @@ -1147,6 +1246,10 @@ int DevexecAction(SConnection * pCon, SicsInterp * pSics, void *pData, { int val; char pBueffel[256]; + void *data = NULL; + pDummy pDum = NULL; + float fTarget; + CommandList *pCom = NULL; pExeList self = (pExeList) pData; if (argc < 2) { @@ -1166,6 +1269,26 @@ int DevexecAction(SConnection * pCon, SicsInterp * pSics, void *pData, SCWrite(pCon, pBueffel, eValue); return 1; } + } else if(strcmp(argv[1],"force") == 0) { + if(argc < 4){ + SCWrite(pCon,"ERROR: insufficient number of arguments to devexec force", + eError); + return 0; + } + pCom = FindCommand(pSics,argv[2]); + fTarget = atof(argv[3]); + if(pCom == NULL){ + SCPrintf(pCon,eError,"ERROR: command %s to force not found", argv[2]); + return 0; + } + data = pCom->pData; + pDum = (pDummy)data; + if(GetDrivableInterface(data) == NULL && GetCountableInterface(data) == NULL ){ + SCPrintf(pCon,eError,"ERROR: command %s not startable", argv[2]); + return 0; + } + val = ForceStartDevice(self,argv[2],pDum->pDescriptor,data, pCon, fTarget); + return val; } else { SCWrite(pCon, "ERROR: unknown subcommand to devexec", eError); return 0; diff --git a/fitcenter.c b/fitcenter.c index fd4b2981..d8c2ae3c 100644 --- a/fitcenter.c +++ b/fitcenter.c @@ -6,6 +6,11 @@ copyright: see copyright.h Mark Koennecke, October 1997 + + Added center of edge finding + + Mark Koennecke, Octover 2011 + -----------------------------------------------------------------------------*/ #include #include @@ -221,6 +226,51 @@ static int CalculateFitIntern(pFit self) return iRet; } +/*-------------------------------------------------------------------------*/ +static int CalculateEdgeIntern(pFit self) +{ + int i, iRet, iPeak, nSlope = 0;; + long lCount; + float fNenner,fSum, fCI; + + + /* find the maximum counts */ + iRet = FindMax(self); + self->lPeak = self->lCounts[iRet]; + /* a default fit is the peak maximum. This + helps optimise to do the right thing if no proper calculation + could be performed + */ + if (self->lPeak < 3) { + return -3; + } + + /* + * calculate the COG between .9*max < counts < .1*max + */ + fSum = 0.; + fNenner = 0.; + for (i = 0; i < self->iNP; i++) { + lCount = self->lCounts[i]; + if(lCount > self->lPeak *.20 && lCount < self->lPeak * .80){ + fSum += lCount * self->fAxis[i]; + fNenner += lCount; + nSlope++; + } + } + if(fNenner > .0001){ + fCI = fSum / fNenner; + } else { + return -3; + } + self->fCenter = fCI; + self->fStddev = 1.0; + + if(nSlope < 3) { + iRet = -7; + } + return iRet; +} /*--------------------------------------------------------------------------*/ int CalculateFit(pFit self) @@ -328,7 +378,7 @@ int FitFactory(SConnection * pCon, SicsInterp * pSics, void *pData, pDummy pDum = NULL; CommandList *pCom = NULL; char pBueffel[132]; - int iRet, iRet1; + int iRet, iRet1, iRet2; if (argc < 2) { SCWrite(pCon, @@ -365,6 +415,7 @@ int FitFactory(SConnection * pCon, SicsInterp * pSics, void *pData, iRet = AddCommand(pSics, "peak", FitWrapper, DeleteFitCenter, self); iRet1 = AddCommand(pSics, "center", CenterWrapper, NULL, self); + iRet2 = AddCommand(pSics, "edge", EdgeWrapper, NULL, self); if (!iRet || !iRet1) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate commands peak and center not created"); @@ -374,7 +425,6 @@ int FitFactory(SConnection * pCon, SicsInterp * pSics, void *pData, } return 1; } - /*--------------------------------------------------------------------------*/ int FitWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) @@ -451,7 +501,65 @@ int FitWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, return 1; } +/*---------------------------------------------------------------------------*/ +int EdgeWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]) +{ + pFit self = NULL; + int iRet; + char pBueffel[256]; + pDynString buf = NULL; + self = (pFit) pData; + assert(self); + + Init(self); + iRet = CalculateEdgeIntern(self); + switch (iRet) { + case 0: + SCWrite(pCon, "ERROR: failure to fit your data!", eError); + return 0; + break; + case -3: + SCWrite(pCon, "ERROR: No counts found in Fit!", eError); + return 0; + break; + case -4: + SCWrite(pCon, "ERROR: Insufficient counts in peak", eError); + return 0; + break; + case -7: + SCWrite(pCon, + "WARNING: not enough points in slope, results may be inreliable, remeasure with smaller step width", + eWarning); + break; + } + + /* + This is a little feature to get the peak without rubbish for + the TAS routines + */ + if (argc > 1) { + strtolower(argv[1]); + if (strcmp(argv[1], "value") == 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%f", self->fCenter); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + } + + /* print results */ + SCStartBuffering(pCon); + snprintf(pBueffel,sizeof(pBueffel)-1, "Estimated Edge Center: %f\n", + self->fCenter); + SCWrite(pCon, pBueffel, eValue); + buf = SCEndBuffering(pCon); + if (buf != NULL) { + SCWrite(pCon, GetCharArray(buf), eValue); + } + + return 1; +} /*---------------------------------------------------------------------------*/ int CenterWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) diff --git a/fitcenter.h b/fitcenter.h index 0d7285ff..d2b7bec9 100644 --- a/fitcenter.h +++ b/fitcenter.h @@ -8,6 +8,10 @@ copyright: see copyright.h Mark Koennecke, October 1997 + + Added center of edge finding + + Mark Koennecke, Octover 2011 ----------------------------------------------------------------------------*/ #ifndef SICSFITCENTER #define SICSFITCENTER @@ -33,6 +37,8 @@ int FitFactory(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]); int FitWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]); +int EdgeWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, + int argc, char *argv[]); int CenterWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]); diff --git a/macro.c b/macro.c index 63cd295d..ea2bd798 100644 --- a/macro.c +++ b/macro.c @@ -1089,7 +1089,7 @@ int CaptureAction(SConnection *pCon, SicsInterp * pSics, void *pData, comCon = SCCopyConnection(pCon); if (comCon == NULL) { - SCWrite(pCon, "EROOR: out of memory in capture", eError); + SCWrite(pCon, "ERROR: out of memory in capture", eError); return 0; } /* diff --git a/motor.c b/motor.c index 0c13fa1a..40770d83 100644 --- a/motor.c +++ b/motor.c @@ -1,3 +1,4 @@ + /*------------------------------------------------------------------------ M O T O R S diff --git a/motorlist.c b/motorlist.c index ebfeeb87..a22c916b 100644 --- a/motorlist.c +++ b/motorlist.c @@ -125,6 +125,12 @@ static int MOLICheckStatus(void *data, SConnection * pCon) break; case HWFault: case HWPosFault: + /** + * It is questionable if one should not set a flag here + * and keep p;olling: it is not clear if this error is a + * communication problem or that the motor really + * has stopped. + */ return status; break; default: @@ -138,6 +144,47 @@ static int MOLICheckStatus(void *data, SConnection * pCon) } return result; } +/*--------------------------------------------------------- + A special version for EIGER. I am coutious: I have problems + with this at EIGER but I do not want to propogate the fix + elsewhere even if it may be the right thing to do. + -----------------------------------------------------------*/ +int MOLIEigerStatus(void *data, SConnection * pCon) +{ + int self = 0, iRet, status, result = HWIdle; + MotControl tuktuk; + + self = *(int *) data; + + iRet = LLDnodePtr2First(self); + while (iRet != 0) { + LLDnodeDataTo(self, &tuktuk); + if (tuktuk.running == 1) { + status = tuktuk.pDriv->CheckStatus(tuktuk.data, pCon); + switch (status) { + case HWIdle: + tuktuk.running = 0; + LLDnodeDataFrom(self, &tuktuk); + break; + case HWBusy: + result = HWBusy; + break; + case HWFault: + case HWPosFault: + tuktuk.running = 0; + LLDnodeDataFrom(self, &tuktuk); + break; + default: + /* + this is a programming error and has to be fixed + */ + assert(0); + } + } + iRet = LLDnodePtr2Next(self); + } + return result; +} /*---------------------------------------------------------------- GetValue is supposed to read a motor position diff --git a/motorsec.c b/motorsec.c index aca6c152..76faaebc 100644 --- a/motorsec.c +++ b/motorsec.c @@ -210,13 +210,13 @@ static int checkPosition(pMotor self, SConnection * pCon) float precision, hard, target, maxretry; pHdb node = NULL; - if (SCGetInterrupt(pCon) != eContinue) { - return HWFault; - } if (self->stopped) { SCPrintf(pCon, eWarning, "WARNING: %s stopped", self->name); return HWFault; } + if (SCGetInterrupt(pCon) != eContinue) { + return HWFault; + } SecMotorGetPar(self, "hardposition", &hard); SecMotorGetPar(self, "targetposition", &target); SecMotorGetPar(self, "precision", &precision); diff --git a/sicshipadaba.c b/sicshipadaba.c index 90f6aee7..f77872eb 100644 --- a/sicshipadaba.c +++ b/sicshipadaba.c @@ -2405,6 +2405,7 @@ static int UpdateHdbNode(SConnection * pCon, SicsInterp * pSics, if (targetNode == NULL) { return 0; } + /* SCPrintf(pCon,eWarning, "Updating %s", argv[1]); */ if (argc > 2) { if (!cloneHdbValue(&targetNode->value, &newValue)) { SCWrite(pCon, "ERROR: out of memory cloning node", eError); diff --git a/tasdrive.c b/tasdrive.c index b338fea8..fcdb3cbe 100644 --- a/tasdrive.c +++ b/tasdrive.c @@ -72,8 +72,10 @@ static int readTASMotAngles(ptasUB self, SConnection * pCon, } ang->monochromator_two_theta = val; if (ABS(val / 2. - theta) > .1) { - SCWrite(pCon, "WARNING: theta monochromator not half of two theta", - eWarning); + if(DevExecLevelRunning(pServ->pExecutor,RUNRUN) != 1) { + SCWrite(pCon, "WARNING: theta monochromator not half of two theta", + eWarning); + } } /* @@ -90,7 +92,7 @@ static int readTASMotAngles(ptasUB self, SConnection * pCon, return status; } ang->analyzer_two_theta = val; - if (ABS(val / 2. - theta) > .1) { + if (ABS(val / 2. - theta) > .1 && DevExecLevelRunning(pServ->pExecutor,RUNRUN) != 1) { SCWrite(pCon, "WARNING: theta analyzer not half of two theta", eWarning); } @@ -236,7 +238,7 @@ static void writeMotPos(SConnection * pCon, int silent, char *name, if (silent != 1) { snprintf(pBueffel, 131, "Driving %5s from %8.3f to %8.3f", name, val, target); - SCWrite(pCon, pBueffel, eWarning); + SCWrite(pCon, pBueffel, eLog); } } @@ -258,6 +260,7 @@ static int startTASMotor(pMotor mot, SConnection * pCon, char *name, char buffer[132]; pIDrivable pDriv = NULL; pDummy dum = NULL; + pDynString mes = NULL; dum = (pDummy)mot; if(strcmp(dum->pDescriptor->name,"Motor") == 0){ @@ -272,8 +275,11 @@ static int startTASMotor(pMotor mot, SConnection * pCon, char *name, mot->stopped = 0; if (ABS(val - target) > MOTPREC) { pDriv = GetDrivableInterface(mot); + SCStartBuffering(pCon); status = pDriv->SetValue(mot, pCon, (float) target); + mes = SCEndBuffering(pCon); if (status != OKOK) { + SCPrintf(pCon,eLogError, GetCharArray(mes)); return status; } } @@ -310,7 +316,8 @@ static int startMotors(ptasMot self, tasAngles angles, status = startTASMotor(self->math->motors[MCV], pCon, "mcv", curve, silent); if (status != OKOK) { - return status; + SCWrite(pCon,"WARNING: monochromator vertical curvature motor failed to start", eWarning); + SCSetInterrupt(pCon,eContinue); } } @@ -319,8 +326,9 @@ static int startMotors(ptasMot self, tasAngles angles, angles.monochromator_two_theta); status = startTASMotor(self->math->motors[MCH], pCon, "mch", curve, silent); - if (status != OKOK) { - return status; + if (status != OKOK) { + SCWrite(pCon,"WARNING: monochromator horizontal curvature motor failed to start", eWarning); + SCSetInterrupt(pCon,eContinue); } } @@ -346,7 +354,8 @@ static int startMotors(ptasMot self, tasAngles angles, status = startTASMotor(self->math->motors[ACV], pCon, "acv", curve, silent); if (status != OKOK) { - return status; + SCWrite(pCon,"WARNING: analyzer vertical curvature motor failed to start", eWarning); + SCSetInterrupt(pCon,eContinue); } } if (self->math->motors[ACH] != NULL) { @@ -355,7 +364,8 @@ static int startMotors(ptasMot self, tasAngles angles, status = startTASMotor(self->math->motors[ACH], pCon, "ach", curve, silent); if (status != OKOK) { - return status; + SCWrite(pCon,"WARNING: analyzer horizontal curvature motor failed to start", eWarning); + SCSetInterrupt(pCon,eContinue); } } } @@ -450,7 +460,6 @@ static int checkQMotorLimits(ptasMot self, SConnection * pCon, } return retVal; } - /*-----------------------------------------------------------------------------*/ static int calculateAndDrive(ptasMot self, SConnection * pCon) { @@ -461,31 +470,33 @@ static int calculateAndDrive(ptasMot self, SConnection * pCon) if (self->math->ubValid == 0) { SCWrite(pCon, "WARNING: UB matrix invalid", eWarning); } + status = calcAllTasAngles(&self->math->machine, self->math->target, &angles); self->math->mustDrive = 0; + switch (status) { case ENERGYTOBIG: - SCWrite(pCon, "ERROR: desired energy to big", eError); - return HWFault; - break; + SCWrite(pCon, "ERROR: desired energy to big", eError); + return HWFault; + break; case UBNOMEMORY: - SCWrite(pCon, "ERROR: out of memory calculating angles", eError); - driveQ = 0; - break; + SCWrite(pCon, "ERROR: out of memory calculating angles", eError); + driveQ = 0; + break; case BADRMATRIX: - SCWrite(pCon, "ERROR: bad crystallographic parameters or bad UB", - eError); - driveQ = 0; - break; + SCWrite(pCon, "ERROR: bad crystallographic parameters or bad UB", + eError); + driveQ = 0; + break; case BADUBORQ: - SCWrite(pCon, "ERROR: bad UB matrix or bad Q-vector", eError); - driveQ = 0; - break; + SCWrite(pCon, "ERROR: bad UB matrix or bad Q-vector", eError); + driveQ = 0; + break; case TRIANGLENOTCLOSED: - SCWrite(pCon, "ERROR: cannot close scattering triangle", eError); - driveQ = 0; - break; + SCWrite(pCon, "ERROR: cannot close scattering triangle", eError); + driveQ = 0; + break; } /** * check out of plane condition and permission @@ -523,8 +534,8 @@ static int calculateAndDrive(ptasMot self, SConnection * pCon) /*-----------------------------------------------------------------------------*/ static int checkMotors(ptasMot self, SConnection * pCon) { - int i, status, length = 12; - int mask[12]; + int i, status, length = 12, count; + int mask[12], busy[12]; pIDrivable pDrivInt = NULL; self->math->mustRecalculate = 1; @@ -532,8 +543,10 @@ static int checkMotors(ptasMot self, SConnection * pCon) length = 8; } memset(mask, 0, 12 * sizeof(int)); + memset(busy, 0, 12 * sizeof(int)); for (i = 0; i < length; i++) { mask[i] = 1; + busy[i] = 1; } if (self->math->outOfPlaneAllowed == 0) { mask[SGU] = 0; @@ -541,15 +554,26 @@ static int checkMotors(ptasMot self, SConnection * pCon) } for (i = 0; i < 12; i++) { - if (self->math->motors[i] != NULL && mask[i] != 0) { - pDrivInt = GetDrivableInterface(self->math->motors[i]); - status = pDrivInt->CheckStatus(self->math->motors[i], pCon); - if (status != HWIdle && status != OKOK) { - return status; - } + if(self->math->motors[i] == NULL){ + busy[i] = 0; + } else { + if(mask[i] != 0) { + pDrivInt = GetDrivableInterface(self->math->motors[i]); + status = pDrivInt->CheckStatus(self->math->motors[i], pCon); + if(status == HWIdle || status == OKOK || status == HWFault || status == HWPosFault){ + busy[i] = 0; + } + } } } - return HWIdle; + for(i = 0, count = 0; i < 12; i++){ + count += busy[i]; + } + if(count == 0) { + return HWIdle; + } else { + return HWBusy; + } } /*------------------------------------------------------------------------------*/ diff --git a/tasscanub.c b/tasscanub.c index 9bfa31e6..07c1e5da 100644 --- a/tasscanub.c +++ b/tasscanub.c @@ -560,6 +560,11 @@ static int TASUBScanPoint(pScanData self, int iPoint) long m1, m2, m3, cnts; char pBueffel[1024], pWork[80], pError[132]; + /* + * force an update to write the right things + */ + tasUpdate(self->pCon,pTAS->ub); + /* after polarisation analysis, this has to be ignored as it is called another time from the ScanLoop @@ -746,7 +751,7 @@ static int TASUBScanCount(pScanData self, int iPoint) */ fVal = GetCounterPreset(self->pCounterData); eOld = GetStatus(); - status = DoCount(self->pCounterData, fVal, self->pCon, 0); + status = DoCount(self->pCounterData, fVal, self->pCon, 1); iRet = Wait4Success(GetExecutor()); if (iRet == DEVINT) { SCWrite(self->pCon, "Counting aborted due to Interrupt", eLog); diff --git a/tasub.c b/tasub.c index 618972eb..fae652d8 100644 --- a/tasub.c +++ b/tasub.c @@ -1769,7 +1769,7 @@ static int setTarget(SConnection * pCon, SicsInterp * pSics, ptasUB self, } /*------------------------------------------------------------------*/ -static int tasUpdate(SConnection * pCon, ptasUB self) +int tasUpdate(SConnection * pCon, ptasUB self) { int status; tasAngles angles; diff --git a/tasub.h b/tasub.h index cfd0da20..4aa1d40d 100644 --- a/tasub.h +++ b/tasub.h @@ -52,4 +52,5 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData, int findReflection(int list, int idx, ptasReflection r); +int tasUpdate(SConnection *pCon, ptasUB self); #endif diff --git a/tasub.w b/tasub.w index bcedf49b..ab8fd3ac 100644 --- a/tasub.w +++ b/tasub.w @@ -110,6 +110,7 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData, /*--------------------------------------------------------------------*/ @ int findReflection(int list, int idx, ptasReflection r); +int tasUpdate(SConnection *pCon, ptasUB self); #endif @} @o tasdrive.h @{ diff --git a/volist.tcl b/volist.tcl index 0881dc02..ce4d945d 100644 --- a/volist.tcl +++ b/volist.tcl @@ -25,6 +25,7 @@ set txt [counter getcounts] set cts [omGetNum $txt] omth add 3 $cts + drive stt 66 om 33. counter count $preset set txt [counter getcounts]