/*-------------------------------------------------------------------------- S C A N Implementation file for the SICS scan command. Mark Koennecke, October 1997, June 2001 Extracted scanvar.c, .h Extended to allow for storing and retrieving of all scan data from scripts Changed recover to work with ASCII files using the feautures implemented above. Extracted stdscan.h, stdscan.c Mark Koennecke, November 2004 copyright: see copyright.h ----------------------------------------------------------------------------*/ #include "sics.h" #include #include #include #include #include "fortify.h" #include "sdynar.h" #include "dynstring.h" #include "stringdict.h" #include "status.h" #include "sicsvar.h" #include "counter.h" #include "scan.h" #include "scan.i" #include "integrate.h" #include "udpquieck.h" #include "splitter.h" #include "danu.h" #include "userscan.h" #include "motor.h" #include "nxscript.h" #include "site.h" #include "lld.h" #include "stdscan.h" /*---------------------------------------------------------------------------*/ static void DeleteCountEntry(void *pData) { free(pData); } /*---------------------------------------------------------------------------*/ void InitCountEntry(pCountEntry pCount) { int i; pCount->lCount = -1L; pCount->i = -1; pCount->fTime = -1.0; for (i = 0; i < 10; i++) { pCount->Monitors[i] = -1L; } } /*--------------------------------------------------------------------------*/ static int DummyWrite(pScanData self) { return 1; } /*--------------------------------------------------------------------------*/ static int DummyWrite2(pScanData self, int iPoint) { return 1; } /*---------------------------------------------------------------------------*/ static void *ScanInterface(void *pData, int iInter) { pScanData self = NULL; self = (pScanData) pData; assert(self); if (iInter == CALLBACKINTERFACE) { return self->pCall; } return NULL; } /*------------------------------------------------------------------------*/ static void ConfigureScanDict(pStringDict dict) { StringDictAddPair(dict, "writeheader", "stdscan writeheader"); StringDictAddPair(dict, "prepare", "stdscan prepare"); StringDictAddPair(dict, "drive", "stdscan drive"); StringDictAddPair(dict, "count", "stdscan count"); StringDictAddPair(dict, "collect", "stdscan collect"); StringDictAddPair(dict, "writepoint", "stdscan writepoint"); StringDictAddPair(dict, "userdata", "unknown"); StringDictAddPair(dict, "finish", "stdscan finish"); } /*------------------------------------------------------------------------*/ static void ResetScanDict(pStringDict dict) { StringDictUpdate(dict, "writeheader", "stdscan writeheader"); StringDictUpdate(dict, "prepare", "stdscan prepare"); StringDictUpdate(dict, "drive", "stdscan drive"); StringDictUpdate(dict, "count", "stdscan count"); StringDictUpdate(dict, "collect", "stdscan collect"); StringDictUpdate(dict, "writepoint", "stdscan writepoint"); StringDictUpdate(dict, "userdata", "unknown"); StringDictUpdate(dict, "finish", "stdscan finish"); } /*--------------------------------------------------------------------------*/ pScanData CreateScanObject(char *pRecover, char *pHeader, pCounter pCount, char *objName) { pScanData pNew = NULL; pNew = (pScanData) malloc(sizeof(ScanData)); if (!pNew) { return NULL; } memset(pNew, 0, sizeof(ScanData)); /* create an ObjectDescriptor */ pNew->pDes = CreateDescriptor("ScanObject"); if (!pNew->pDes) { free(pNew); return NULL; } pNew->pDes->GetInterface = ScanInterface; /* allocate the dynamic arrays */ pNew->pScanVar = CreateDynar(0, 10, 10, DeleteVarEntry); pNew->pCounts = CreateDynar(0, 10, 10, DeleteCountEntry); pNew->scanFunctions = CreateStringDict(); if ((!pNew->pScanVar) || (!pNew->pCounts) || (!pNew->scanFunctions)) { DeleteDescriptor(pNew->pDes); free(pNew); return NULL; } /* make a callback interface */ pNew->pCall = CreateCallBackInterface(); if (!pNew->pCall) { DeleteScanObject(pNew); return NULL; } /* assign various things */ if (pRecover) { strlcpy(pNew->pRecover, pRecover,1024); } else { memset(pNew->pRecover,0,sizeof(pNew->pRecover)); } if (pHeader) { strlcpy(pNew->pHeaderFile, pHeader,1024); } pNew->iMode = eTimer; pNew->fPreset = 10.; strlcpy(pNew->pCounterName, pCount->name,511); pNew->pCounterData = pCount; pNew->PrepareScan = PrepareScan; pNew->WriteHeader = WriteHeader; pNew->WriteScanPoints = WriteScanPoints; pNew->ScanDrive = ScanDrive; pNew->ScanCount = ScanCount; pNew->CollectScanData = CollectScanData; pNew->iWindow = 6; strlcpy(pNew->objectName, objName, 131); ConfigureScanDict(pNew->scanFunctions); return pNew; } /*---------------------------------------------------------------------------*/ void DeleteScanObject(void *pData) { pScanData self = NULL; self = (pScanData) pData; if (!self) { return; } if (self->pDes) { DeleteDescriptor(self->pDes); } if (self->pCall) { DeleteCallBackInterface(self->pCall); } if (self->pScanVar) { DeleteDynar(self->pScanVar); } if (self->pCounts) { DeleteDynar(self->pCounts); } if (self->pCommand) { free(self->pCommand); } if (self->scanFunctions) { DeleteStringDict(self->scanFunctions); } free(self); } /*------------------------------------------------------------------------*/ int ResetScanFunctions(pScanData self) { assert(self); self->PrepareScan = PrepareScan; self->WriteHeader = WriteHeader; self->WriteScanPoints = WriteScanPoints; self->ScanDrive = ScanDrive; self->ScanCount = ScanCount; self->CollectScanData = CollectScanData; return 1; } /*-------------------------------------------------------------------------*/ int AddScanVar(pScanData self, SicsInterp * pSics, SConnection * pCon, char *name, float fStart, float fStep) { pVarEntry pVar = NULL; if (self->iActive) { SCWrite(pCon, "ERROR: cannot change parameters while scan is running", eError); return 0; } pVar = MakeScanVar(pSics, pCon, name, fStart, fStep); if (pVar == NULL) { return 0; } /* put it away */ DynarPut(self->pScanVar, self->iScanVar, pVar); self->iScanVar++; return 1; } /*-------------------------------------------------------------------------*/ int AddLogVar(pScanData self, SicsInterp * pSics, SConnection * pCon, char *name) { pVarEntry pVar = NULL; if (self->iActive) { SCWrite(pCon, "ERROR: cannot change parameters while scan is running", eError); return 0; } pVar = MakeLogVar(pSics, pCon, name); if (pVar == NULL) { return 0; } /* put it away */ DynarPut(self->pScanVar, self->iScanVar, pVar); self->iScanVar++; return 1; } /*--------------------------------------------------------------------------*/ int ClearScanVar(pScanData self) { if (self->iActive) { return 0; } self->iScanVar = 0; return 1; } /*--------------------------------------------------------------------------*/ static int WriteRecover(pScanData self) { FILE *fd; pVarEntry pVar = NULL; void *pData = NULL; pCountEntry pCount = NULL; int i, j, status; fd = fopen(self->pRecover, "w"); if (!fd) { return 0; } fprintf(fd, "%s clear\n", self->objectName); /* write scan vars */ for (i = 0; i < self->iScanVar; i++) { DynarGet(self->pScanVar, i, &pData); pVar = (pVarEntry) pData; if (pVar) { if (isLogVar(pVar)) { fprintf(fd, "%s log %s\n", self->objectName, ScanVarName(pVar)); } else { fprintf(fd, "%s add %s %f %f\n", self->objectName, ScanVarName(pVar), ScanVarStart(pVar), ScanVarStep(pVar)); } } pData = NULL; } for (i = 0; i < self->iScanVar; i++) { DynarGet(self->pScanVar, i, &pData); pVar = (pVarEntry) pData; if (pVar) { status = LLDnodePtr2First(pVar->dataList); while (status != 0) { fprintf(fd, "%s appendvarpos %d %f\n", self->objectName, i, LLDnodeFloat(pVar->dataList)); status = LLDnodePtr2Next(pVar->dataList); } } pData = NULL; } /* write counts */ for (i = 0; i < self->iCounts; i++) { DynarGet(self->pCounts, i, &pData); pCount = (pCountEntry) pData; if (pCount != NULL) { fprintf(fd, "%s storecounts %ld %f %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n", self->objectName, pCount->lCount, pCount->fTime, pCount->Monitors[0], pCount->Monitors[1], pCount->Monitors[2], pCount->Monitors[3], pCount->Monitors[4], pCount->Monitors[5], pCount->Monitors[6], pCount->Monitors[7], pCount->Monitors[8], pCount->Monitors[9]); } } if (self->iMode == eTimer) { fprintf(fd, "%s continue %d timer %f\n", self->objectName, self->iNP, self->fPreset); } else { fprintf(fd, "%s continue %d monitor %f\n", self->objectName, self->iNP, self->fPreset); } fclose(fd); return 1; } /*-------------------------------------------------------------------------*/ int AppendScanLine(pScanData self, char *line) { /* reopen file */ self->fd = fopen(self->pFile, "r+"); if (!self->fd) { SCWrite(self->pCon, "ERROR: Failed to reopen scan file, aborting scan", eError); return 0; } /* jump to end of file */ fseek(self->fd, 0, SEEK_END); /* print */ fprintf(self->fd, "%s\n", line); /* done */ fclose(self->fd); self->fd = NULL; return 1; } /*-------------------------------------------------------------------------*/ extern char *stptok(const char *s, char *t, int len, char *brk); extern char *trim(char *txt); int StoreScanCounts(pScanData self, char *data) { CountEntry sCount; char pNumber[30], *pPtr; int iCount = 0; char pBueffel[256]; if (data == NULL) { SCWrite(self->pCon, "WARNING: StoreScanCounts called without data", eLog); return 1; } InitCountEntry(&sCount); /* parse the data */ pPtr = trim(data); pPtr = stptok(pPtr, pNumber, 29, " \t"); if (pPtr != NULL) { sCount.lCount = atoi(pNumber); } else { SCWrite(self->pCon, "WARNING: No data in StoreScanCounts", eLog); snprintf(pBueffel, 255, "Received: %s", data); SCWrite(self->pCon, pBueffel, eLog); return 1; } pPtr = stptok(pPtr, pNumber, 29, " \t"); if (pPtr != NULL) { sCount.fTime = atof(pNumber); } if (pPtr == NULL) { return 1; } while ((pPtr = stptok(pPtr, pNumber, 29, " \t")) != NULL) { sCount.Monitors[iCount] = atoi(pNumber); iCount++; if (iCount >= 10) { SCWrite(self->pCon, "ERROR: I have only space for 10 Monitors in count structure", eLogError); return 0; } } sCount.i = self->iCounts; DynarReplace(self->pCounts, self->iCounts, &sCount, sizeof(CountEntry)); self->iCounts++; if (self->iCounts > self->iNP) { self->iNP++; } return 1; } /*-----------------------------------------------------------------------*/ CountEntry CollectCounterData(pScanData self) { int i, iRet; CountEntry sCount; char *pAns = NULL, *pPtr = NULL; Tcl_Interp *pTcl; float fVal; InitCountEntry(&sCount); /* monitors */ for (i = 1; i < 10; i++) { sCount.Monitors[i - 1] = GetMonitor((pCounter) self->pCounterData, i, self->pCon); } if (self->iChannel != 0 && self->iChannel != -10) { sCount.Monitors[self->iChannel - 1] = GetCounts((pCounter) self->pCounterData, self->pCon); } /* counts, depending on iChannel */ if (self->iChannel == -10) { /* execute the Tcl-script for getting the data */ pTcl = InterpGetTcl(self->pSics); if (!self->pCommand) { SCWrite(self->pCon, "ERROR: command must be configured for user defined scans", eError); SCSetInterrupt(self->pCon, eAbortBatch); return sCount; } iRet = Tcl_Eval(pTcl, self->pCommand); if (iRet != TCL_OK) { SCWrite(self->pCon, pTcl->result, eLogError); return sCount; } /* interprete the Tcl result as a list of counts WARNING: this may need to be changed when switching to future versions of Tcl */ pAns = strdup(pTcl->result); pPtr = strtok(pAns, " "); if (!pPtr) { SCWrite(self->pCon, "ERROR: no counts found in Tcl-result", eLogError); } sscanf(pPtr, "%f", &fVal); sCount.lCount = (long) fVal; i = 0; while ((pPtr != NULL) && (i < 10)) { pPtr = strtok(NULL, " "); if (pPtr) { sscanf(pPtr, "%f", &fVal); sCount.Monitors[i] = (long) fVal; i++; } } free(pAns); } else if (self->iChannel == 0) { sCount.lCount = GetCounts((pCounter) self->pCounterData, self->pCon); } else { sCount.lCount = GetMonitor((pCounter) self->pCounterData, self->iChannel, self->pCon); } /* get time */ sCount.fTime = GetCountTime((pCounter) self->pCounterData, self->pCon); /* stow away */ DynarReplace(self->pCounts, self->iCounts, &sCount, sizeof(CountEntry)); self->iCounts++; if (self->iCounts > self->iNP) { self->iNP++; } return sCount; } /*---------------------------------------------------------------------------*/ static int ScanLoop(pScanData self) { int i, iInt, iRet, iStatus, iHeaderWritten = 0; assert(self); assert(self->pCon); InvokeCallBack(self->pCall, SCANSTART, self); for (i = self->iCounts; i < self->iNP; i++) { /*--------- drive */ iRet = self->ScanDrive(self, i); /* finished, check for interrupts. Whatever happened, user interrupt or HW interrupt, it will be on our connection */ iInt = SCGetInterrupt(self->pCon); switch (iInt) { case eContinue: break; case eAbortOperation: SCSetInterrupt(self->pCon, eContinue); SCWrite(self->pCon, "WARNING: skipped scan point due to motor failure", eLog); continue; break; case eAbortScan: SCWrite(self->pCon, "ERROR: Scan aborted", eLogError); /* eat the interrupt, the requested op has been done */ SCSetInterrupt(self->pCon, eContinue); return 0; break; default: /* all others */ SCWrite(self->pCon, "ERROR: Scan aborted", eLogError); return 0; break; } if (!iRet) { SCWrite(self->pCon, "WARNING: skipped scan point after drive failure", eLog); continue; } if(iHeaderWritten == 0) { iRet = self->WriteHeader(self); iHeaderWritten++; if (!iRet) { SCWrite(self->pCon, "ERROR: cannot open data file, Scan aborted", eError); self->pCon = NULL; self->pSics = NULL; return 0; } } /*-------------- count */ iRet = self->ScanCount(self, i); /* finished, check for interrupts. Whatever happened, user interrupt or HW interrupt, it will be on our connection */ iInt = SCGetInterrupt(self->pCon); switch (iInt) { case eContinue: break; case eAbortOperation: continue; break; case eAbortScan: SCWrite(self->pCon, "ERROR: Scan aborted", eLogError); /* eat the interrupt, the requested op has been done */ SCSetInterrupt(self->pCon, eContinue); return 0; break; default: /* all others */ SCWrite(self->pCon, "ERROR: Scan aborted", eLogError); return 0; break; } if (!iRet) { SCWrite(self->pCon, "WARNING: skipped scan point after count failure", eLog); continue; } /*-------- scan post processing */ self->CollectScanData(self, i); InvokeCallBack(self->pCall, SCANPOINT, self); self->WriteScanPoints(self, i); if (strlen(self->pRecover) > 10) { WriteRecover(self); } } return 1; } /*--------------------------------------------------------------------------*/ int DoScan(pScanData self, int iNP, int iMode, float fPreset, SicsInterp * pSics, SConnection * pCon) { int iRet; char *pPtr = NULL; char pBueffel[1024]; assert(self); assert(pCon); assert(pSics); self->pCon = pCon; self->pSics = pSics; /* check arguments */ if (iNP <= 0) { SCWrite(self->pCon, "ERROR: iNP < 0, nothing to do, Scan aborted", eError); self->pCon = NULL; self->pSics = NULL; return 0; } if (self->iScanVar <= 0) { SCWrite(self->pCon, "WARNING: no scan variables given", eWarning); } if ((iMode != eTimer) && (iMode != ePreset)) { SCWrite(self->pCon, "ERROR: Invalid counter mode given", eError); self->pCon = NULL; self->pSics = NULL; return 0; } if (self->iActive != 0) { SCWrite(pCon, "ERROR: another scan is still running", eError); self->pCon = NULL; self->pSics = NULL; return 0; } self->iActive = 1; self->iNP = iNP; self->iMode = iMode; self->fPreset = fPreset; /* do some preprocessing */ if (self->PrepareScan != NULL) { iRet = self->PrepareScan(self); } else { iRet = 1; } if (!iRet) { self->pCon = NULL; self->pSics = NULL; self->iActive = 0; return 0; } iRet = ScanLoop(self); if(self->pCon != NULL && self->pSics != NULL){ ScriptScanFinish(self); } InvokeCallBack(self->pCall, SCANEND, self); SendQuieck(QUIECK, self->pFile); self->iActive = 0; self->pCon = NULL; self->pSics = NULL; return iRet; } /*---------------------------------------------------------------------------- SilentScan does a scan which does not produce a data file. It is intended for internal use. Only status messages appear on screen. ---------------------------------------------------------------------------*/ int SilentScan(pScanData self, int iNP, int iMode, float fPreset, SicsInterp * pSics, SConnection * pCon) { int iRet; char *pPtr = NULL; char pBueffel[1024]; int (*HeaderFunc) (pScanData self), (*ScanFunc) (pScanData self, int iPoint); assert(self); assert(pCon); assert(pSics); /* check arguments */ if (iNP <= 0) { SCWrite(self->pCon, "ERROR: iNP < 0, nothing to do, Scan aborted", eError); return 0; } if (self->iScanVar <= 0) { SCWrite(self->pCon, "WARNING: no scan variables given", eWarning); } if ((iMode != eTimer) && (iMode != ePreset)) { SCWrite(self->pCon, "ERROR: Invalid counter mode given", eError); return 0; } if (self->iActive != 0) { SCWrite(pCon, "ERROR: another scan is still running", eError); self->pCon = NULL; self->pSics = NULL; return 0; } HeaderFunc = self->WriteHeader; self->WriteHeader = DummyWrite; ScanFunc = self->WriteScanPoints; self->WriteScanPoints = DummyWrite2; self->pCon = pCon; self->pSics = pSics; self->iNP = iNP; self->iMode = iMode; self->fPreset = fPreset; /* do some preprocessing */ iRet = SilentPrepare(self); if (!iRet) { self->WriteHeader = HeaderFunc; self->WriteScanPoints = ScanFunc; self->pCon = NULL; self->pSics = NULL; return 0; } self->iActive = 1; iRet = ScanLoop(self); self->iActive = 0; self->pCon = NULL; self->pSics = NULL; self->WriteHeader = HeaderFunc; self->WriteScanPoints = ScanFunc; return iRet; } /*--------------------------------------------------------------------------*/ int ContinueScan(pScanData self, SicsInterp * pSics, SConnection * pCon, int argc, char *argv[]) { int iRet; char *pPtr = NULL, pBueffel[512]; double dVal; assert(pSics); assert(pCon); self->pCon = pCon; self->pSics = pSics; if (argc < 5) { SCWrite(pCon, "ERROR: not enough arguments to scan continue", eError); return 0; } /* get NP */ iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &self->iNP); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } /* interpret Mode */ if (strcmp(argv[3], "timer") == 0) { self->iMode = eTimer; } else if (strcmp(argv[3], "monitor") == 0) { self->iMode = ePreset; } else { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not recognized as valid counter mode", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } /* preset */ iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[4], &dVal); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } self->fPreset = dVal; /* configure counter */ SetCounterMode((pCounter) self->pCounterData, self->iMode); SetCounterPreset((pCounter) self->pCounterData, self->fPreset); /* new scan data file */ pPtr = ScanMakeFileName(self->pSics, self->pCon); if (!pPtr) { SCWrite(self->pCon, "ERROR: cannot allocate new data filename, Scan aborted", eError); self->pCon = NULL; self->pSics = NULL; return 0; } snprintf(pBueffel,sizeof(pBueffel)-1, "Writing data file: %s ...", pPtr); SCWrite(self->pCon, pBueffel, eWarning); strlcpy(self->pFile, pPtr,1023); free(pPtr); iRet = self->WriteHeader(self); if (!iRet) { SCWrite(self->pCon, "ERROR: cannot open data file, Scan aborted", eError); self->pCon = NULL; self->pSics = NULL; return 0; } self->iActive = 1; iRet = ScanLoop(self); ScriptScanFinish(self); InvokeCallBack(self->pCall, SCANEND, self); SendQuieck(QUIECK, self->pFile); self->iActive = 0; self->pCon = NULL; self->pSics = NULL; return iRet; } /*--------------------------------------------------------------------------*/ int GetScanNP(pScanData self) { assert(self); return self->iNP; } /*--------------------------------------------------------------------------*/ float GetScanPreset(pScanData self) { assert(self); return self->fPreset; } /*--------------------------------------------------------------------------*/ int GetScanCounts(pScanData self, long *lData, int iDataLen) { int i, iEnd; pCountEntry pData = NULL; void *pPtr = NULL; assert(self); /* hanlde iEnd */ if (self->iCounts < iDataLen) { iEnd = self->iCounts; } else { iEnd = iDataLen; } /* initialise to 0 */ memset(lData, 0, iDataLen * sizeof(long)); /* the loop */ for (i = 0; i < iEnd; i++) { DynarGet(self->pCounts, i, &pPtr); pData = (pCountEntry) pPtr; if (pData) { lData[i] = pData->lCount; } pData = NULL; } return 1; } /*--------------------------------------------------------------------------*/ int GetScanMonitor(pScanData self, int iWhich, long *lData, int iDataLen) { int i, iEnd; pCountEntry pData = NULL; void *pPtr = NULL; assert(self); /* hanlde iEnd */ if (self->iCounts < iDataLen) { iEnd = self->iCounts; } else { iEnd = iDataLen; } /* initialise to 0 */ memset(lData, 0, iDataLen * sizeof(long)); /* the loop */ for (i = 0; i < iEnd; i++) { DynarGet(self->pCounts, i, &pPtr); pData = (pCountEntry) pPtr; if (pData) { lData[i] = pData->Monitors[iWhich]; } pData = NULL; } return 1; } /*--------------------------------------------------------------------------*/ int GetScanVar(pScanData self, int iWhich, float *fData, int iDataLen) { int iEnd, i; pVarEntry pVar = NULL; void *pPtr = NULL; /* does it exist ? */ if ((iWhich < 0) || (iWhich >= self->iScanVar)) { return 0; } /* handle iEnd */ if (self->iCounts < iDataLen) { iEnd = self->iCounts; } else { iEnd = iDataLen; } DynarGet(self->pScanVar, iWhich, &pPtr); pVar = (pVarEntry) pPtr; if (pVar) { /* initialise to theoretical values */ for (i = 0; i < self->iNP; i++) { fData[i] = pVar->fStart + i * pVar->fStep; } CopyScanVar(pVar, fData, self->iNP); return 1; } else { return 0; } /* not reached */ assert(0); } /*--------------------------------------------------------------------------*/ int GetSoftScanVar(pScanData self, int iWhich, float *fData, int iDataLen) { int iEnd, i; pVarEntry pVar = NULL; void *pPtr = NULL; /* does it exist ? */ if ((iWhich < 0) || (iWhich >= self->iScanVar)) { return 0; } /* handle iEnd */ if (self->iCounts < iDataLen) { iEnd = self->iCounts; } else { iEnd = iDataLen; } DynarGet(self->pScanVar, iWhich, &pPtr); pVar = (pVarEntry) pPtr; if (pVar) { /* initialise to theoretical values */ for (i = 0; i < self->iNP; i++) { fData[i] = pVar->fStart + i * pVar->fStep; } return 1; } else { return 0; } /* not reached */ assert(0); } /*-------------------------------------------------------------------------*/ int GetScanVarName(pScanData self, int iWhich, char *pName, int iLength) { pVarEntry pVar = NULL; void *pPtr = NULL; /* does it exist ? */ if ((iWhich < 0) || (iWhich >= self->iScanVar)) { return 0; } /* get the scan var */ DynarGet(self->pScanVar, iWhich, &pPtr); pVar = (pVarEntry) pPtr; if (pVar) { strlcpy(pName, ScanVarName(pVar), iLength); return 1; } else { return 0; } } /*---------------------------------------------------------------------*/ int isScanRunning(pScanData self) { return self->iActive; } /*---------------------------------------------------------------------*/ int GetScanVarStep(pScanData self, int iWhich, float *fStep) { pVarEntry pVar = NULL; void *pPtr = NULL; /* does it exist ? */ if ((iWhich < 0) || (iWhich >= self->iScanVar)) { return 0; } /* get the scan var */ DynarGet(self->pScanVar, iWhich, &pPtr); pVar = (pVarEntry) pPtr; if (pVar) { *fStep = ScanVarStep(pVar); return 1; } else { return 0; } } /*-------------------------------------------------------------------------- ScanIntegrate does an integration of the current scan data. It returns 1 on success or one of the integrate error codes defined in integrate.h -----------------------------------------------------------------------------*/ int ScanIntegrate(pScanData self, float *fSum, float *fVar) { long *lData = NULL; int iRet; assert(self); /* no integration if no peak measured */ if (self->iCounts <= self->iWindow * 2) return INTEGNOPEAK; /* get some memory */ lData = (long *) malloc(self->iNP * sizeof(long)); if (!lData) { return INTEGNOPEAK; } /* get counts */ GetScanCounts(self, lData, self->iNP); /* Do it */ iRet = GabePeakIntegrate(self->iWindow, self->iNP, lData, fSum, fVar); free(lData); return iRet; } /*-------------------------------------------------------------------------- SimScan is a debugging aid for other modules. It simulates a scan on a variable in the range from 10 -20 degrees in angle and 100 points. Data is created as a Gauss function located at fPos, with a halfwidth of FWHM and a height of fHeight. All data is randomized a little in a range of 5 counts. The peak will sit on a background of 20 counts. This requires a motor a4 to exist as it will be used for x-axis simulation. This routine will not stop you from simulating shit if you throw shit at it! ----------------------------------------------------------------------------*/ int SimScan(pScanData self, float fPos, float FWHM, float fHeight) { int i, iRet; SConnection *pCon = NULL; CountEntry sCount; pVarEntry pVar = NULL; void *pDings = NULL; float x, y, fTmp, fStdDev; assert(self); InitCountEntry(&sCount); /* go to a clean state */ ClearScanVar(self); /* put in the scan variable */ pCon = SCCreateDummyConnection(pServ->pSics); if (!pCon) { return 0; } iRet = AddScanVar(self, pServ->pSics, pCon, "a4", 10., 0.1); SCDeleteConnection(pCon); if (!iRet) { return 0; } /* do the x-axis of the scan */ DynarGet(self->pScanVar, 0, &pDings); pVar = (pVarEntry) pDings; if (!pVar) { return 0; } /* create scan data in loop */ fStdDev = FWHM / 2.354; for (i = 0; i < 90; i++) { x = 10. + 0.1 * i; AppendScanVar(pVar, x); sCount.i = i; /* gaussian */ fTmp = (x - fPos) / fStdDev; y = fHeight * 0.4 * exp(-0.5 * fTmp * fTmp); /* randomize a little */ y += 7. * (float) rand() / (float) RAND_MAX; /* add a little background */ sCount.lCount = (long) (10 + y); /* stow away */ DynarReplace(self->pCounts, i, &sCount, sizeof(CountEntry)); } self->iCounts = 90; self->iNP = 90; return 1; } /*---------------------------------------------------------------------------*/ int ScanFactory(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { pScanData pNew = NULL; pCounter pCount = NULL; pDummy pDum = NULL; CommandList *pCom = NULL; char pBueffel[512]; int iRet; if (argc < 5) { SCWrite(pCon, "ERROR: Insufficient number of arguments to ScanFactory", eError); return 0; } strtolower(argv[1]); strtolower(argv[2]); pCom = FindCommand(pSics, argv[2]); if (!pCom) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: cannot find counter %s", argv[2]); SCWrite(pCon, pBueffel, eError); return 0; } pDum = (pDummy) pCom->pData; if (!pDum) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: counter %s has no data", argv[2]); SCWrite(pCon, pBueffel, eError); return 0; } if (!(pDum->pDescriptor->GetInterface(pDum, COUNTID))) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: object %s is NO counter", argv[2]); SCWrite(pCon, pBueffel, eError); return 0; } pNew = CreateScanObject(argv[4], argv[3], (pCounter) pCom->pData, argv[1]); if (!pNew) { SCWrite(pCon, "ERROR: failure to allocate scan data structure", eError); return 0; } iRet = AddCommand(pSics, argv[1], ScanWrapper, DeleteScanObject, pNew); if (!iRet) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: duplicate command %s not created", argv[1]); SCWrite(pCon, pBueffel, eError); return 0; } /* ignore this one, this is cheaper then checking for the existence of another scan object */ AddCommand(pSics, "stdscan", StandardScanWrapper, NULL, NULL); return 1; } /*--------------------------------------------------------------------------*/ static int ScanInterest(int iEvent, void *pEventData, void *pUser) { pScanData self = NULL; SConnection *pCon = NULL; char *pPtr = NULL, pItem[20]; long *lData = NULL; int i; writeFunc oldWrite; self = (pScanData) pEventData; pCon = (SConnection *) pUser; assert(self); assert(pCon); if (!SCisConnected(pCon)) { return -1; } if (iEvent == SCANSTART) { SCWrite(pCon, "NewScan", eEvent); return 1; } else if (iEvent == SCANEND) { SCWrite(pCon, "ScanEnd", eEvent); return 1; } else if (iEvent == SCANPOINT) { /* allocate space */ pPtr = (char *) malloc((self->iNP * 20 + 20) * sizeof(char)); if (!pPtr) { return 0; } memset(pPtr, 0, (self->iNP * 20 + 20) * sizeof(char)); lData = (long *) malloc(self->iNP * sizeof(long)); if (!lData) { return 0; } memset(lData, 0, self->iNP * sizeof(long)); /* get counts */ GetScanCounts(self, lData, self->iNP); /* format a message */ strcpy(pPtr, "scan.Counts= {"); for (i = 0; i < self->iNP; i++) { snprintf(pItem,sizeof(pItem)-1, "%ld ", lData[i]); strcat(pPtr, pItem); } strcat(pPtr, "}"); oldWrite = SCGetWriteFunc(pCon); SCSetWriteFunc(pCon, SCOnlySockWrite); SCWrite(pCon, pPtr, eEvent); SCSetWriteFunc(pCon, oldWrite); free(lData); free(pPtr); return 1; } return 1; } /*--------------------------------------------------------------------------*/ static int ScanDynInterest(int iEvent, void *pEventData, void *pUser) { pScanData self = NULL; SConnection *pCon = NULL; void *pPtr; pVarEntry pVar; pCountEntry pCount = NULL; float fVal; long lVal; int i; char pBueffel[256]; self = (pScanData) pEventData; pCon = (SConnection *) pUser; assert(self); assert(pCon); if (!SCisConnected(pCon)) { return -1; } if (iEvent == SCANSTART) { SCWrite(pCon, "NewScan", eEvent); return 1; } else if (iEvent == SCANEND) { SCWrite(pCon, "ScanEnd", eEvent); return 1; } else if (iEvent == SCANPOINT) { i = self->iCounts - 1; DynarGet(self->pScanVar, 0, &pPtr); pVar = (pVarEntry) pPtr; if (pVar != NULL) { fVal = GetScanVarPos(pVar, i); } else { fVal = -9999.99; } DynarGet(self->pCounts, i, &pPtr); pCount = (pCountEntry) pPtr; if (pCount != NULL) { lVal = pCount->lCount; } else { lVal = -9999; } snprintf(pBueffel, 255, "%s.scanpoint = {%d %f %ld}", self->objectName, i, fVal, lVal); SCWrite(pCon, pBueffel, eEvent); } return 1; } /*--------------------------------------------------------------------------*/ static int ScanUUInterest(int iEvent, void *pEventData, void *pUser) { pScanData self = NULL; SConnection *pCon = NULL, *comCon = NULL; char pItem[20]; long *lData = NULL; int *iData = NULL; int i; self = (pScanData) pEventData; pCon = (SConnection *) pUser; assert(self); assert(pCon); /* printf("ScanUUInterest called for pCon = %p handle %d\n", pCon, SCGetSockHandle(pCon)); */ if (!SCisConnected(pCon)) { return -1; } if (iEvent == SCANSTART) { SCWrite(pCon, "NewScan", eEvent); return 1; } else if (iEvent == SCANEND) { SCWrite(pCon, "ScanEnd", eEvent); return 1; } else if (iEvent == SCANPOINT) { /* allocate space */ lData = (long *) malloc(self->iNP * sizeof(long)); iData = (int *) malloc(self->iNP * sizeof(int)); if (!lData || !iData) { return 0; } memset(lData, 0, self->iNP * sizeof(long)); memset(iData, 0, self->iNP * sizeof(int)); /* get counts */ GetScanCounts(self, lData, self->iNP); /* put into network byte order */ for (i = 0; i < self->iNP; i++) { iData[i] = htonl((int) lData[i]); } SCWriteUUencoded(pCon, "ScanData", iData, self->iNP * sizeof(int)); free(lData); free(iData); return 1; } return 1; } /*--------------------------------------------------------------------------*/ static int GetVarPar(SConnection * pCon, pScanData self, char *scanname, int i) { char pBueffel[512]; void *pPtr = NULL; pVarEntry pVar = NULL; assert(pCon); assert(self); if (i < 0 || i >= self->iScanVar) { SCWrite(pCon, "ERROR: scan variable number out of range", eError); return 0; } DynarGet(self->pScanVar, i, &pPtr); pVar = (pVarEntry) pPtr; if (pVar != NULL) { snprintf(pBueffel, 511, "%s.%s = %f = %f", scanname, ScanVarName(pVar), ScanVarStart(pVar), ScanVarStep(pVar)); SCWrite(pCon, pBueffel, eValue); return 1; } return 0; } /*--------------------------------------------------------------------------*/ static int AppendVarPos(SConnection * pCon, pScanData self, int scanVar, float fPos) { char pBueffel[512]; void *pPtr = NULL; pVarEntry pVar = NULL; assert(pCon); assert(self); if (scanVar < 0 || scanVar >= self->iScanVar) { SCWrite(pCon, "ERROR: scan variable number out of range", eError); return 0; } DynarGet(self->pScanVar, scanVar, &pPtr); pVar = (pVarEntry) pPtr; if (pVar != NULL) { AppendScanVar(pVar, fPos); return 1; } return 0; } /*--------------------------------------------------------------------------*/ static void PrintScanVars(pScanData self, char *scanname, SConnection * pCon) { char pBueffel[1024]; pVarEntry pVar = NULL; void *pPtr = NULL; int i; assert(pCon); assert(self); snprintf(pBueffel, sizeof pBueffel, "%s.scanvars = { ", scanname); for (i = 0; i < self->iScanVar; i++) { DynarGet(self->pScanVar, i, &pPtr); pVar = (pVarEntry) pPtr; if (pVar != NULL) { strlcat(pBueffel, ScanVarName(pVar), sizeof pBueffel); strlcat(pBueffel, " ", sizeof pBueffel); } } strlcat(pBueffel, "}", sizeof pBueffel); SCWrite(pCon, pBueffel, eValue); } /*--------------------------------------------------------------------------*/ static int PrintCountsOrMonitors(pScanData self, SConnection * pCon, char *name, int iWhich) { pDynString data = NULL; long *lData = NULL; char pBueffel[60]; int i; if (self->iNP < 1) { SCWrite(pCon, "ERROR: no scan data available", eError); return 0; } data = CreateDynString(80, 80); lData = (long *) malloc(self->iNP * sizeof(long)); if (data == NULL || lData == NULL) { SCWrite(pCon, "ERROR: out of memory printing counts", eError); return 0; } memset(lData, 0, self->iNP * sizeof(long)); if (iWhich < 0) { GetScanCounts(self, lData, self->iNP); snprintf(pBueffel, 59, "%s.Counts = {", name); } else { GetScanMonitor(self, iWhich, lData, self->iNP); snprintf(pBueffel, 59, "%s.mon%2.2d = {", name, iWhich); } DynStringCopy(data, pBueffel); for (i = 0; i < self->iNP; i++) { snprintf(pBueffel, 59, " %ld", lData[i]); DynStringConcat(data, pBueffel); } DynStringConcatChar(data, '}'); SCWrite(pCon, GetCharArray(data), eValue); DeleteDynString(data); free(lData); return 1; } /*--------------------------------------------------------------------------*/ static int PrintTimes(pScanData self, SConnection * pCon, char *name) { pDynString data = NULL; char pBueffel[60]; int i, iEnd; pCountEntry pData = NULL; void *pPtr = NULL; if (self->iNP < 1) { SCWrite(pCon, "ERROR: no scan data available", eError); return 0; } data = CreateDynString(80, 80); if (data == NULL) { SCWrite(pCon, "ERROR: out of memory printing counts", eError); return 0; } snprintf(pBueffel, 59, "%s.scantimes = { ", name); DynStringCopy(data, pBueffel); for (i = 0; i < self->iCounts; i++) { DynarGet(self->pCounts, i, &pPtr); pData = (pCountEntry) pPtr; if (pData) { snprintf(pBueffel, 59, " %f", pData->fTime); DynStringConcat(data, pBueffel); } } DynStringConcatChar(data, '}'); SCWrite(pCon, GetCharArray(data), eValue); DeleteDynString(data); return 1; } /*------------------------------------------------------------------------*/ static int ScanInvokeCallback(pScanData self, SConnection * pCon, char *name) { int eventID; if (strcmp(name, "scanstart") == 0) { eventID = SCANSTART; } else if (strcmp(name, "scanpoint") == 0) { eventID = SCANPOINT; } else if (strcmp(name, "scanend") == 0) { eventID = SCANEND; } else { SCWrite(pCon, "ERROR: callback ID not recognised", eError); return 0; } InvokeCallBack(self->pCall, eventID, self); SCSendOK(pCon); return 1; } /*-----------------------------------------------------------------------*/ static void ListScanFunctions(pScanData self, SConnection * pCon) { pDynString result = NULL; char pValue[256], *pPtr = NULL; result = CreateDynString(80, 80); if (result == NULL) { SCWrite(pCon, "ERROR: failed to allocate memory in function list", eError); return; } while ((pPtr = (char *) StringDictGetNext(self->scanFunctions, pValue, 255)) != NULL) { DynStringConcat(result, pPtr); DynStringConcat(result, " = "); DynStringConcat(result, pValue); DynStringConcatChar(result, '\n'); } SCWrite(pCon, GetCharArray(result), eValue); DeleteDynString(result); } /*-------------------------------------------------------------------------*/ static int InterpretScanFunctions(pScanData self, SConnection * pCon, int argc, char *argv[]) { char pValue[256]; char response[512]; if (argc < 3) { SCWrite(pCon, "ERROR: need subcommand to scan function", eError); return 0; } strtolower(argv[2]); if (strcmp(argv[2], "list") == 0) { ListScanFunctions(self, pCon); return 1; } if (argc > 3) { /* set case */ Arg2Text(argc - 3, &argv[3], pValue, 255); if (!StringDictUpdate(self->scanFunctions, argv[2], pValue)) { snprintf(pValue, 255, "ERROR: scan function %s not found", argv[2]); SCWrite(pCon, pValue, eError); return 0; } } /* request case */ if (StringDictGet(self->scanFunctions, argv[2], pValue, 255)) { snprintf(response, 511, "%s function %s = %s", argv[0], argv[2], pValue); SCWrite(pCon, response, eValue); return 1; } else { snprintf(pValue, 255, "ERROR: scan function %s not found", argv[2]); SCWrite(pCon, pValue, eError); return 0; } return 0; } /*--------------------------------------------------------------------------*/ static int DumpScan(pScanData self, SConnection * pCon) { int i; SConnection *oldCon; char pFile[1024]; if (self->iActive) { SCWrite(pCon, "ERROR: cannot dump scan while running", eError); return 0; } if (!self->pSics) { self->pSics = pServ->pSics; } /* * save old file etc status */ oldCon = self->pCon; pFile[0] = '\0'; strlcpy(pFile, self->pFile, 1023); prepareDataFile(self); self->pCon = pCon; self->WriteHeader(self); for (i = 0; i < self->iNP; i++) { self->WriteScanPoints(self, i); } SCWrite(pCon, "Scan dumped", eValue); self->pCon = oldCon; strlcpy(self->pFile, pFile, 1023); return 1; } /*---------------------------------------------------------------------------*/ int ScanWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { pScanData self = NULL; char pBueffel[512]; double fStep, fStart, fPreset; float *fData = NULL; int lNP; int iChannel; int iRet = 0, iMode, i; char *pPtr = NULL, pItem[20]; long *lData = NULL, lID; int *iData; void *pVarData = NULL; pVarEntry pVar = NULL; float fSum, fVar; double x; float fPos, FWHM, fHeight; pSite site = NULL; SConnection *conSave; self = (pScanData) pData; assert(self); argtolower(argc, argv); if (argc < 2) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: not enough arguments for %s", argv[0]); SCWrite(pCon, pBueffel, eError); return 0; } /* first interpret commands which do not require user rights */ /*---------- getfile */ if (strcmp(argv[1], "getfile") == 0) { snprintf(pBueffel,sizeof(pBueffel)-1, "scan.File = %s", self->pFile); SCWrite(pCon, pBueffel, eValue); return 1; } if (strcmp(argv[1], "getscanvars") == 0) { PrintScanVars(self, argv[0], pCon); return 1; } /*--------- getcounts */ else if (strcmp(argv[1], "getcounts") == 0) { return PrintCountsOrMonitors(self, pCon, argv[0], -77); } /*------------ getmonitor */ else if (strcmp(argv[1], "getmonitor") == 0) { if (argc < 3) { SCWrite(pCon, "ERROR: need monitor number to print", eError); return 0; } iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &i); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected integer, got %s", argv[2]); SCWrite(pCon, pBueffel, eError); return 0; } return PrintCountsOrMonitors(self, pCon, argv[0], i); } /*--------- gettimes */ else if (strcmp(argv[1], "gettimes") == 0) { return PrintTimes(self, pCon, argv[0]); } /*---------- uucounts */ else if (strcmp(argv[1], "uucounts") == 0) { /* get some memory */ if (self->iNP < 1) { SCWrite(pCon, "ERROR: no counts available", eError); return 0; } lData = (long *) malloc(self->iNP * sizeof(long)); iData = (int *) malloc((self->iNP + 1) * sizeof(int)); if (!lData || !iData) { SCWrite(pCon, "ERROR: out of memory in scan", eError); return 0; } /* get counts */ GetScanCounts(self, lData, self->iNP); /* copy them */ memset(iData, 0, self->iNP + 1); iData[0] = htonl(self->iNP); for (i = 0; i < self->iNP; i++) { iData[i + 1] = htonl(lData[i]); } SCWriteUUencoded(pCon, "ScanCounts", iData, (self->iNP + 1) * sizeof(int)); return 1; } /*--------- noscanvar */ else if (strcmp(argv[1], "noscanvar") == 0) { snprintf(pBueffel,sizeof(pBueffel)-1, "%s.noscanvar = %d", argv[0], self->iScanVar); SCWrite(pCon, pBueffel, eValue); return 1; } /*-------- NP */ else if (strcmp(argv[1], "np") == 0) { snprintf(pBueffel,sizeof(pBueffel)-1, "%s.nP = %d", argv[0], self->iNP); SCWrite(pCon, pBueffel, eValue); return 1; } /*-------- isactive */ else if (strcmp(argv[1], "isactive") == 0) { snprintf(pBueffel,sizeof(pBueffel)-1, "%s.active = %d", argv[0], self->iActive); SCWrite(pCon, pBueffel, eValue); return 1; } /*--------- getvardata */ else if (strcmp(argv[1], "getvardata") == 0) { /* we need an integer parameter saying which */ if (argc >= 3) { iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &i); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected integer, got %s", argv[2]); SCWrite(pCon, pBueffel, eError); return 0; } } else { SCWrite(pCon, "ERROR: expected number of variable to retrieve data for ", eError); return 0; } /* check the int for validity */ if ((i < 0) || (i >= self->iScanVar)) { SCWrite(pCon, "ERROR: non existent scan variable requested!", eError); return 0; } /* get some memory */ fData = (float *) malloc(self->iNP * sizeof(float)); if (!fData) { SCWrite(pCon, "ERROR: out of memory in scan", eError); return 0; } pPtr = (char *) malloc((self->iNP * 20 + 20) * sizeof(char)); if (!pPtr) { SCWrite(pCon, "ERROR: out of memory in scan", eError); return 0; } memset(pPtr, 0, (self->iNP * 20 + 20) * sizeof(char)); /* get data */ GetScanVar(self, i, fData, self->iNP); /* get name of ScanVar */ DynarGet(self->pScanVar, i, &pVarData); pVar = (pVarEntry) pVarData; if (!pVar) { SCWrite(pCon, "ERROR: Corrupted data structures, inform Programmer", eError); return 0; } /* format them */ sprintf(pPtr, "scan.%s = ", ScanVarName(pVar)); for (i = 0; i < self->iNP; i++) { snprintf(pItem,sizeof(pItem)-1, "{%12.4f} ", fData[i]); strcat(pPtr, pItem); } SCWrite(pCon, pPtr, eValue); free(fData); free(pPtr); return 1; } /*---------getvarpar */ else if (strcmp(argv[1], "getvarpar") == 0) { /* we need an integer parameter saying which */ if (argc >= 3) { iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &i); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected integer, got %s", argv[2]); SCWrite(pCon, pBueffel, eError); return 0; } } else { SCWrite(pCon, "ERROR: expected number of variable to retrieve data for ", eError); return 0; } return GetVarPar(pCon, self, argv[0], i); } /*-------- interest */ else if (strcmp(argv[1], "interest") == 0) { /* printf("Registering scan callbacks on handle %d\n", SCGetSockHandle(pCon)); */ lID = RegisterCallback(self->pCall, SCANSTART, ScanInterest, SCCopyConnection(pCon), SCDeleteConnection); lID = RegisterCallback(self->pCall, SCANEND, ScanInterest, SCCopyConnection(pCon), SCDeleteConnection); lID = RegisterCallback(self->pCall, SCANPOINT, ScanInterest, SCCopyConnection(pCon), SCDeleteConnection); SCSendOK(pCon); return 1; } /*-------- interest */ else if (strcmp(argv[1], "dyninterest") == 0) { /* printf("Registering scanDyn callbacks on handle %d\n", SCGetSockHandle(pCon)); */ lID = RegisterCallback(self->pCall, SCANSTART, ScanDynInterest, SCCopyConnection(pCon), SCDeleteConnection); lID = RegisterCallback(self->pCall, SCANEND, ScanDynInterest, SCCopyConnection(pCon), SCDeleteConnection); lID = RegisterCallback(self->pCall, SCANPOINT, ScanDynInterest, SCCopyConnection(pCon), SCDeleteConnection); SCSendOK(pCon); return 1; } /*-------- uuinterest */ else if (strcmp(argv[1], "uuinterest") == 0) { /* printf("Registering scanUU callbacks on handle %d, con = %p\n", SCGetSockHandle(conSave), conSave); */ lID = RegisterCallback(self->pCall, SCANSTART, ScanUUInterest, SCCopyConnection(pCon), SCDeleteConnection); lID = RegisterCallback(self->pCall, SCANEND, ScanUUInterest, SCCopyConnection(pCon), SCDeleteConnection); lID = RegisterCallback(self->pCall, SCANPOINT, ScanUUInterest, SCCopyConnection(pCon), SCDeleteConnection); SCSendOK(pCon); return 1; } /* ------- uninterest */ else if (strcmp(argv[1], "uninterest") == 0) { RemoveCallbackCon(self->pCall, pCon); SCSendOK(pCon); return 1; } /*------- deal with command needing user rights in all cases */ /* check User Rights */ if (!(SCMatchRights(pCon, usUser))) { SCWrite(pCon, "ERROR: You are NOT authorised to use scan", eError); return 0; } /*---------- add command */ if (strcmp(argv[1], "add") == 0) { if (argc < 5) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Insufficient number of arguments given for %s add", argv[0]); SCWrite(pCon, pBueffel, eError); return 0; } /* get numbers */ iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[3], &fStart); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[4], &fStep); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } iRet = AddScanVar(self, pSics, pCon, argv[2], (float) fStart, (float) fStep); if (iRet) { SCSendOK(pCon); } return iRet; } else if (strcmp(argv[1], "log") == 0) { if (argc < 3) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: Insufficient number of arguments given for %s log", argv[0]); SCWrite(pCon, pBueffel, eError); return 0; } iRet = AddLogVar(self, pSics, pCon, argv[2]); if (iRet) { SCSendOK(pCon); } return iRet; } /* --------clear */ else if (strcmp(argv[1], "clear") == 0) { iRet = ClearScanVar(self); if (iRet) { SCSendOK(pCon); } else { SCWrite(pCon, "ERROR: cannot change parameters while scanning", eError); return 0; } return 1; } /*------------ dump */ else if (strcmp(argv[1], "dump") == 0) { return DumpScan(self, pCon); } /* --------callback */ else if (strcmp(argv[1], "callback") == 0) { if (argc < 3) { SCWrite(pCon, "ERROR: need callback ID for invocation", eError); return 0; } return ScanInvokeCallback(self, pCon, argv[2]); } /*------------ configure */ else if (strcmp(argv[1], "configure") == 0) { if (argc < 3) { SCWrite(pCon, "ERROR: missing configure option", eError); return 0; } /* this is for users only */ if (!SCMatchRights(pCon, usUser)) return 0; strtolower(argv[2]); if (strcmp(argv[2], "standard") == 0) { ResetScanFunctions(self); SCSendOK(pCon); return 1; } else if (strcmp(argv[2], "user") == 0) { ConfigureUserScan(self); SCSendOK(pCon); return 1; } else if (strcmp(argv[2], "script") == 0) { ConfigureScript(self); ResetScanDict(self->scanFunctions); SCSendOK(pCon); return 1; } else { site = getSite(); if (site != NULL) { iRet = site->ConfigureScan(self, argv[2]); } if (!iRet) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: option %s not recognized by configure", argv[2]); SCWrite(pCon, pBueffel, eError); return 0; } else { SCSendOK(pCon); return 1; } } } /*------------ functions */ else if (strcmp(argv[1], "function") == 0) { return InterpretScanFunctions(self, pCon, argc, argv); } /*---------- scan */ else if (strcmp(argv[1], "run") == 0) { if (argc < 5) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: not enough arguments for %s run", argv[0]); SCWrite(pCon, pBueffel, eError); return 0; } /* get NP */ iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &lNP); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[2]); SCWrite(pCon, pBueffel, eError); return 0; } /* interpret Mode */ if (strcmp(argv[3], "timer") == 0) { iMode = eTimer; } else if (strcmp(argv[3], "monitor") == 0) { iMode = ePreset; } else { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not recognized as valid counter mode", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } /* preset */ iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[4], &fPreset); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } iRet = DoScan(self, (int) lNP, iMode, (float) fPreset, pSics, pCon); if (iRet) { SCSendOK(pCon); } return iRet; } /*------------ continue */ else if (strcmp(argv[1], "continue") == 0) { return ContinueScan(self, pSics, pCon, argc, argv); } /*---------- silent */ else if (strcmp(argv[1], "silent") == 0) { if (argc < 5) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: not enough arguments for %s silent", argv[0]); SCWrite(pCon, pBueffel, eError); return 0; } /* get NP */ iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &lNP); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[2]); SCWrite(pCon, pBueffel, eError); return 0; } /* interpret Mode */ if (strcmp(argv[3], "timer") == 0) { iMode = eTimer; } else if (strcmp(argv[3], "monitor") == 0) { iMode = ePreset; } else { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not recognized as valid counter mode", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } /* preset */ iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[4], &fPreset); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } iRet = SilentScan(self, (int) lNP, iMode, (float) fPreset, pSics, pCon); if (iRet) { SCSendOK(pCon); } return iRet; } /*----------- getnumchan */ else if (strcmp(argv[1], "getnumchan") == 0) { snprintf(pBueffel, 511, "%s.getnumchan = %d", argv[0], GetNMonitor((pCounter) self->pCounterData)); SCWrite(pCon, pBueffel, eValue); } /*----------- setchannel */ else if (strcmp(argv[1], "setchannel") == 0) { if (argc < 3) { SCWrite(pCon, "ERROR: setchannel expects an integer argument", eError); return 0; } /* convert to int */ iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &iChannel); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected integer, got %s", argv[2]); SCWrite(pCon, pBueffel, eError); return 0; } if (((iChannel < 0) && (iChannel != -10)) || (iChannel >= GetNMonitor((pCounter) self->pCounterData))) { SCWrite(pCon, "ERROR: requested counter channel out of range ", eError); return 0; } self->iChannel = iChannel; SCSendOK(pCon); return 1; } /*--------- command */ else if (strcmp(argv[1], "command") == 0) { /* inquire */ if (argc < 3) { snprintf(pBueffel,sizeof(pBueffel)-1, "%s.command = %s", argv[0], self->pCommand); SCWrite(pCon, pBueffel, eValue); return 1; } /* set case */ Arg2Text(argc - 2, &argv[2], pBueffel, 511); if (self->pCommand) free(self->pCommand); self->pCommand = strdup(pBueffel); SCSendOK(pCon); return 1; } /*--------- integration window */ else if (strcmp(argv[1], "window") == 0) { if (argc > 2) { /* set value */ iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &iChannel); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } if (iChannel < 0) { SCWrite(pCon, "ERROR: new integration window size out of range", eError); return 0; } self->iWindow = iChannel; SCSendOK(pCon); return 1; } else { /* request the value */ snprintf(pBueffel,sizeof(pBueffel)-1, "Integration Window = %d", self->iWindow); SCWrite(pCon, pBueffel, eValue); return 1; } } /*------------- integrate */ else if (strcmp(argv[1], "integrate") == 0) { iRet = ScanIntegrate(self, &fSum, &fVar); switch (iRet) { case INTEGLEFT: SCWrite(pCon, "ERROR: no left limit found for peak", eError); return 0; break; case INTEGRIGHT: SCWrite(pCon, "ERROR: no right limit found for peak", eError); return 0; break; case INTEGNOPEAK: SCWrite(pCon, "ERROR: no data found for peak", eError); return 0; break; case INTEGFUNNYBACK: SCWrite(pCon, "WARNING: background asymmetric or worse", eWarning); default: snprintf(pBueffel,sizeof(pBueffel)-1, "Intensity = %f, Variance = %f", fSum, fVar); SCWrite(pCon, pBueffel, eValue); return 1; break; } } /*---------- simscan */ else if (strcmp(argv[1], "simscan") == 0) { if (argc < 5) { SCWrite(pCon, "ERROR expected fPos FWHM Height parameters", eError); return 0; } iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[2], &x); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } fPos = x; iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[3], &x); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } FWHM = x; iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[4], &x); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } fHeight = x; iRet = SimScan(self, fPos, FWHM, fHeight); if (!iRet) { SCWrite(pCon, "ERROR: cannot create simulated scan data", eError); return 0; } SCSendOK(pCon); return 1; } /*----------------- line */ else if (strcmp(argv[1], "line") == 0) { Arg2Text(argc - 2, &argv[2], pBueffel, 511); return AppendScanLine(self, pBueffel); } /*----------------- storecounts */ else if (strcmp(argv[1], "storecounts") == 0) { Arg2Text(argc - 2, &argv[2], pBueffel, 511); return StoreScanCounts(self, pBueffel); } /*----------------- appendvarpos */ else if (strcmp(argv[1], "appendvarpos") == 0) { if (argc < 4) { SCWrite(pCon, "ERROR: insufficient number of arguments to appendvarpos", eError); return 0; } iRet = Tcl_GetInt(InterpGetTcl(pSics), argv[2], &i); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[3], &fStep); if (iRet != TCL_OK) { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: expected number, got %s", argv[3]); SCWrite(pCon, pBueffel, eError); return 0; } return AppendVarPos(pCon, self, i, (float) fStep); } /*------- savecounter */ else if (strcmp(argv[1], "savecounter") == 0) { conSave = self->pCon; self->pCon = pCon; CollectCounterData(self); self->pCon = conSave; if (SCGetInterrupt(pCon) >= eAbortScan) { return 0; } } else { snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s not recognized as subcommand to %s", argv[1], argv[0]); SCWrite(pCon, pBueffel, eError); return 0; } return 0; }