2584 lines
72 KiB
C
2584 lines
72 KiB
C
|
|
/*--------------------------------------------------------------------------
|
|
S C A N
|
|
|
|
Implementation file for the SICS scan command.
|
|
|
|
|
|
Mark Koennecke, October 1997, June 2001
|
|
|
|
copyright: see copyright.h
|
|
----------------------------------------------------------------------------*/
|
|
#include "sics.h"
|
|
#include <stdio.h>
|
|
#include <arpa/inet.h>
|
|
#include <tcl.h>
|
|
#include <math.h>
|
|
#include "fortify.h"
|
|
#include "sdynar.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"
|
|
|
|
extern void SNXFormatTime(char *pBuffer, int iLen);
|
|
/*
|
|
from nxdata.c
|
|
*/
|
|
/*------------------------------------------------------------------------*/
|
|
char *ScanMakeFileName(SicsInterp *pSics, SConnection *pCon)
|
|
{
|
|
pSicsVariable pPath = NULL, pPref = NULL, pEnd = NULL;
|
|
char *pRes = NULL;
|
|
int iLen, iNum, iYear;
|
|
char pNumText[10];
|
|
CommandList *pCom = NULL;
|
|
|
|
/*
|
|
make a simulated filename if in simulation mode
|
|
*/
|
|
if(pServ->simMode)
|
|
return strdup("sim001001901.sim");
|
|
|
|
pRes = makeFilename(pSics,pCon);
|
|
if(pRes == NULL)
|
|
{
|
|
pRes = strdup("emergency.scn");
|
|
}
|
|
|
|
return pRes;
|
|
}
|
|
|
|
/*--------------------- VarEntry Management --------------------------------*/
|
|
static void DeleteVarEntry(void *pData)
|
|
{
|
|
pVarEntry pVar = NULL;
|
|
|
|
pVar = (pVarEntry)pData;
|
|
|
|
assert(pVar);
|
|
|
|
if(pVar->fData)
|
|
{
|
|
free(pVar->fData);
|
|
}
|
|
free(pVar);
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static void DeleteCountEntry(void *pData)
|
|
{
|
|
free(pData);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int DummyWrite(pScanData self)
|
|
{
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int DummyWrite2(pScanData self, int iPoint)
|
|
{
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int WriteHeader(pScanData self)
|
|
{
|
|
int i, iRet;
|
|
FILE *fd;
|
|
char pBuffer[512], pError[512], *pPtr, *pName;
|
|
CommandList *pCom = NULL;
|
|
pSicsVariable pVar = NULL;
|
|
pDummy pDum = NULL;
|
|
pIDrivable pDriv = NULL;
|
|
float fVal;
|
|
pMotor pMot = NULL;
|
|
pVarEntry pScanVar = NULL;
|
|
void *pVoid = NULL;
|
|
|
|
assert(self->pSics);
|
|
assert(self->pCon);
|
|
|
|
/* open data file */
|
|
self->fd = fopen(self->pFile,"w");
|
|
if(!self->fd)
|
|
{
|
|
SCWrite(self->pCon,"ERROR: cannot write data file",eError);
|
|
return 0;
|
|
}
|
|
|
|
/* open header description file */
|
|
fd = fopen(self->pHeaderFile,"r");
|
|
if(!fd)
|
|
{
|
|
SCWrite(self->pCon,"ERROR: cannot open header description file",eError);
|
|
return 0;
|
|
}
|
|
|
|
/* loop through description file and act along the way */
|
|
while(fgets(pBuffer,511,fd) != NULL)
|
|
{
|
|
pPtr = strstr(pBuffer,"!!VAR(");
|
|
if(pPtr) /* handle a Sics variable */
|
|
{
|
|
/* extract the name */
|
|
pName = pPtr + 6; /* first char of name */
|
|
*pPtr = '\0'; /* this is the starter of the line */
|
|
pPtr = pName;
|
|
while( (*pPtr != '\0') && (*pPtr != ')') )
|
|
{
|
|
pPtr++;
|
|
}
|
|
*pPtr = '\0';
|
|
/* find the variable */
|
|
pCom = FindCommand(self->pSics,pName);
|
|
if(!pCom)
|
|
{
|
|
sprintf(pError,"ERROR: variable %s NOT found",pName);
|
|
SCWrite(self->pCon,pError,eError);
|
|
continue;
|
|
}
|
|
pVar = (pSicsVariable)pCom->pData;
|
|
if(!pVar)
|
|
{
|
|
sprintf(pError,"ERROR: variable %s NOT found",pName);
|
|
SCWrite(self->pCon,pError,eError);
|
|
continue;
|
|
}
|
|
switch(pVar->eType)
|
|
{
|
|
case veFloat:
|
|
sprintf(pError,"%f",pVar->fVal);
|
|
break;
|
|
case veInt:
|
|
sprintf(pError,"%d",pVar->iVal);
|
|
break;
|
|
case veText:
|
|
sprintf(pError,"%s",pVar->text);
|
|
break;
|
|
}
|
|
/* finally write */
|
|
fprintf(self->fd,"%s %s\n",pBuffer,pError);
|
|
continue;
|
|
}/* end variable */
|
|
/*------- Drivable */
|
|
pPtr = strstr(pBuffer,"!!DRIV(");
|
|
if(pPtr)
|
|
{
|
|
/* extract the name */
|
|
pName = pPtr + 7; /* first char of name */
|
|
*pPtr = '\0'; /* this is the starter of the line */
|
|
pPtr = pName;
|
|
while( (*pPtr != '\0') && (*pPtr != ')') )
|
|
{
|
|
pPtr++;
|
|
}
|
|
*pPtr = '\0';
|
|
/* find the variable */
|
|
pCom = FindCommand(self->pSics,pName);
|
|
if(!pCom)
|
|
{
|
|
sprintf(pError,"ERROR: variable %s NOT found",pName);
|
|
SCWrite(self->pCon,pError,eError);
|
|
continue;
|
|
}
|
|
pDum = (pDummy)pCom->pData;
|
|
if(!pDum)
|
|
{
|
|
sprintf(pError,"ERROR: variable %s is NOT drivable",pName);
|
|
SCWrite(self->pCon,pError,eError);
|
|
continue;
|
|
}
|
|
pDriv = (pIDrivable)pDum->pDescriptor->GetInterface(pDum,DRIVEID);
|
|
if(!pDriv)
|
|
{
|
|
sprintf(pError,"ERROR: variable %s is NOT drivable",pName);
|
|
SCWrite(self->pCon,pError,eError);
|
|
continue;
|
|
}
|
|
fVal = pDriv->GetValue(pDum,self->pCon);
|
|
fprintf(self->fd,"%s %f\n",pBuffer,fVal);
|
|
continue;
|
|
} /* end drive */
|
|
/*------- zero point */
|
|
pPtr = strstr(pBuffer,"!!ZERO(");
|
|
if(pPtr)
|
|
{
|
|
/* extract the name */
|
|
pName = pPtr + 7; /* first char of name */
|
|
*pPtr = '\0'; /* this is the starter of the line */
|
|
pPtr = pName;
|
|
while( (*pPtr != '\0') && (*pPtr != ')') )
|
|
{
|
|
pPtr++;
|
|
}
|
|
*pPtr = '\0';
|
|
/* find the motor */
|
|
pMot = FindMotor(self->pSics,pName);
|
|
if(!pMot)
|
|
{
|
|
sprintf(pError,"ERROR: motor %s NOT found",pName);
|
|
SCWrite(self->pCon,pError,eError);
|
|
continue;
|
|
}
|
|
iRet = MotorGetPar(pMot,"softzero",&fVal);
|
|
if(!iRet)
|
|
{
|
|
SCWrite(self->pCon,"ERROR: failed to read zero point",eError);
|
|
continue;
|
|
}
|
|
fprintf(self->fd,"%s %f\n",pBuffer,fVal);
|
|
continue;
|
|
} /* end zero point */
|
|
/* ------- date */
|
|
pPtr = strstr(pBuffer,"!!DATE!!");
|
|
if(pPtr)
|
|
{
|
|
*pPtr = '\0';
|
|
SNXFormatTime(pError,511);
|
|
fprintf(self->fd,"%s %s\n",pBuffer,pError);
|
|
continue;
|
|
}
|
|
/*-------- filename */
|
|
pPtr = strstr(pBuffer,"!!FILE!!");
|
|
if(pPtr)
|
|
{
|
|
*pPtr = '\0';
|
|
fprintf(self->fd,"%s %s\n",pBuffer,self->pFile);
|
|
continue;
|
|
}
|
|
/*------------ scanzero */
|
|
pPtr = strstr(pBuffer,"!!SCANZERO!!");
|
|
if(pPtr)
|
|
{
|
|
*pPtr = '\0';
|
|
/* write zero point of first scan variable if motor */
|
|
DynarGet(self->pScanVar,0,&pVoid);
|
|
pScanVar = (pVarEntry)pVoid;
|
|
if(pScanVar)
|
|
{
|
|
pMot = NULL;
|
|
pMot = FindMotor(self->pSics,pScanVar->Name);
|
|
if(pMot != NULL)
|
|
{
|
|
MotorGetPar(pMot,"softzero",&fVal);
|
|
fprintf(self->fd,"%s zero = %8.3f\n",pScanVar->Name, fVal);
|
|
}
|
|
}
|
|
}
|
|
/* --------- plain text */
|
|
fprintf(self->fd,"%s",pBuffer);
|
|
} /* end while */
|
|
|
|
|
|
/* remember position for seeking to it for writing data */
|
|
self->lPos = ftell(self->fd);
|
|
|
|
fclose(fd);
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int WriteScanPoints(pScanData self, int iPoint)
|
|
{
|
|
int i, i2;
|
|
char pLine[512], pItem[30], pInfo[512];
|
|
pVarEntry pVar = NULL;
|
|
pCountEntry pData = NULL;
|
|
void *pPtr = NULL;
|
|
|
|
assert(self->pCon);
|
|
assert(self->pSics);
|
|
|
|
/* 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 header */
|
|
fseek(self->fd,self->lPos, SEEK_SET);
|
|
if(self->iChannel != 0)
|
|
{
|
|
fprintf(self->fd,"WARNING: Scanning monitor %d\n",self->iChannel);
|
|
}
|
|
|
|
/* make the data header */
|
|
sprintf(pLine,"%-5s","NP");
|
|
strcpy(pInfo,"Scanning Variables: ");
|
|
for(i = 0; i < self->iScanVar;i++)
|
|
{
|
|
DynarGet(self->pScanVar,i,&pPtr);
|
|
pVar = (pVarEntry)pPtr;
|
|
if(pVar)
|
|
{
|
|
sprintf(pItem,"%-9.9s ",pVar->Name);
|
|
strcat(pLine,pItem);
|
|
sprintf(pItem,"%s, ",pVar->Name);
|
|
strcat(pInfo,pItem);
|
|
}
|
|
}
|
|
strcat(pLine," Counts ");
|
|
strcat(pLine,"Monitor1 ");
|
|
strcat(pLine,"Monitor2 ");
|
|
strcat(pLine,"Monitor3 ");
|
|
strcat(pLine,"Time ");
|
|
sprintf(pItem,"\n%d Points,",self->iNP);
|
|
strcat(pInfo,pItem);
|
|
if(self->iMode == eTimer)
|
|
{
|
|
strcat(pInfo," Mode: Timer,");
|
|
}
|
|
else
|
|
{
|
|
strcat(pInfo," Mode: Monitor,");
|
|
}
|
|
sprintf(pItem," Preset %f",self->fPreset);
|
|
strcat(pInfo,pItem);
|
|
fprintf(self->fd,"%s\n",pInfo);
|
|
fprintf(self->fd,"%s\n",pLine);
|
|
|
|
/* now the scan points */
|
|
for(i = 0; i < self->iCounts; i++)
|
|
{
|
|
sprintf(pLine,"%-5d",i);
|
|
/* print vars */
|
|
for(i2 = 0; i2 < self->iScanVar; i2++)
|
|
{
|
|
DynarGet(self->pScanVar,i2,&pPtr);
|
|
pVar = (pVarEntry)pPtr;
|
|
if(pVar)
|
|
{
|
|
sprintf(pItem,"%-10.3f",pVar->fData[i]);
|
|
strcat(pLine,pItem);
|
|
}
|
|
}
|
|
/* print Counts & Monitor */
|
|
DynarGet(self->pCounts,i,&pPtr);
|
|
pData = (pCountEntry)pPtr;
|
|
if(pData)
|
|
{
|
|
sprintf(pItem," %-12ld",pData->lCount);
|
|
strcat(pLine,pItem);
|
|
sprintf(pItem,"%-12ld",pData->Monitors[0]);
|
|
strcat(pLine,pItem);
|
|
sprintf(pItem,"%-12ld",pData->Monitors[1]);
|
|
strcat(pLine,pItem);
|
|
sprintf(pItem,"%-12ld",pData->Monitors[2]);
|
|
strcat(pLine,pItem);
|
|
sprintf(pItem,"%-6.1f",pData->fTime);
|
|
strcat(pLine,pItem);
|
|
}
|
|
fprintf(self->fd,"%s\n",pLine);
|
|
}
|
|
|
|
/* done */
|
|
fprintf(self->fd,"END-OF-DATA\n");
|
|
fclose(self->fd);
|
|
self->fd = NULL;
|
|
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 int ScanDrive(pScanData self, int iPoint);
|
|
static int ScanCount(pScanData self, int iPoint);
|
|
static int CollectScanData(pScanData self, int iPoint);
|
|
static int PrepareScan(pScanData self);
|
|
/*--------------------------------------------------------------------------*/
|
|
pScanData CreateScanObject(char *pRecover, char *pHeader,pCounter pCount)
|
|
{
|
|
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);
|
|
if( (!pNew->pScanVar) || (!pNew->pCounts) )
|
|
{
|
|
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)
|
|
{
|
|
strcpy(pNew->pRecover,pRecover);
|
|
}
|
|
if(pHeader)
|
|
{
|
|
strcpy(pNew->pHeaderFile,pHeader);
|
|
}
|
|
pNew->iMode = eTimer;
|
|
pNew->fPreset = 10.;
|
|
strcpy(pNew->pCounterName,pCount->name);
|
|
pNew->pCounterData = pCount;
|
|
pNew->PrepareScan = PrepareScan;
|
|
pNew->WriteHeader = WriteHeader;
|
|
pNew->WriteScanPoints = WriteScanPoints;
|
|
pNew->ScanDrive = ScanDrive;
|
|
pNew->ScanCount = ScanCount;
|
|
pNew->CollectScanData = CollectScanData;
|
|
pNew->iWindow = 6;
|
|
|
|
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);
|
|
}
|
|
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;
|
|
self->posSoft = 0;
|
|
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int AddScanVar(pScanData self, SicsInterp *pSics, SConnection *pCon,
|
|
char *name, float fStart, float fStep)
|
|
{
|
|
CommandList *pCom = NULL;
|
|
pIDrivable pDriv = NULL;
|
|
pDummy pData = NULL;
|
|
VarEntry pVar;
|
|
char pBueffel[512];
|
|
|
|
if(self->iActive)
|
|
{
|
|
SCWrite(pCon,"ERROR: cannot change parameters while scan is running",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/* find the thing */
|
|
pCom = FindCommand(pSics,name);
|
|
if(!pCom)
|
|
{
|
|
sprintf(pBueffel,"ERROR: Cannot find variable %s to scan",name);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
pData = (pDummy)pCom->pData;
|
|
if(!pData)
|
|
{
|
|
sprintf(pBueffel,"ERROR: Cannot find data for variable %s",name);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
pDriv = pData->pDescriptor->GetInterface(pData,DRIVEID);
|
|
if(!pDriv)
|
|
{
|
|
sprintf(pBueffel,"ERROR: variable %s is NOT driveable and cannot be scanned",name);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
|
|
/* got everything, fill in the VarEntry structure */
|
|
strcpy(pVar.Name,name);
|
|
pVar.pInter = pDriv;
|
|
pVar.pObject = pData;
|
|
pVar.fStart = fStart;
|
|
pVar.fStep = fStep;
|
|
pVar.fData = NULL;
|
|
|
|
/* put it away */
|
|
DynarPutCopy(self->pScanVar,self->iScanVar,&pVar,sizeof(VarEntry));
|
|
self->iScanVar++;
|
|
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int ClearScanVar(pScanData self)
|
|
{
|
|
if(self->iActive)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
self->iScanVar = 0;
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
struct RecoHead {
|
|
int iScanVar;
|
|
int iNP;
|
|
int iMode;
|
|
float fPreset;
|
|
int iCounts;
|
|
int iChannel;
|
|
};
|
|
|
|
struct VarHead {
|
|
char pName[256];
|
|
float fStart;
|
|
float fStep;
|
|
};
|
|
/*--------------------------------------------------------------------------*/
|
|
static int WriteRecover(pScanData self)
|
|
{
|
|
FILE *fd;
|
|
struct RecoHead sHead;
|
|
struct VarHead sVar;
|
|
void *pData;
|
|
pVarEntry pVar = NULL;
|
|
pCountEntry pCount = NULL;
|
|
int i;
|
|
|
|
fd = fopen(self->pRecover,"wb");
|
|
if(!fd)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* write Header */
|
|
sHead.iScanVar = self->iScanVar;
|
|
sHead.iNP = self->iNP;
|
|
sHead.iMode = self->iMode;
|
|
sHead.fPreset = self->fPreset;
|
|
sHead.iCounts = self->iCounts;
|
|
sHead.iChannel = self->iChannel;
|
|
fwrite(&sHead,sizeof(struct RecoHead),1,fd);
|
|
|
|
/* write scan vars */
|
|
for(i = 0; i < self->iScanVar; i++)
|
|
{
|
|
DynarGet(self->pScanVar,i,&pData);
|
|
pVar = (pVarEntry)pData;
|
|
if(pVar)
|
|
{
|
|
strcpy(sVar.pName,pVar->Name);
|
|
sVar.fStep = pVar->fStep;
|
|
sVar.fStart = pVar->fStart;
|
|
fwrite(&sVar,sizeof(struct VarHead),1,fd);
|
|
fwrite(pVar->fData,sizeof(float),sHead.iNP,fd);
|
|
}
|
|
pData = NULL;
|
|
}
|
|
|
|
/* write counts */
|
|
for(i = 0; i < self->iCounts; i++)
|
|
{
|
|
DynarGet(self->pCounts,i,&pData);
|
|
pCount = (pCountEntry)pData;
|
|
if(pCount)
|
|
{
|
|
fwrite(pCount,sizeof(CountEntry),1,fd);
|
|
}
|
|
}
|
|
|
|
fclose(fd);
|
|
return 1;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int ReadRecover(pScanData self)
|
|
{
|
|
FILE *fd;
|
|
struct RecoHead sHead;
|
|
struct VarHead sVar;
|
|
pVarEntry pVar;
|
|
void *pData;
|
|
CountEntry CountData;
|
|
int i,iRet;
|
|
|
|
assert(self);
|
|
assert(self->pCon);
|
|
|
|
fd = fopen(self->pRecover,"rb");
|
|
if(!fd)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* read Header */
|
|
iRet = fread(&sHead,sizeof(struct RecoHead),1,fd);
|
|
if(iRet != 1)
|
|
{
|
|
SCWrite(self->pCon,"ERROR: Recover File corrupted",eError);
|
|
fclose(fd);
|
|
return 0;
|
|
}
|
|
self->iNP = sHead.iNP;
|
|
self->iMode = sHead.iMode;
|
|
self->fPreset = sHead.fPreset;
|
|
self->iCounts = sHead.iCounts;
|
|
self->iChannel = sHead.iChannel;
|
|
|
|
/* read Scan Variables */
|
|
self->iScanVar = 0;
|
|
for(i = 0; i < sHead.iScanVar; i++)
|
|
{
|
|
iRet = fread(&sVar,sizeof(struct VarHead),1,fd);
|
|
if(iRet != 1)
|
|
{
|
|
SCWrite(self->pCon,"ERROR: Recover File corrupted",eError);
|
|
fclose(fd);
|
|
return 0;
|
|
}
|
|
AddScanVar(self,self->pSics,self->pCon,
|
|
sVar.pName, sVar.fStart, sVar.fStep);
|
|
DynarGet(self->pScanVar,i,&pData);
|
|
pVar = (pVarEntry)pData;
|
|
pVar->fData = (float *)malloc(sHead.iNP*sizeof(float));
|
|
if(!pVar->fData)
|
|
{
|
|
SCWrite(self->pCon,"ERROR: out of memory in scan::ReadRecover",eError);
|
|
fclose(fd);
|
|
return 0;
|
|
}
|
|
fread(pVar->fData,sizeof(float),sHead.iNP,fd);
|
|
}
|
|
|
|
/* read counts */
|
|
for(i = 0; i < sHead.iCounts; i++)
|
|
{
|
|
fread(&CountData,sizeof(CountEntry),1,fd);
|
|
DynarPutCopy(self->pCounts,i,&CountData,sizeof(CountEntry));
|
|
}
|
|
|
|
fclose(fd);
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int PrepareScan(pScanData self)
|
|
{
|
|
pVarEntry pVar = NULL;
|
|
void *pDings;
|
|
int i, iRet;
|
|
float fVal;
|
|
char pBueffel[512];
|
|
char pMessage[1024];
|
|
|
|
assert(self);
|
|
assert(self->iNP > 0);
|
|
assert(self->pCon);
|
|
|
|
/* check boundaries of scan variables and allocate storage */
|
|
for(i = 0; i < self->iScanVar; i++)
|
|
{
|
|
DynarGet(self->pScanVar,i,&pDings);
|
|
pVar = (pVarEntry)pDings;
|
|
if(pVar)
|
|
{
|
|
/* start value */
|
|
fVal = pVar->fStart;
|
|
iRet = pVar->pInter->CheckLimits(pVar->pObject,
|
|
fVal,pBueffel,511);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pMessage,"ERROR: %s, scan aborted",pBueffel);
|
|
SCWrite(self->pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
/* end value */
|
|
fVal = pVar->fStart + (self->iNP - 1) * pVar->fStep;
|
|
iRet = pVar->pInter->CheckLimits(pVar->pObject,
|
|
fVal,pBueffel,511);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pMessage,"ERROR: %s, scan aborted",pBueffel);
|
|
SCWrite(self->pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
/* allocate data space */
|
|
if(pVar->fData)
|
|
{
|
|
free(pVar->fData);
|
|
pVar->fData = NULL;
|
|
}
|
|
pVar->fData = (float *)malloc(self->iNP * sizeof(float));
|
|
if(!pVar->fData)
|
|
{
|
|
SCWrite(self->pCon,"ERROR: out of memory in scan, aborting",eError);
|
|
return 0;
|
|
}
|
|
memset(pVar->fData,0,self->iNP * sizeof(float));
|
|
}
|
|
else
|
|
{
|
|
SCWrite(self->pCon,
|
|
"WARNING: Internal error, no scan variable, I try to continue",
|
|
eWarning);
|
|
}
|
|
pVar = NULL;
|
|
} /* end for */
|
|
|
|
/* configure counter */
|
|
SetCounterMode((pCounter)self->pCounterData,self->iMode);
|
|
SetCounterPreset((pCounter)self->pCounterData, self->fPreset);
|
|
self->iCounts = 0;
|
|
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int NonCheckPrepare(pScanData self)
|
|
{
|
|
pVarEntry pVar = NULL;
|
|
void *pDings;
|
|
int i, iRet;
|
|
float fVal;
|
|
char pBueffel[512];
|
|
char pMessage[1024];
|
|
|
|
assert(self);
|
|
assert(self->iNP > 0);
|
|
assert(self->pCon);
|
|
|
|
/* allocate storage for scan variables */
|
|
for(i = 0; i < self->iScanVar; i++)
|
|
{
|
|
DynarGet(self->pScanVar,i,&pDings);
|
|
pVar = (pVarEntry)pDings;
|
|
if(pVar)
|
|
{
|
|
/* start value */
|
|
fVal = pVar->fStart;
|
|
|
|
/* allocate data space */
|
|
if(pVar->fData)
|
|
{
|
|
free(pVar->fData);
|
|
pVar->fData = NULL;
|
|
}
|
|
pVar->fData = (float *)malloc(self->iNP * sizeof(float));
|
|
if(!pVar->fData)
|
|
{
|
|
SCWrite(self->pCon,"ERROR: out of memory in scan, aborting",eError);
|
|
return 0;
|
|
}
|
|
memset(pVar->fData,0,self->iNP * sizeof(float));
|
|
}
|
|
else
|
|
{
|
|
SCWrite(self->pCon,
|
|
"WARNING: Internal error, no scan variable, I try to continue",
|
|
eWarning);
|
|
}
|
|
pVar = NULL;
|
|
} /* end for */
|
|
|
|
/* configure counter */
|
|
SetCounterMode((pCounter)self->pCounterData,self->iMode);
|
|
SetCounterPreset((pCounter)self->pCounterData, self->fPreset);
|
|
self->iCounts = 0;
|
|
|
|
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);
|
|
|
|
int StoreScanCounts(pScanData self, char *data)
|
|
{
|
|
CountEntry sCount;
|
|
char pNumber[20], *pPtr;
|
|
int iCount = 0;
|
|
|
|
if(data == NULL)
|
|
{
|
|
SCWrite(self->pCon,"WARNING: StoreScanCounst called without data",eWarning);
|
|
return 1;
|
|
}
|
|
|
|
/* parse the data */
|
|
pPtr = data;
|
|
pPtr = stptok(pPtr,pNumber,19," \t");
|
|
if(pPtr != NULL)
|
|
{
|
|
sCount.lCount = atoi(pNumber);
|
|
}
|
|
else
|
|
{
|
|
SCWrite(self->pCon,"ERROR: No data in StoreScanCounts",eError);
|
|
return 0;
|
|
}
|
|
while((pPtr = stptok(pPtr,pNumber,19," \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",
|
|
eError);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
sCount.i = self->iCounts;
|
|
DynarReplace(self->pCounts,self->iCounts,&sCount,sizeof(CountEntry));
|
|
self->iCounts++;
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int StartToDrive(pScanData self, int iPoint)
|
|
{
|
|
pVarEntry pVar = NULL;
|
|
void *pDings;
|
|
int i, iRet, status;
|
|
float fVal;
|
|
pDummy pDum;
|
|
char pBueffel[512];
|
|
|
|
assert(self);
|
|
assert(self->pCon);
|
|
|
|
|
|
/* loop over all scan variables */
|
|
status = 1;
|
|
for(i = 0; i < self->iScanVar; i++)
|
|
{
|
|
DynarGet(self->pScanVar,i,&pDings);
|
|
pVar = (pVarEntry)pDings;
|
|
if(pVar)
|
|
{
|
|
pDum = (pDummy)pVar->pObject;
|
|
fVal = pVar->fStart + iPoint * pVar->fStep;
|
|
iRet = StartDevice(pServ->pExecutor,
|
|
pVar->Name,
|
|
pDum->pDescriptor,
|
|
pVar->pObject,
|
|
self->pCon,
|
|
fVal);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"ERROR: Failed to start %s",pVar->Name);
|
|
SCWrite(self->pCon,pBueffel,eError);
|
|
status = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int CollectScanDataIntern(pScanData self, int iPoint, int jochenFlag)
|
|
{
|
|
pVarEntry pVar = NULL;
|
|
void *pDings;
|
|
int i, iRet, status;
|
|
float fVal;
|
|
char pStatus[512], pItem[20];
|
|
char pHead[512];
|
|
CountEntry sCount;
|
|
char *pAns = NULL, *pPtr = NULL ;
|
|
Tcl_Interp *pTcl;
|
|
|
|
assert(self);
|
|
assert(self->pCon);
|
|
|
|
/* prepare output header */
|
|
sprintf(pHead,"%-5.5s","NP");
|
|
sprintf(pStatus,"%-5d",iPoint);
|
|
|
|
/* loop over all scan variables */
|
|
status = 1;
|
|
for(i = 0; i < self->iScanVar; i++)
|
|
{
|
|
DynarGet(self->pScanVar,i,&pDings);
|
|
pVar = (pVarEntry)pDings;
|
|
if(pVar)
|
|
{
|
|
if(jochenFlag == 1 &&
|
|
strcmp(pVar->pObject->pDescriptor->name, "Motor") == 0)
|
|
{
|
|
MotorGetSoftPosition((pMotor)pVar->pObject,self->pCon,&fVal);
|
|
}
|
|
else
|
|
{
|
|
fVal = pVar->pInter->GetValue(pVar->pObject,self->pCon);
|
|
}
|
|
pVar->fData[iPoint] = fVal;
|
|
sprintf(pItem,"%-10.10s",pVar->Name);
|
|
strcat(pHead,pItem);
|
|
sprintf(pItem,"%-10.3f",fVal);
|
|
strcat(pStatus,pItem);
|
|
}
|
|
}
|
|
|
|
/* store counter data */
|
|
/* 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 */
|
|
strcat(pHead,"Counts ");
|
|
if(self->iChannel == -10)
|
|
{
|
|
/* execute the Tcl-script for getting the data */
|
|
pTcl = (Tcl_Interp *)self->pSics->pTcl;
|
|
if(!self->pCommand)
|
|
{
|
|
SCWrite(self->pCon,
|
|
"ERROR: command must be configured for user defined scans",
|
|
eError);
|
|
SCSetInterrupt(self->pCon,eAbortBatch);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_Eval(pTcl,self->pCommand);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
SCWrite(self->pCon,pTcl->result,eError);
|
|
return 0;
|
|
}
|
|
/* 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",eError);
|
|
return 0;
|
|
}
|
|
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);
|
|
}
|
|
sprintf(pItem,"%-15d",sCount.lCount);
|
|
strcat(pStatus,pItem);
|
|
|
|
/* get time */
|
|
sCount.fTime = GetCountTime((pCounter)self->pCounterData,
|
|
self->pCon);
|
|
strcat(pHead,"Monitor1 ");
|
|
sprintf(pItem,"%-12d",sCount.Monitors[0]);
|
|
strcat(pStatus,pItem);
|
|
strcat(pHead,"Monitor2 ");
|
|
sprintf(pItem,"%-12d",sCount.Monitors[1]);
|
|
strcat(pStatus,pItem);
|
|
strcat(pHead,"Monitor3 ");
|
|
sprintf(pItem,"%-12d",sCount.Monitors[2]);
|
|
strcat(pStatus,pItem);
|
|
strcat(pHead,"Time ");
|
|
sprintf(pItem,"%-6.1f",sCount.fTime);
|
|
strcat(pStatus,pItem);
|
|
|
|
|
|
/* write progress */
|
|
strcat(pHead,"\n");
|
|
strcat(pStatus,"\n");
|
|
SCWrite(self->pCon,pHead,eWarning);
|
|
SCWrite(self->pCon,pStatus,eWarning);
|
|
|
|
/* stow away */
|
|
DynarReplace(self->pCounts,self->iCounts,&sCount,sizeof(CountEntry));
|
|
self->iCounts++;
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int CollectScanData(pScanData self, int iPoint)
|
|
{
|
|
return CollectScanDataIntern(self,iPoint,0);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int CollectScanDataJochen(pScanData self, int iPoint)
|
|
{
|
|
return CollectScanDataIntern(self,iPoint,1);
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int ScanDrive(pScanData self, int iPoint)
|
|
{
|
|
int iRet;
|
|
long lTask;
|
|
int status;
|
|
|
|
iRet = StartToDrive(self,iPoint);
|
|
if(!iRet)
|
|
{
|
|
SCWrite(self->pCon,"ERROR: Cannot Drive, Scan aborted",eError);
|
|
status = 0;
|
|
}
|
|
else
|
|
{
|
|
status = 1;
|
|
}
|
|
/* wait for finish */
|
|
lTask = GetDevexecID(pServ->pExecutor);
|
|
if(lTask > 0)
|
|
{
|
|
TaskWait(pServ->pTasker,lTask);
|
|
}
|
|
return status;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int ScanCount(pScanData self, int iPoint)
|
|
{
|
|
pDummy pDum;
|
|
int iRet;
|
|
long lTask;
|
|
|
|
pDum = (pDummy)self->pCounterData;
|
|
iRet = StartDevice(pServ->pExecutor,
|
|
"ScanCounter",
|
|
pDum->pDescriptor,
|
|
self->pCounterData,
|
|
self->pCon,
|
|
self->fPreset);
|
|
if(!iRet)
|
|
{
|
|
SCWrite(self->pCon,"ERROR: Cannot Count, Scan aborted",eError);
|
|
return 0;
|
|
}
|
|
SetStatus(eCounting);
|
|
/* wait for finish */
|
|
lTask = GetDevexecID(pServ->pExecutor);
|
|
if(lTask > 0);
|
|
{
|
|
TaskWait(pServ->pTasker,lTask);
|
|
}
|
|
return 1;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int ScanLoop(pScanData self)
|
|
{
|
|
int i,iInt,iRet,iStatus;
|
|
|
|
assert(self);
|
|
assert(self->pCon);
|
|
|
|
InvokeCallBack(self->pCall,SCANSTART,self);
|
|
for(i = self->iCounts; i < self->iNP; i++)
|
|
{
|
|
/*--------- drive */
|
|
iRet = self->ScanDrive(self,i);
|
|
if(!iRet)
|
|
{
|
|
return 0;
|
|
}
|
|
/* 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",
|
|
eWarning);
|
|
continue;
|
|
break;
|
|
case eAbortScan:
|
|
SCWrite(self->pCon,"ERROR: Scan aborted",eError);
|
|
/* 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",eError);
|
|
return 0;
|
|
break;
|
|
}
|
|
/*-------------- count */
|
|
iRet = self->ScanCount(self, i);
|
|
if(!iRet)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* 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",eError);
|
|
/* 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",eError);
|
|
return 0;
|
|
break;
|
|
}
|
|
/*-------- scan post processing */
|
|
self->CollectScanData(self,i);
|
|
InvokeCallBack(self->pCall,SCANPOINT,self);
|
|
|
|
self->WriteScanPoints(self,i);
|
|
if(self->pRecover)
|
|
{
|
|
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->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;
|
|
return 0;
|
|
}
|
|
|
|
/* allocate a new 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;
|
|
}
|
|
sprintf(pBueffel,"Writing data file: %s ...",pPtr);
|
|
SCWrite(self->pCon,pBueffel,eWarning);
|
|
strcpy(self->pFile,pPtr);
|
|
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);
|
|
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 = PrepareScan(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 RecoverScan(pScanData self, SicsInterp *pSics, SConnection *pCon)
|
|
{
|
|
int iRet;
|
|
char *pPtr = NULL, pBueffel[512];
|
|
|
|
assert(pSics);
|
|
assert(pCon);
|
|
|
|
self->pCon = pCon;
|
|
self->pSics = pSics;
|
|
|
|
/* read recover file */
|
|
iRet = ReadRecover(self);
|
|
if(!iRet)
|
|
{
|
|
return iRet;
|
|
}
|
|
|
|
/* 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;
|
|
}
|
|
sprintf(pBueffel,"Writing data file: %s ...",pPtr);
|
|
SCWrite(self->pCon,pBueffel,eWarning);
|
|
strcpy(self->pFile,pPtr);
|
|
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);
|
|
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;
|
|
}
|
|
|
|
/* copy the actual scan data */
|
|
memcpy(fData,pVar->fData,iEnd*sizeof(float));
|
|
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)
|
|
{
|
|
strncpy(pName,pVar->Name,iLength);
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
/*---------------------------------------------------------------------*/
|
|
int isScanVarSoft(pScanData self){
|
|
return self->posSoft;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
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 = pVar->fStep;
|
|
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);
|
|
|
|
/* 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;
|
|
}
|
|
pVar->fData = (float *)malloc(90*sizeof(float));
|
|
if(!pVar->fData)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* create scan data in loop */
|
|
fStdDev = FWHM/2.354;
|
|
for(i = 0; i < 90; i++)
|
|
{
|
|
x = pVar->fData[i] = 10. + 0.1 * i;
|
|
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)
|
|
{
|
|
sprintf(pBueffel,"ERROR: cannot find counter %s",argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
pDum = (pDummy)pCom->pData;
|
|
if(!pDum)
|
|
{
|
|
sprintf(pBueffel,"ERROR: counter %s has no data",argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
if(!(pDum->pDescriptor->GetInterface(pDum,COUNTID)))
|
|
{
|
|
sprintf(pBueffel,"ERROR: object %s is NO counter",argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
pNew = CreateScanObject(argv[4],argv[3],(pCounter)pCom->pData);
|
|
if(!pNew)
|
|
{
|
|
SCWrite(pCon,"ERROR: failure to allocate scan data structure",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
iRet = AddCommand(pSics,
|
|
argv[1],
|
|
ScanWrapper,
|
|
DeleteScanObject,
|
|
pNew);
|
|
if(!iRet)
|
|
{
|
|
sprintf(pBueffel,"ERROR: duplicate command %s not created",argv[1]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
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(iEvent == SCANSTART)
|
|
{
|
|
SCWrite(pCon,"NewScan",eWarning);
|
|
return 1;
|
|
}
|
|
else if(iEvent == SCANEND)
|
|
{
|
|
SCWrite(pCon,"ScanEnd",eWarning);
|
|
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++)
|
|
{
|
|
sprintf(pItem,"{%d} ",lData[i]);
|
|
strcat(pPtr,pItem);
|
|
}
|
|
oldWrite = SCGetWriteFunc(pCon);
|
|
SCSetWriteFunc(pCon,SCOnlySockWrite);
|
|
SCWrite(pCon,pPtr,eWarning);
|
|
SCSetWriteFunc(pCon,oldWrite);
|
|
free(lData);
|
|
free(pPtr);
|
|
return 1;
|
|
}
|
|
return 1;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
static int ScanUUInterest(int iEvent, void *pEventData, void *pUser)
|
|
{
|
|
pScanData self = NULL;
|
|
SConnection *pCon = NULL;
|
|
char pItem[20];
|
|
long *lData = NULL;
|
|
int *iData = NULL;
|
|
int i;
|
|
|
|
self = (pScanData)pEventData;
|
|
pCon = (SConnection *)pUser;
|
|
|
|
assert(self);
|
|
assert(pCon);
|
|
|
|
if(iEvent == SCANSTART)
|
|
{
|
|
SCWrite(pCon,"NewScan",eWarning);
|
|
return 1;
|
|
}
|
|
else if(iEvent == SCANEND)
|
|
{
|
|
SCWrite(pCon,"ScanEnd",eWarning);
|
|
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;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
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, 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;
|
|
|
|
self = (pScanData)pData;
|
|
assert(self);
|
|
|
|
argtolower(argc,argv);
|
|
if(argc < 2)
|
|
{
|
|
sprintf(pBueffel,"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)
|
|
{
|
|
sprintf(pBueffel,"scan.File = %s",self->pFile);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
/*--------- getcounts */
|
|
else if(strcmp(argv[1],"getcounts") == 0)
|
|
{
|
|
/* get some memory */
|
|
if(self->iNP < 1)
|
|
{
|
|
SCWrite(pCon,"ERROR: no counts available",eError);
|
|
return 0;
|
|
}
|
|
lData = (long *)malloc(self->iNP*sizeof(long));
|
|
if(!lData)
|
|
{
|
|
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 counts */
|
|
GetScanCounts(self,lData,self->iNP);
|
|
|
|
/* format them */
|
|
strcpy(pPtr,"scan.Counts= ");
|
|
for(i = 0; i < self->iNP; i++)
|
|
{
|
|
sprintf(pItem,"{%d} ",lData[i]);
|
|
strcat(pPtr,pItem);
|
|
}
|
|
SCWrite(pCon,pPtr,eValue);
|
|
free(lData);
|
|
free(pPtr);
|
|
return 1;
|
|
}
|
|
/*---------- 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)
|
|
{
|
|
sprintf(pBueffel,"%s.noscanvar = %d",argv[0],
|
|
self->iScanVar);
|
|
SCWrite(pCon,pBueffel,eValue);
|
|
return 1;
|
|
}
|
|
/*-------- NP */
|
|
else if(strcmp(argv[1],"np") == 0)
|
|
{
|
|
sprintf(pBueffel,"%s.nP = %d",argv[0],
|
|
self->iNP);
|
|
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(pSics->pTcl,argv[2],&i);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"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 = ", pVar->Name);
|
|
for(i = 0; i < self->iNP; i++)
|
|
{
|
|
sprintf(pItem,"{%12.3f} ",fData[i]);
|
|
strcat(pPtr,pItem);
|
|
}
|
|
SCWrite(pCon,pPtr,eValue);
|
|
free(fData);
|
|
free(pPtr);
|
|
return 1;
|
|
}
|
|
/*-------- interest */
|
|
else if(strcmp(argv[1],"interest") == 0)
|
|
{
|
|
lID = RegisterCallback(self->pCall, SCANSTART, ScanInterest,
|
|
pCon, NULL);
|
|
SCRegister(pCon,pSics, self->pCall,lID);
|
|
lID = RegisterCallback(self->pCall, SCANEND, ScanInterest,
|
|
pCon, NULL);
|
|
SCRegister(pCon,pSics, self->pCall,lID);
|
|
lID = RegisterCallback(self->pCall, SCANPOINT, ScanInterest,
|
|
pCon, NULL);
|
|
SCRegister(pCon,pSics, self->pCall,lID);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/*-------- uuinterest */
|
|
else if(strcmp(argv[1],"uuinterest") == 0)
|
|
{
|
|
lID = RegisterCallback(self->pCall, SCANSTART, ScanUUInterest,
|
|
pCon, NULL);
|
|
SCRegister(pCon,pSics, self->pCall,lID);
|
|
lID = RegisterCallback(self->pCall, SCANEND, ScanUUInterest,
|
|
pCon, NULL);
|
|
SCRegister(pCon,pSics, self->pCall,lID);
|
|
lID = RegisterCallback(self->pCall, SCANPOINT, ScanUUInterest,
|
|
pCon, NULL);
|
|
SCRegister(pCon,pSics, self->pCall,lID);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
/* ------- uninterest */
|
|
else if(strcmp(argv[1],"uninterest") == 0)
|
|
{
|
|
RemoveCallback2(self->pCall,pCon);
|
|
SCUnregister(pCon,self->pCall);
|
|
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)
|
|
{
|
|
sprintf(pBueffel,
|
|
"ERROR: Insufficient number of arguments given for %s add",
|
|
argv[0]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
/* get numbers */
|
|
iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&fStart);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&fStep);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"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;
|
|
}
|
|
/* --------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;
|
|
}
|
|
/*------------ configure */
|
|
else if(strcmp(argv[1],"configure") == 0)
|
|
{
|
|
if(argc < 3)
|
|
{
|
|
SCWrite(pCon,"ERROR: missing configure option",eError);
|
|
return 0;
|
|
}
|
|
/* this is for userss 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],"soft") == 0)
|
|
{
|
|
ResetScanFunctions(self);
|
|
self->CollectScanData = CollectScanDataJochen;
|
|
self->posSoft = 1;
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
site = getSite();
|
|
if(site != NULL){
|
|
iRet = site->ConfigureScan(self,argv[2]);
|
|
}
|
|
if(!iRet){
|
|
sprintf(pBueffel,"ERROR: option %s not recognized by configure",
|
|
argv[2]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
} else {
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
/*---------- scan */
|
|
else if(strcmp(argv[1],"run") == 0)
|
|
{
|
|
/* get NP */
|
|
iRet = Tcl_GetInt(pSics->pTcl,argv[2],&lNP);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]);
|
|
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
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s not recognized as valid counter mode",
|
|
argv[3]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
/* preset */
|
|
iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&fPreset);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"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;
|
|
}
|
|
/*---------- silent */
|
|
else if(strcmp(argv[1],"silent") == 0)
|
|
{
|
|
/* get NP */
|
|
iRet = Tcl_GetInt(pSics->pTcl,argv[2],&lNP);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]);
|
|
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
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s not recognized as valid counter mode",
|
|
argv[3]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
/* preset */
|
|
iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&fPreset);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"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;
|
|
}
|
|
/*--------- recover */
|
|
else if(strcmp(argv[1],"recover") == 0)
|
|
{
|
|
iRet = RecoverScan(self,pSics,pCon);
|
|
if(iRet)
|
|
{
|
|
SCSendOK(pCon);
|
|
}
|
|
return iRet;
|
|
}
|
|
/*----------- 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(pSics->pTcl,argv[2],&iChannel);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"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)
|
|
{
|
|
sprintf(pBueffel,"%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(pSics->pTcl,argv[2],&iChannel);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"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 */
|
|
sprintf(pBueffel,"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:
|
|
sprintf(pBueffel,"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(pSics->pTcl,argv[2],&x);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
fPos = x;
|
|
iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&x);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
FWHM = x;
|
|
iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&x);
|
|
if(iRet != TCL_OK)
|
|
{
|
|
sprintf(pBueffel,"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);
|
|
}
|
|
else
|
|
{
|
|
sprintf(pBueffel,"ERROR: %s not recognized as subcommand to %s",
|
|
argv[1], argv[0]);
|
|
SCWrite(pCon,pBueffel,eError);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|