2240 lines
60 KiB
C
2240 lines
60 KiB
C
|
|
/*--------------------------------------------------------------------------
|
|
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 <stdio.h>
|
|
#include <arpa/inet.h>
|
|
#include <tcl.h>
|
|
#include <math.h>
|
|
#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;
|
|
}
|