- Added separate drivable motors for four circle H, K, L
- Added a listen mode to commandlog in order to support the batchEditor - Some small fixes to exe* for BatchEditor
This commit is contained in:
365
diffscan.c
Normal file
365
diffscan.c
Normal file
@ -0,0 +1,365 @@
|
||||
/*-------------------------------------------------------------------
|
||||
diffscan is an operator which can perform a fast differential scan
|
||||
while a motor is running.
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, November 2004
|
||||
---------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <tcl.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "diffscan.h"
|
||||
#include "drive.h"
|
||||
#include "counter.h"
|
||||
|
||||
#define DIFFMONITOR 0
|
||||
#define SKIP 1
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
static void KillDiffScan(void *data){
|
||||
pDiffScan self = (pDiffScan)data;
|
||||
|
||||
if(self == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
if(self->pDes != NULL){
|
||||
DeleteDescriptor(self->pDes);
|
||||
}
|
||||
if(self->parArray != NULL){
|
||||
ObParDelete(self->parArray);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int SaveDiffScan(void *data, char *name, FILE *fd){
|
||||
pDiffScan self = (pDiffScan)data;
|
||||
if(self == NULL){
|
||||
return 0;
|
||||
}
|
||||
fprintf(fd,"%s monitor %f\n",name,ObVal(self->parArray,DIFFMONITOR));
|
||||
fprintf(fd,"%s skip %f\n",name,ObVal(self->parArray,SKIP));
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
int MakeDiffScan(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pDiffScan pNew = NULL;
|
||||
int status;
|
||||
|
||||
pNew = (pDiffScan)malloc(sizeof(DiffScan));
|
||||
if(pNew == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory creating differential scan",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
memset(pNew,0,sizeof(DiffScan));
|
||||
pNew->pDes = CreateDescriptor("DiffScan");
|
||||
pNew->parArray = ObParCreate(2);
|
||||
if(!pNew->pDes || !pNew->parArray){
|
||||
SCWrite(pCon,"ERROR: out of memory creating differential scan",
|
||||
eError);
|
||||
KillDiffScan(pNew);
|
||||
return 0;
|
||||
}
|
||||
ObParInit(pNew->parArray, DIFFMONITOR,"monitor",4.0,usUser);
|
||||
ObParInit(pNew->parArray, SKIP,"skip",.0,usUser);
|
||||
pNew->pDes->SaveStatus = SaveDiffScan;
|
||||
|
||||
if(argc > 1) {
|
||||
status = AddCommand(pSics,argv[2],
|
||||
DiffScanWrapper,
|
||||
KillDiffScan,
|
||||
pNew);
|
||||
|
||||
} else {
|
||||
status = AddCommand(pSics,"diffscan",
|
||||
DiffScanWrapper,
|
||||
KillDiffScan,
|
||||
pNew);
|
||||
|
||||
}
|
||||
if(status != 1){
|
||||
SCWrite(pCon,"ERROR: duplicate diffscan not created",eError);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
int DiffScanWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pDiffScan self = NULL;
|
||||
pScanData pScan = NULL;
|
||||
ObPar *par = NULL;
|
||||
char pBueffel[255];
|
||||
int status;
|
||||
|
||||
self = (pDiffScan)pData;
|
||||
assert(self);
|
||||
|
||||
if(argc < 2){
|
||||
SCWrite(pCon,"ERROR: need arguments to diffscan",eError);
|
||||
return 0;
|
||||
}
|
||||
if(!SCMatchRights(pCon,usUser)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
first try to find a scan object and to run
|
||||
*/
|
||||
strtolower(argv[1]);
|
||||
pScan = (pScanData)FindCommandData(pSics,argv[1],"ScanObject");
|
||||
if(pScan != NULL && argc > 2){
|
||||
status = RunDiffScan(self,pScan,pCon, atof(argv[2]));
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
if we end here we are treating variables
|
||||
*/
|
||||
if(argc > 2){
|
||||
/*
|
||||
set case
|
||||
*/
|
||||
return ObParSet(self->parArray,argv[0],argv[1],atof(argv[2]),pCon);
|
||||
} else {
|
||||
/*
|
||||
get case
|
||||
*/
|
||||
par = ObParFind(self->parArray,argv[1]);
|
||||
if(par != NULL){
|
||||
snprintf(pBueffel,255,"%s.%s = %f",argv[0],argv[1],par->fVal);
|
||||
SCWrite(pCon,pBueffel,eValue);
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBueffel,255,"ERROR: parameter %s not found",argv[1]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int StartDiffScan(pDiffScan self, pScanData pScan,
|
||||
SConnection *pCon, float fEnd){
|
||||
pVarEntry pVar = NULL;
|
||||
void *pPtr = NULL;
|
||||
pCounter pCount = NULL;
|
||||
char pBueffel[255];
|
||||
int status;
|
||||
|
||||
/*
|
||||
error checks
|
||||
*/
|
||||
if(pScan->iScanVar < 1) {
|
||||
SCWrite(pCon,"ERROR: no scan variable to diffscan",eError);
|
||||
return 0;
|
||||
}
|
||||
if(pScan->iScanVar > 1) {
|
||||
snprintf(pBueffel,255,
|
||||
"WARNING: diffscan handles only first scan variable, %d %s",
|
||||
pScan->iScanVar - 1,
|
||||
"scan variables ignored");
|
||||
SCWrite(pCon,pBueffel, eWarning);
|
||||
}
|
||||
|
||||
/*
|
||||
initialize data structure
|
||||
*/
|
||||
self->scanObject = pScan;
|
||||
self->scanObject->pCon = pCon;
|
||||
self->skip = (int)ObVal(self->parArray,SKIP);
|
||||
self->scaleMonitor = (int)ObVal(self->parArray,DIFFMONITOR);
|
||||
self->normalizationScale = -1;
|
||||
pScan->iCounts = 0;
|
||||
|
||||
/*
|
||||
get variable
|
||||
*/
|
||||
DynarGet(pScan->pScanVar,0,&pPtr);
|
||||
pVar = (pVarEntry)pPtr;
|
||||
if(pVar == NULL){
|
||||
SCWrite(pCon,"ERROR: cannot access scan variable",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
drive to start position
|
||||
*/
|
||||
status = Drive(pCon,pServ->pSics,ScanVarName(pVar),ScanVarStart(pVar));
|
||||
if(status != 1){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Configure counter. We operate in timer mode with a very long
|
||||
preset mode. Stopping is done explicitly in the diffscan task
|
||||
*/
|
||||
SetCounterMode(pScan->pCounterData,eTimer);
|
||||
SetCounterPreset(pScan->pCounterData,3600.);
|
||||
|
||||
/*
|
||||
start motor and counter
|
||||
*/
|
||||
status = pVar->pInter->SetValue(pVar->pObject,pCon,fEnd);
|
||||
if(status != OKOK){
|
||||
/*
|
||||
errors will already have been reported in SetValue
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
pCount = (pCounter)pScan->pCounterData;
|
||||
assert(pCount);
|
||||
status = pCount->pCountInt->StartCount(pCount,pCon);
|
||||
if(status != OKOK){
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static float normalizeEntry(pCountEntry pCount, pCountEntry last,
|
||||
long monValue, int scaleMon){
|
||||
int i;
|
||||
float fScale;
|
||||
float value;
|
||||
long diff;
|
||||
|
||||
/*
|
||||
calculate scale
|
||||
*/
|
||||
diff = pCount->Monitors[scaleMon-1] - last->Monitors[scaleMon-1];
|
||||
if(diff > 0) {
|
||||
fScale = (float)monValue/(float)diff;
|
||||
} else {
|
||||
fScale = 0.;
|
||||
}
|
||||
value = ((float)(pCount->lCount - last->lCount))*fScale;
|
||||
pCount->lCount = (long)value;
|
||||
for(i = 0; i < 10; i++){
|
||||
pCount->Monitors[i] = (pCount->Monitors[i] - last->Monitors[i])*fScale;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static void copyCountData(pCountEntry last, pCountEntry pCount){
|
||||
memcpy(last,pCount,sizeof(CountEntry));
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static int DiffScanTask(void *pData){
|
||||
pCounter pCount = NULL;
|
||||
pCountEntry data;
|
||||
pVarEntry pVar = NULL;
|
||||
void *pPtr = NULL;
|
||||
float fPos, countValue;
|
||||
int status, finish = 1, count;
|
||||
char pBueffel[255];
|
||||
long rawCount, rawMon;
|
||||
CountEntry rawCopy;
|
||||
|
||||
pDiffScan self = (pDiffScan)pData;
|
||||
|
||||
/*
|
||||
manage skip
|
||||
*/
|
||||
if(self->skip > 0){
|
||||
if(self->skipCount > self->skip){
|
||||
self->skipCount = 0;
|
||||
} else {
|
||||
self->skipCount++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
read motor status
|
||||
*/
|
||||
DynarGet(self->scanObject->pScanVar,0,&pPtr);
|
||||
pVar = (pVarEntry)pPtr;
|
||||
status = pVar->pInter->CheckStatus(pVar->pObject,self->scanObject->pCon);
|
||||
if(status != HWBusy) {
|
||||
finish = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
read values
|
||||
*/
|
||||
status = GetDrivablePosition(pVar->pObject,self->scanObject->pCon,
|
||||
&fPos);
|
||||
if(status == 0){
|
||||
return finish;
|
||||
}
|
||||
AppendScanVar(pVar,fPos);
|
||||
pCount = (pCounter)self->scanObject->pCounterData;
|
||||
pCount->pCountInt->TransferData(pCount,self->scanObject->pCon);
|
||||
CollectCounterData(self->scanObject);
|
||||
|
||||
/*
|
||||
normalize (or not)
|
||||
*/
|
||||
DynarGet(self->scanObject->pCounts,self->scanObject->iCounts-1,&pPtr);
|
||||
data = (pCountEntry)pPtr;
|
||||
copyCountData(&rawCopy,data);
|
||||
if(self->normalizationScale < 0){
|
||||
countValue = (float)data->lCount;
|
||||
rawCount = data->lCount;
|
||||
rawMon = data->Monitors[self->scaleMonitor-1];
|
||||
self->normalizationScale = data->Monitors[self->scaleMonitor-1];
|
||||
} else {
|
||||
if(data->Monitors[self->scaleMonitor -1] -
|
||||
self->last.Monitors[self->scaleMonitor-1] < 5) {
|
||||
SCWrite(self->scanObject->pCon,
|
||||
"WARNING: low count rate",eWarning);
|
||||
}
|
||||
rawCount = data->lCount;
|
||||
rawMon = data->Monitors[self->scaleMonitor-1];
|
||||
countValue = normalizeEntry(data,&self->last,
|
||||
self->normalizationScale,
|
||||
self->scaleMonitor);
|
||||
}
|
||||
copyCountData(&self->last,&rawCopy);
|
||||
|
||||
/*
|
||||
print progress
|
||||
*/
|
||||
snprintf(pBueffel,255,"%5d %12.4f %12.4f RAW: %10d %10d",
|
||||
self->scanObject->iCounts -1,
|
||||
fPos, countValue, rawCount,
|
||||
rawMon);
|
||||
SCWrite(self->scanObject->pCon,pBueffel,eWarning);
|
||||
InvokeCallBack(self->scanObject->pCall,SCANPOINT,self->scanObject);
|
||||
|
||||
/*
|
||||
check for interrupt
|
||||
*/
|
||||
if(SCGetInterrupt(self->scanObject->pCon) >= eAbortScan){
|
||||
finish = 0;
|
||||
}
|
||||
|
||||
return finish;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
int RunDiffScan(pDiffScan self, pScanData pScan,
|
||||
SConnection *pCon, float fEnd){
|
||||
long lID;
|
||||
pCounter pCount = NULL;
|
||||
|
||||
if(StartDiffScan(self,pScan,pCon,fEnd) != 1) {
|
||||
return 0;
|
||||
}
|
||||
InvokeCallBack(self->scanObject->pCall,SCANSTART,self->scanObject);
|
||||
|
||||
|
||||
lID = TaskRegister(pServ->pTasker,DiffScanTask,NULL,NULL,self,10);
|
||||
TaskWait(pServ->pTasker,lID);
|
||||
|
||||
|
||||
pCount = (pCounter)self->scanObject->pCounterData;
|
||||
pCount->pCountInt->Halt(pCount);
|
||||
InvokeCallBack(self->scanObject->pCall,SCANEND,self->scanObject);
|
||||
|
||||
return 1;
|
||||
}
|
Reference in New Issue
Block a user