- A couple of small fixes for memory and initialization problems.
This is to make valgrind happy SKIPPED: psi/amorscan.c psi/el734hp.c psi/psi.c psi/tasscan.c
This commit is contained in:
@ -77,6 +77,7 @@
|
||||
SICSLogWrite("Error allocating memory for Interpreter",eInternal);
|
||||
return NULL;
|
||||
}
|
||||
memset(pInter,0,sizeof(SicsInterp));
|
||||
pInter->pCList = NULL;
|
||||
pInter->AList.pFirst = NULL; /* M.Z. */
|
||||
pInter->pTcl = (void *)MacroInit(pInter);
|
||||
|
41
conman.c
41
conman.c
@ -35,6 +35,10 @@
|
||||
Introduced SCPrintf to avoid many of these pBueffel.
|
||||
Markus Zolliker, Sept 2004.
|
||||
|
||||
Cleaned up conman data structure. Removed left over and unused
|
||||
fields.
|
||||
Mark Koennecke, December 2004
|
||||
|
||||
Copyright: see copyright.h
|
||||
-----------------------------------------------------------------------------*/
|
||||
#include "fortify.h"
|
||||
@ -167,7 +171,6 @@ extern pServer pServ;
|
||||
pRes->inUse = 0;
|
||||
pRes->iMacro = 0;
|
||||
pRes->iTelnet = 0;
|
||||
pRes->pSics = pSics;
|
||||
pRes->eInterrupt = eContinue;
|
||||
pRes->lMagic = CONMAGIC;
|
||||
pRes->iLogin = 0;
|
||||
@ -179,7 +182,7 @@ extern pServer pServ;
|
||||
}
|
||||
|
||||
/* install command */
|
||||
AddCommand(pRes->pSics, ConName(pRes->ident), ConSicsAction, NULL,pRes);
|
||||
AddCommand(pSics, ConName(pRes->ident), ConSicsAction, NULL,pRes);
|
||||
return pRes;
|
||||
|
||||
}
|
||||
@ -411,7 +414,7 @@ extern pServer pServ;
|
||||
fclose(pVictim->pFiles[i]);
|
||||
}
|
||||
|
||||
RemoveCommand(pVictim->pSics,ConName(pVictim->ident));
|
||||
RemoveCommand(pServ->pSics,ConName(pVictim->ident));
|
||||
|
||||
if(pVictim->pDes)
|
||||
{
|
||||
@ -428,14 +431,6 @@ extern pServer pServ;
|
||||
}
|
||||
LLDdelete(pVictim->iList);
|
||||
|
||||
/* remove standing data connections */
|
||||
if(pVictim->pDataSock)
|
||||
{
|
||||
NETClosePort(pVictim->pDataSock);
|
||||
free(pVictim->pDataSock);
|
||||
free(pVictim->pDataComp);
|
||||
}
|
||||
|
||||
/* remove command stack */
|
||||
if(pVictim->pStack)
|
||||
{
|
||||
@ -549,7 +544,9 @@ extern pServer pServ;
|
||||
l = vsnprintf(buf, sizeof buf, fmt, ap);
|
||||
va_end(ap);
|
||||
if (l >= sizeof buf) {
|
||||
/* we have probably a C99 conforming snprintf and need a larger buffer */
|
||||
/* we have probably a C99 conforming snprintf and
|
||||
need a larger buffer
|
||||
*/
|
||||
dyn = malloc(l+1);
|
||||
if (dyn != NULL) {
|
||||
va_start(ap, fmt);
|
||||
@ -662,7 +659,7 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
||||
/* put it into the interpreter if present */
|
||||
if(SCinMacro(self))
|
||||
{
|
||||
InterpWrite(self->pSics,buffer);
|
||||
InterpWrite(pServ->pSics,buffer);
|
||||
/* print it to client if error message */
|
||||
if((iOut== eError) || (iOut == eWarning) )
|
||||
{
|
||||
@ -742,7 +739,7 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
||||
/* put it into the interpreter if present */
|
||||
if(SCinMacro(self))
|
||||
{
|
||||
InterpWrite(self->pSics,buffer);
|
||||
InterpWrite(pServ->pSics,buffer);
|
||||
/* print it to client if error message */
|
||||
if((iOut== eError) || (iOut == eWarning) )
|
||||
{
|
||||
@ -793,7 +790,7 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
||||
/* put it into the interpreter if present */
|
||||
if(SCinMacro(self))
|
||||
{
|
||||
InterpWrite(self->pSics,buffer);
|
||||
InterpWrite(pServ->pSics,buffer);
|
||||
}
|
||||
else /* not in interpreter, normal logic */
|
||||
{
|
||||
@ -861,7 +858,7 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
||||
/* put it into the interpreter if present */
|
||||
if(SCinMacro(self))
|
||||
{
|
||||
InterpWrite(self->pSics,buffer);
|
||||
InterpWrite(pServ->pSics,buffer);
|
||||
}
|
||||
else /* not in interpreter, normal logic */
|
||||
{
|
||||
@ -1641,7 +1638,7 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
||||
|
||||
if(self->pAction)
|
||||
{
|
||||
InterpExecute(self->pSics,self->pCon,self->pAction);
|
||||
InterpExecute(pServ->pSics,self->pCon,self->pAction);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -1799,9 +1796,8 @@ static void writeToLogFiles(SConnection *self, char *buffer)
|
||||
}
|
||||
/* invoke command */
|
||||
CostaLock(self->pStack);
|
||||
SCInvoke(self,self->pSics,pPtr);
|
||||
SCInvoke(self,pServ->pSics,pPtr);
|
||||
CostaUnlock(self->pStack);
|
||||
/* SCWrite(self,"\b",eError); */
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1897,9 +1893,12 @@ int SCActive(SConnection *self)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if(GetExeOwner(pServ->pExecutor) == self)
|
||||
if(pServ->pExecutor != NULL)
|
||||
{
|
||||
return 1;
|
||||
if(GetExeOwner(pServ->pExecutor) == self)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
24
conman.h
24
conman.h
@ -12,6 +12,8 @@
|
||||
|
||||
Mark Koennecke, Aprl 2003
|
||||
|
||||
Mark Koennecke, December 2004
|
||||
|
||||
copyright: see copyright.h
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef SICSCONNECT
|
||||
@ -30,33 +32,31 @@ typedef int (*writeFunc)(struct __SConnection *pCon,
|
||||
typedef struct __SConnection {
|
||||
/* object basics */
|
||||
pObjectDescriptor pDes;
|
||||
/* char *pName; now generated on the fly from ident */
|
||||
long lMagic;
|
||||
long ident;
|
||||
struct __SConnection *next;
|
||||
|
||||
/* I/O control */
|
||||
/* our socket */
|
||||
mkChannel *pSock;
|
||||
|
||||
/* per connection log files */
|
||||
FILE *pFiles[MAXLOGFILES];
|
||||
int iMacro;
|
||||
int iTelnet;
|
||||
int iOutput;
|
||||
int iFiles;
|
||||
writeFunc write;
|
||||
mkChannel *pDataSock;
|
||||
char *pDataComp;
|
||||
int iDataPort;
|
||||
|
||||
int iMacro; /* suppress I/O in macro*/
|
||||
int iTelnet; /* telnet flag */
|
||||
int iOutput;
|
||||
writeFunc write; /* function doing
|
||||
writing */
|
||||
|
||||
/* execution context */
|
||||
int eInterrupt;
|
||||
int iUserRights;
|
||||
int inUse;
|
||||
int iDummy;
|
||||
int iGrab;
|
||||
int iErrCode;
|
||||
int iGrab; /* grab flag for token*/
|
||||
int parameterChange;
|
||||
int sicsError;
|
||||
SicsInterp *pSics;
|
||||
|
||||
/* a FIFO */
|
||||
pCosta pStack;
|
||||
|
@ -654,7 +654,7 @@
|
||||
{
|
||||
self->pCountInt->TransferData(self,pCon);
|
||||
}
|
||||
if( (iNum < 0) || (iNum > self->pDriv->iNoOfMonitors) )
|
||||
if( (iNum < 0) || (iNum >= self->pDriv->iNoOfMonitors) )
|
||||
{
|
||||
return -1L;
|
||||
}
|
||||
|
@ -159,6 +159,7 @@
|
||||
DeleteCallBackInterface(self->pCall);
|
||||
|
||||
free(self);
|
||||
pServ->pExecutor = NULL;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void ExeInterest(pExeList self, pDevEntry pDev, char *text) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
<TITLE>The Internal Scan Command</TITLE>
|
||||
</HEAD>
|
||||
<BODY>
|
||||
<H1>The Internal Scan Command</H1>
|
||||
<H1>The Internal Scan Commands</H1>
|
||||
<P>
|
||||
Scans are preformed from a variety of commands in SICS. All these commands
|
||||
are just Tcl--wrappers around an internal scan object implemented in C. This
|
||||
@ -13,6 +13,29 @@ command</a> in the initialisation file. This command install the internal
|
||||
scan object under a user defined name. For the rest of this document it is
|
||||
assumed that this name is xxscan.
|
||||
</P>
|
||||
<h2>Scan Concepts</2>
|
||||
<p>
|
||||
Scanning in SICS evolved a little over time. It turned out that scans
|
||||
are a demanding job for a programmer because of the plethora of
|
||||
special scans people wish to perform and the many data file formats which
|
||||
have to be supported. This requires a very high degree of
|
||||
configurability. Under several refactorings the internal scan command
|
||||
has grown to become:
|
||||
<ul>
|
||||
<li>A controller for the scan process.
|
||||
<li>A container to store scanned variables and counts during the
|
||||
process of a scan. This includes commands to store and retrieve such
|
||||
values.
|
||||
<li>A container for the configuration of the scan. A scan is
|
||||
configured by specifying functions to be called at the various steps
|
||||
during the scan. These are preconfigured to the standard scan
|
||||
functions. An API is provided to replace some or all of the scan
|
||||
functions by user defined ones.
|
||||
</ul>
|
||||
The internal scan object is augmented by a library of standard scan
|
||||
functions. The transition to the new model is not yet clean in order
|
||||
not to break to much old code.
|
||||
</p>
|
||||
The scan object (named here xxscan, but may have another name) understands
|
||||
the following commands:
|
||||
<DL>
|
||||
@ -28,6 +51,8 @@ different parameters.
|
||||
the counter mode to use (this can be either timer or monitor) and preset
|
||||
which is the preset value for the counter. Scan data is written to an output
|
||||
file.
|
||||
<dt>xxscan continue NP mode preset
|
||||
<dd>Continues an interrupted scan. Used by the recovery feauture.
|
||||
<DT>xxscan silent NP mode preset
|
||||
<DD>Executes a scan. The arguments are: NP the number of scan points, mode
|
||||
the counter mode to use (this can be either timer or monitor) and preset
|
||||
@ -47,16 +72,33 @@ command sets the channel to collect data from. The argument n is an integer
|
||||
ID for the channel to use.
|
||||
<DT>xxscan getcounts
|
||||
<DD>Retrieves the counst collected during the scan.
|
||||
<dt>xxscan getmonitor i
|
||||
<dd>Prints the monitor values collected during the scan for the
|
||||
monitor number i
|
||||
<dt>xxscan gettime
|
||||
<dd>Prints the counting times for the scan points in the current scan.
|
||||
<dt>xxscan np
|
||||
<dd>Prints the number of points in the current scan.
|
||||
<DT>xxscan getvardata n
|
||||
<DD>This command retrieves the values of a scan variable during the scan
|
||||
(the x axis). The argument n is the ID of the scan variable to retrieve data
|
||||
for. ID is 0 for the first scan variable added, 1 for the second etc.
|
||||
<dt>xxscan noscanvar
|
||||
<dd>Prints the number of scan variables
|
||||
<dt>xxscan getvarpar i
|
||||
<dd>Prints the name , start and step of the scan variable number i
|
||||
<DT>xxscan interest
|
||||
<DD>A SICS client can be automatically notified about scan progress. This is
|
||||
switched on with this command. Three types of messages are sent: A string
|
||||
NewScan on start of the scan, a string ScanEnd after the scan has finished
|
||||
and a string scan.Counts = {109292 8377 ...} with the scan values after each
|
||||
finished scan point.
|
||||
<dt>xxscan uuinterest
|
||||
<dd>As above but the array of counts is transferred in UU encoded
|
||||
format.
|
||||
<dt>xxscan dyninterest
|
||||
<dd>As above but scan points are printed one by one as a list
|
||||
containing: point number first_scan_var_pos counts.
|
||||
<DT>xxscan uninterest
|
||||
<DD> Uninterest switches automatic notification about scan progress off.
|
||||
<DT>xxscan integrate
|
||||
@ -87,10 +129,70 @@ object. Currently there are two:
|
||||
<li><b>amor</b>, a special mode the reflectometer AMOR which writes
|
||||
NeXus files.
|
||||
</ul>
|
||||
<dt>xxscan storecounts counts time mon1 mon2 ...
|
||||
<dD>This stores an entry of count values into the scan data
|
||||
structure. To be used from user defined scan functions. The scan
|
||||
pointer is incremented by one.
|
||||
<dt>xxscan storecounter
|
||||
<dd>Store the counts and monitors in the counter object configured for
|
||||
the scan into the scan data structure. Increments the scan pointer by
|
||||
one.
|
||||
<dt>xxscan appendvarpos i pos
|
||||
<dd>Append pos to the array of positions for scan variable i. To be
|
||||
used from user defined scan functions.
|
||||
<dt>xxscan callback scanstart | scanpoint | scanend
|
||||
<dd>Triggers callbacks configured on the scan object. May be used by
|
||||
user functions implementing own scan loops.
|
||||
<dt>xxscan function list
|
||||
<dd>Lists the available configurable function names. The calling style
|
||||
of these functions is described in the next section about stdscan.
|
||||
<dt>xxscan function functionname
|
||||
<dd>Returns the currently configured function for functionname.
|
||||
<dt>xxscan function functionname newfunctionname
|
||||
<dd>Sets a new function to be called for the function functionname in
|
||||
the scan.
|
||||
</DL>
|
||||
</P>
|
||||
<p>
|
||||
<h2>User Defined Scans</h2>
|
||||
<h2>User Definable Scan Functions</h2>
|
||||
<p>The last commands in the last section allowed to overload the
|
||||
functions implementing various operations during the scan with user
|
||||
defined methods. This section is the reference for these
|
||||
functions. The following operations during a scan be configured:
|
||||
<dl>
|
||||
<dt>writeheader
|
||||
<dd>Is supposed to write the header of the data file
|
||||
<dt>prepare
|
||||
<dd>Prepare does all the necessary operations necessary before a scan
|
||||
starts.
|
||||
<dt>drive
|
||||
<dd>Is called to drive to the next scan point
|
||||
<dt>count
|
||||
<dd>Is called at each scan point to perform the counting operation
|
||||
<dt>collect
|
||||
<dd>Is called for each scan point. This function is supposed to store
|
||||
the scan data into the scan data structure.
|
||||
<dt>writepoint
|
||||
<dd>Is called for each scan point and is meant to print information
|
||||
about the scan point to the data file and to the user.
|
||||
<dt>userdata
|
||||
<dd>This is the name of a user defined object which may be used to
|
||||
store user data for the scan.
|
||||
</dl>
|
||||
The exact invocations of the functions:
|
||||
<ul>
|
||||
<li>writeheader scanobjectname userobjectname
|
||||
<li>prepare scanobjectname userobjectname
|
||||
<li>drive scanobjectname userobjectname point
|
||||
<li>count scanobjectname userobjectname point
|
||||
<li>collect scanobjectname userobjectname point
|
||||
<li>writepoint scanobjectname userobjectname point
|
||||
</ul>
|
||||
scanobjectname is the name of the scan object invoking the
|
||||
function. This can be used for querying the scan
|
||||
object. userobjectname is the name of a entity as specified as
|
||||
userdata in the configuration. point is the number of the current scan point.
|
||||
</p>
|
||||
<h2>User Defined Scans(Old Style)</h2>
|
||||
<p>
|
||||
In some cases users wish to control the scan more closely, i.e. do
|
||||
multiple counting operations at the same point etc. This is especially
|
||||
@ -133,6 +235,44 @@ command:
|
||||
In all this replace xxxscan with the name of the internal scan
|
||||
command.
|
||||
</p>
|
||||
<h2>Differential Scans</h2>
|
||||
<p>
|
||||
When aligning or when searching peaks a very fast scan is
|
||||
required. This is the differential scan. It starts a motor and
|
||||
collects counts while the motor is running. The counts collected are
|
||||
the monitor normalized difference to the previous reading. This
|
||||
functionality can be configured into SICS with the command:
|
||||
<pre>
|
||||
MakeDiffScan
|
||||
</pre> in the configuration file. An optional parameter defines
|
||||
another name then diffscan (the default) for this object. Differential
|
||||
scans can only be run against one motor as it cannot be guaranteed that
|
||||
motors in a coordinated movement operate at the same speed. The
|
||||
procedure to use diffscan is:
|
||||
<ul>
|
||||
<li>Configure a scan variable into a SICS scan object: xxscan add var
|
||||
start step
|
||||
<li>Run diffscan as: diffscan scanobjectname end_position_of_scan
|
||||
This runs the differential scan. Scanobjectname is the name of a SICS
|
||||
internal scan object. It will be used to store the results of the
|
||||
scan. While the scan is running some basic information is printed. The
|
||||
scan will range from the start given in the xxscan add command to the
|
||||
end position given in this call.
|
||||
</ul>
|
||||
The diffscan object has two configurable parameters:
|
||||
<dl>
|
||||
<dt>monitor
|
||||
<dd>The monitor number to normalize against. For maximum precision
|
||||
this should be a monitor with a lot of intensity on it.
|
||||
<dt>skip
|
||||
<dd>The number of SICS main loop cycles to skip between readings. This
|
||||
can be used to control the amount of data generated during a
|
||||
differential scan. This may become a problem if there is fast hardware.
|
||||
</dl>
|
||||
A word of warning: positions found in differential scans may not be
|
||||
totally correct. The differential scan might even miss peaks when the
|
||||
relationship between motor speed and sampling rate is bad.
|
||||
</p>
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*---------------------------------------------------------------------------
|
||||
E N V I R O N M E N T C O N T R O L L E R
|
||||
|
||||
This is the implementation file for a base class for all environement
|
||||
This is the implementation file for a base class for all environment
|
||||
control devices in SICS.
|
||||
|
||||
Mark Koennecke, Juli 1997
|
||||
@ -1426,7 +1426,8 @@ static pEVControl InstallCommonControllers(SicsInterp *pSics,
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
else if(strcmp(argv[1],"new") == 0 || strcmp(argv[1], "replace") == 0) /* make a new one */
|
||||
else if(strcmp(argv[1],"new") == 0 || strcmp(argv[1], "replace") == 0)
|
||||
/* make a new one */
|
||||
{
|
||||
/* argv[2] = name */
|
||||
/* argv[3] must be type */
|
||||
@ -1462,7 +1463,9 @@ static pEVControl InstallCommonControllers(SicsInterp *pSics,
|
||||
if(site != NULL){
|
||||
pNew = site->InstallEnvironmentController(pSics,pCon,argc,argv);
|
||||
} else {
|
||||
sprintf(pBueffel,"ERROR: %s not recognized as a valid driver type", argv[3]);
|
||||
sprintf(pBueffel,
|
||||
"ERROR: %s not recognized as a valid driver type",
|
||||
argv[3]);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
pNew = NULL;
|
||||
}
|
||||
|
2
exeman.c
2
exeman.c
@ -322,7 +322,7 @@ static void registerCallbacks(SConnection *pCon, SicsInterp *pSics,
|
||||
info, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
lID = RegisterCallback(self->pCall, BATCHAREA, LineCallBack,
|
||||
info, killExeInfo);
|
||||
info, NULL);
|
||||
SCRegister(pCon,pSics, self->pCall,lID);
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
|
27
interface.c
27
interface.c
@ -41,7 +41,7 @@
|
||||
#include <assert.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
|
||||
#include "motor.h"
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
pIDrivable CreateDrivableInterface(void)
|
||||
@ -108,6 +108,31 @@
|
||||
{
|
||||
return (pIDrivable)FindInterface(pObject,DRIVEID);
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int GetDrivablePosition(void *pObject, SConnection *pCon, float *fPos)
|
||||
{
|
||||
pIDrivable pDriv = NULL;
|
||||
pMotor pMot = NULL;
|
||||
float value;
|
||||
|
||||
pDriv = GetDrivableInterface(pObject);
|
||||
if(pDriv == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if(iHasType(pObject,"Motor"))
|
||||
{
|
||||
pMot = (pMotor)pObject;
|
||||
return MotorGetSoftPosition(pMot,pCon,fPos);
|
||||
}
|
||||
value = pDriv->GetValue(pObject,pCon);
|
||||
if(value < 9999.99)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*fPos = value;
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
pICountable GetCountableInterface(void *pObject)
|
||||
{
|
||||
|
26
interface.h
26
interface.h
@ -1,5 +1,5 @@
|
||||
|
||||
#line 359 "interface.w"
|
||||
#line 365 "interface.w"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
I N T E R F A C E S
|
||||
@ -42,16 +42,18 @@
|
||||
} IDrivable, *pIDrivable;
|
||||
|
||||
pIDrivable GetDrivableInterface(void *pObject);
|
||||
int GetDrivablePosition(void *pObject, SConnection *pCon,
|
||||
float *fPos);
|
||||
|
||||
|
||||
#line 384 "interface.w"
|
||||
#line 390 "interface.w"
|
||||
|
||||
|
||||
pIDrivable CreateDrivableInterface(void);
|
||||
|
||||
/* ------------------------ The countable interface ---------------------*/
|
||||
|
||||
#line 177 "interface.w"
|
||||
#line 183 "interface.w"
|
||||
|
||||
typedef struct {
|
||||
int ID;
|
||||
@ -68,23 +70,23 @@
|
||||
pICountable GetCountableInterface(void *pObject);
|
||||
|
||||
|
||||
#line 389 "interface.w"
|
||||
#line 395 "interface.w"
|
||||
|
||||
|
||||
pICountable CreateCountableInterface(void);
|
||||
|
||||
/* ------------------------- The CallBack Interface --------------------*/
|
||||
|
||||
#line 230 "interface.w"
|
||||
#line 236 "interface.w"
|
||||
|
||||
typedef void (*KillFuncIT)(void *pData);
|
||||
typedef int (*SICSCallBack)(int iEvent, void *pEventData,
|
||||
void *pUserData);
|
||||
|
||||
#line 394 "interface.w"
|
||||
#line 400 "interface.w"
|
||||
|
||||
|
||||
#line 252 "interface.w"
|
||||
#line 258 "interface.w"
|
||||
|
||||
typedef struct __ICallBack *pICallBack;
|
||||
|
||||
@ -104,11 +106,11 @@
|
||||
|
||||
pICallBack GetCallbackInterface(void *pData);
|
||||
|
||||
#line 395 "interface.w"
|
||||
#line 401 "interface.w"
|
||||
|
||||
/*---------------------- The Environment Interface --------------------*/
|
||||
|
||||
#line 323 "interface.w"
|
||||
#line 329 "interface.w"
|
||||
|
||||
typedef enum { EVIdle, EVDrive, EVMonitor, EVError } EVMode;
|
||||
typedef struct {
|
||||
@ -118,13 +120,13 @@
|
||||
int (*HandleError)(void *self);
|
||||
} EVInterface, *pEVInterface;
|
||||
|
||||
#line 397 "interface.w"
|
||||
#line 403 "interface.w"
|
||||
|
||||
|
||||
#line 349 "interface.w"
|
||||
#line 355 "interface.w"
|
||||
|
||||
pEVInterface CreateEVInterface(void);
|
||||
|
||||
#line 398 "interface.w"
|
||||
#line 404 "interface.w"
|
||||
|
||||
#endif
|
||||
|
@ -146,6 +146,8 @@ $\langle$driv {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ } IDrivable, *pIDrivable;@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ pIDrivable GetDrivableInterface(void *pObject); @\\
|
||||
\mbox{}\verb@ int GetDrivablePosition(void *pObject, SConnection *pCon,@\\
|
||||
\mbox{}\verb@ float *fPos);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
@ -195,6 +197,10 @@ the existence of a drivable interface. If it exists a pointer to it will be
|
||||
returned. NEVER free this pointer. If no drivable interface exists, NULL
|
||||
will be returned.
|
||||
|
||||
{\bf GetDrivablePosition retrieves the position of the drivabel
|
||||
object. If the device is a motor corrections for zero points and signs
|
||||
will be applied. Returns 1 on success and 0 on failure}
|
||||
|
||||
\subsubsection{The Countable Interface}
|
||||
This is an interface for interacting with anything which counts.
|
||||
|
||||
|
@ -129,6 +129,8 @@ environment controllers fit this bill as well.
|
||||
} IDrivable, *pIDrivable;
|
||||
|
||||
pIDrivable GetDrivableInterface(void *pObject);
|
||||
int GetDrivablePosition(void *pObject, SConnection *pCon,
|
||||
float *fPos);
|
||||
|
||||
@}
|
||||
The first member of this structure is an ID which can be used in order to
|
||||
@ -170,6 +172,10 @@ the existence of a drivable interface. If it exists a pointer to it will be
|
||||
returned. NEVER free this pointer. If no drivable interface exists, NULL
|
||||
will be returned.
|
||||
|
||||
{\bf GetDrivablePosition retrieves the position of the drivabel
|
||||
object. If the device is a motor corrections for zero points and signs
|
||||
will be applied. Returns 1 on success and 0 on failure}
|
||||
|
||||
\subsubsection{The Countable Interface}
|
||||
This is an interface for interacting with anything which counts.
|
||||
|
||||
|
6
macro.c
6
macro.c
@ -511,7 +511,11 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp *interp,
|
||||
{ /* Tcl error */
|
||||
if(strlen(pTcl->result) > 2)
|
||||
{
|
||||
SCWrite(pCon,pTcl->result,eError);
|
||||
/*
|
||||
local copy in order to resolve a valgrind error
|
||||
*/
|
||||
strncpy(pBueffel,pTcl->result,511);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
}
|
||||
pCom = Tcl_DStringValue(&command);
|
||||
SCWrite(pCon,"ERROR: in Tcl block:",eError);
|
||||
|
4
make_gen
4
make_gen
@ -25,8 +25,8 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||
rmtrail.o help.o nxupdate.o confvirtualmot.o \
|
||||
simchop.o choco.o chadapter.o trim.o scaldate.o \
|
||||
hklscan.o xytable.o exebuf.o exeman.o\
|
||||
circular.o maximize.o sicscron.o \
|
||||
d_sign.o d_mod.o tcldrivable.o \
|
||||
circular.o maximize.o sicscron.o scanvar.o \
|
||||
d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o\
|
||||
synchronize.o definealias.o oscillate.o \
|
||||
hmcontrol.o userscan.o rs232controller.o lomax.o \
|
||||
fourlib.o motreg.o motreglist.o anticollider.o \
|
||||
|
8
mesure.c
8
mesure.c
@ -322,7 +322,7 @@ typedef struct {
|
||||
if(pVar)
|
||||
{
|
||||
fVal = pVar->pInter->GetValue(pVar->pObject,self->pCon);
|
||||
pVar->fData[iPoint] = fVal;
|
||||
AppendScanVar(pVar,fVal);
|
||||
sprintf(pItem,"%-10.10s",pVar->Name);
|
||||
strcat(pHead,pItem);
|
||||
sprintf(pItem,"%-10.3f",fVal);
|
||||
@ -419,8 +419,7 @@ static float determineStepWidth(pMesure self, float two_theta)
|
||||
}
|
||||
|
||||
/*
|
||||
check if we are really there. All this only because Jurg
|
||||
does not fix his rotten cradle.
|
||||
check if we are really there.
|
||||
*/
|
||||
CalculateSettings(self->pCryst,fHKL,fPsi,0,fSet,pCon);
|
||||
for(i = 0; i < 4; i++)
|
||||
@ -503,8 +502,7 @@ static float determineStepWidth(pMesure self, float two_theta)
|
||||
}
|
||||
|
||||
/*
|
||||
check if we are really there. All this only because Jurg
|
||||
does not fix his rotten cradle.
|
||||
check if we are really there.
|
||||
*/
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
|
142
motor.c
142
motor.c
@ -71,11 +71,11 @@
|
||||
#define INT 6
|
||||
#define PREC 7
|
||||
#define USRIGHTS 8
|
||||
#define SPEED 9
|
||||
#define SIGN 10
|
||||
#define ECOUNT 11
|
||||
#define POSCOUNT 12
|
||||
#define IGNOREFAULT 13
|
||||
#define SIGN 9
|
||||
#define ECOUNT 10
|
||||
#define POSCOUNT 11
|
||||
#define IGNOREFAULT 12
|
||||
#define MOVECOUNT 13
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
a tiny structure used in CallBack work
|
||||
@ -179,6 +179,8 @@
|
||||
fputs(pBueffel,fd);
|
||||
sprintf(pBueffel,"%s poscount %f\n",name,
|
||||
ObVal(self->ParArray,POSCOUNT));
|
||||
sprintf(pBueffel,"%s movecount %f\n",name,
|
||||
ObVal(self->ParArray,MOVECOUNT));
|
||||
fputs(pBueffel,fd);
|
||||
return 1;
|
||||
}
|
||||
@ -348,138 +350,13 @@ static int evaluateStatus(pMotor self, SConnection *pCon)
|
||||
}
|
||||
return newStatus;
|
||||
}
|
||||
/*-----------------------------------------------------------------------
|
||||
old version, kept for time being.
|
||||
----------------------------------------------------------------------*/
|
||||
static int eevaluateStatus(pMotor self, SConnection *pCon)
|
||||
{
|
||||
int iRet, iCode;
|
||||
MotCallback sCall;
|
||||
char pBueffel[256], pError[132];
|
||||
float fHard;
|
||||
|
||||
iRet = self->pDriver->GetStatus(self->pDriver);
|
||||
if( (iRet == OKOK) || (iRet == HWIdle))
|
||||
{
|
||||
MotorGetSoftPosition(self,pCon,&sCall.fVal);
|
||||
sCall.pName = self->name;
|
||||
InvokeCallBack(self->pCall, MOTEND, &sCall);
|
||||
|
||||
MotorGetHardPosition(self,pCon,&fHard);
|
||||
self->fPosition = fHard;
|
||||
if(absf(fHard - self->fTarget) > ObVal(self->ParArray,PREC))
|
||||
{
|
||||
snprintf(pBueffel,131,"WARNING: %s off position by %f",
|
||||
self->name, absf(fHard - self->fTarget));
|
||||
SCWrite(pCon,pBueffel, eWarning);
|
||||
MotorInterrupt(pCon,ObVal(self->ParArray,INT));
|
||||
self->retryCount = 0;
|
||||
/*
|
||||
suppress HWPosFaults when ignore flag set
|
||||
*/
|
||||
if(ObVal(self->ParArray,IGNOREFAULT) > 0)
|
||||
{
|
||||
return HWIdle;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWPosFault;
|
||||
}
|
||||
}
|
||||
self->retryCount = 0;
|
||||
return HWIdle;
|
||||
}
|
||||
/* motor suggests a fault */
|
||||
else if(iRet == HWFault)
|
||||
{
|
||||
self->pDriver->GetError(self->pDriver,&iCode, pError,131);
|
||||
iRet = self->pDriver->TryAndFixIt(self->pDriver,iCode, self->fTarget);
|
||||
if(iRet == MOTFAIL)
|
||||
{
|
||||
snprintf(pBueffel,255,"ERROR: %s on %s",pError,self->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
MotorInterrupt(pCon,ObVal(self->ParArray,INT));
|
||||
self->retryCount = 0;
|
||||
return HWFault;
|
||||
}
|
||||
else if(iRet == MOTREDO)
|
||||
{
|
||||
self->pDriver->RunTo(self->pDriver,self->fTarget);
|
||||
self->retryCount++;
|
||||
if(self->retryCount >= 3)
|
||||
{
|
||||
self->retryCount = 0;
|
||||
return HWFault;
|
||||
}
|
||||
return HWBusy;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->retryCount = 0;
|
||||
return HWBusy;
|
||||
}
|
||||
}
|
||||
/* a positioning fault */
|
||||
else if(iRet == HWPosFault)
|
||||
{
|
||||
self->pDriver->GetError(self->pDriver,&iCode, pError,131);
|
||||
iRet = self->pDriver->TryAndFixIt(self->pDriver,iCode, self->fTarget);
|
||||
if(iRet == MOTFAIL)
|
||||
{
|
||||
snprintf(pBueffel,255,"ERROR: %s on %s",pError,self->name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
MotorInterrupt(pCon,ObVal(self->ParArray,INT));
|
||||
self->retryCount = 0;
|
||||
return HWFault;
|
||||
}
|
||||
else if(iRet == MOTREDO)
|
||||
{
|
||||
/*
|
||||
abort if to many positioning faults
|
||||
*/
|
||||
self->posFaultCount++;
|
||||
if(self->posFaultCount >= 4)
|
||||
{
|
||||
self->posFaultCount = 0;
|
||||
self->retryCount = 0;
|
||||
/*
|
||||
do not do pass on positioning fault errors when the
|
||||
appropriate flag has been set
|
||||
*/
|
||||
if(ObVal(self->ParArray,IGNOREFAULT) > 0)
|
||||
{
|
||||
return HWIdle;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWPosFault;
|
||||
}
|
||||
}
|
||||
self->pDriver->RunTo(self->pDriver,self->fTarget);
|
||||
return HWBusy;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HWBusy;
|
||||
}
|
||||
}
|
||||
else if(iRet == HWWarn)
|
||||
{
|
||||
self->pDriver->GetError(self->pDriver,&iCode,pError,131);
|
||||
snprintf(pBueffel,255,"WARNING: %s on %s",pError,self->name);
|
||||
SCWrite(pCon,pBueffel,eStatus);
|
||||
return HWIdle;
|
||||
}
|
||||
self->retryCount = 0;
|
||||
return iRet;
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
static void handleMoveCallback(pMotor self, SConnection *pCon)
|
||||
{
|
||||
MotCallback sCall;
|
||||
|
||||
self->posCount++;
|
||||
if(self->posCount >= ObVal(self->ParArray,POSCOUNT))
|
||||
if(self->posCount >= ObVal(self->ParArray,MOVECOUNT))
|
||||
{
|
||||
MotorGetSoftPosition(self,pCon,&sCall.fVal);
|
||||
sCall.pName = self->name;
|
||||
@ -536,11 +413,11 @@ static void handleMoveCallback(pMotor self, SConnection *pCon)
|
||||
ObParInit(pM->ParArray,INT,"interruptmode",INTCONT,usMugger);
|
||||
ObParInit(pM->ParArray,PREC,"precision",0.01,usMugger);
|
||||
ObParInit(pM->ParArray,USRIGHTS,"accesscode",(float)usUser,usMugger);
|
||||
ObParInit(pM->ParArray,SPEED,"speed",0.02,usInternal);
|
||||
ObParInit(pM->ParArray,SIGN,"sign",1.0,usMugger);
|
||||
ObParInit(pM->ParArray,ECOUNT,"failafter",3.0,usMugger);
|
||||
ObParInit(pM->ParArray,POSCOUNT,"maxretry",3.0,usMugger);
|
||||
ObParInit(pM->ParArray,IGNOREFAULT,"ignorefault",0.0,usMugger);
|
||||
ObParInit(pM->ParArray,MOVECOUNT,"movecount",10.0,usMugger);
|
||||
pDriv->GetPosition(pDriv,&(pM->fPosition));
|
||||
pM->fTarget = pM->fPosition;
|
||||
pM->endScriptID = 0;
|
||||
@ -878,6 +755,7 @@ extern void KillPiPiezo(void *pData);
|
||||
self->retryCount = 0;
|
||||
self->stopped = 0;
|
||||
self->fTarget = fHard;
|
||||
self->posCount = 0;
|
||||
iRet = self->pDriver->RunTo(self->pDriver,fHard);
|
||||
if(iRet != OKOK)
|
||||
{ /* try three times to fix it */
|
||||
|
@ -103,7 +103,6 @@ CreateSocketAdress(
|
||||
sockaddrPtr->sin_addr.s_addr = addr.s_addr;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
mkChannel *NETOpenPort(int iPort)
|
||||
|
1
nread.c
1
nread.c
@ -139,6 +139,7 @@ extern VerifyChannel(mkChannel *self); /* defined in network.c */
|
||||
sItem.pCon = pCon;
|
||||
sItem.iEOD = 0;
|
||||
sItem.tStatus = tData;
|
||||
sItem.iReadable = 0;
|
||||
memset(sItem.pHold,0,511);
|
||||
|
||||
LLDnodeAppendFrom(self->iList, &sItem);
|
||||
|
@ -348,7 +348,10 @@
|
||||
if(pSICSOptions)
|
||||
IFDeleteOptions(pSICSOptions);
|
||||
if(self->pSics)
|
||||
{
|
||||
DeleteInterp(self->pSics);
|
||||
self->pSics = NULL;
|
||||
}
|
||||
|
||||
/* close the server port */
|
||||
if(self->pServerPort)
|
||||
|
4
obdes.h
4
obdes.h
@ -1,5 +1,5 @@
|
||||
|
||||
#line 355 "interface.w"
|
||||
#line 361 "interface.w"
|
||||
|
||||
|
||||
#line 29 "interface.w"
|
||||
@ -52,5 +52,5 @@ typedef struct {
|
||||
|
||||
#endif
|
||||
|
||||
#line 356 "interface.w"
|
||||
#line 362 "interface.w"
|
||||
|
||||
|
4
ofac.c
4
ofac.c
@ -107,6 +107,7 @@
|
||||
#include "confvirtmot.h"
|
||||
#include "exeman.h"
|
||||
#include "oscillate.h"
|
||||
#include "diffscan.h"
|
||||
/*----------------------- Server options creation -------------------------*/
|
||||
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
@ -288,6 +289,8 @@
|
||||
MakeExeManager,NULL,NULL);
|
||||
AddCommand(pInter,"MakeOscillator",
|
||||
MakeOscillator,NULL,NULL);
|
||||
AddCommand(pInter,"MakeDiffScan",
|
||||
MakeDiffScan,NULL,NULL);
|
||||
|
||||
|
||||
/*
|
||||
@ -348,6 +351,7 @@
|
||||
RemoveCommand(pSics,"MakeConfigurableMotor");
|
||||
RemoveCommand(pSics,"MakeBatchManager");
|
||||
RemoveCommand(pSics,"MakeOscillator");
|
||||
RemoveCommand(pSics,"MakeDiffScan");
|
||||
|
||||
/*
|
||||
remove site specific installation commands
|
||||
|
@ -115,7 +115,7 @@
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pNew->pScanner = CreateScanObject(NULL,NULL,pCount);
|
||||
pNew->pScanner = CreateScanObject(NULL,NULL,pCount,"optiscan");
|
||||
if(!pNew->pScanner)
|
||||
{
|
||||
DeleteDescriptor(pNew->pDes);
|
||||
|
10
oscillate.c
10
oscillate.c
@ -49,6 +49,16 @@ static int OscillationTask(void *data){
|
||||
errStatus = self->pMot->pDriver->TryAndFixIt(self->pMot->pDriver,code,pos);
|
||||
self->errorCount++;
|
||||
if(errStatus == MOTFAIL){
|
||||
/*
|
||||
try driving the other way on a serious error
|
||||
*/
|
||||
if(self->nextTargetFlag == 1){
|
||||
pos = self->upperLimit;
|
||||
self->nextTargetFlag = 0;
|
||||
} else {
|
||||
pos = self->lowerLimit;
|
||||
self->nextTargetFlag = 1;
|
||||
}
|
||||
MotorRun(self->pMot,self->pCon,pos);
|
||||
}
|
||||
break;
|
||||
|
4
scan.h
4
scan.h
@ -6,6 +6,8 @@
|
||||
|
||||
Mark Koennecke, October 1997
|
||||
|
||||
Extracted scan variable: Mark Koennecke, November 2004
|
||||
|
||||
copyright: see copyright.h
|
||||
-----------------------------------------------------------------------------*/
|
||||
#ifndef SICSSCAN1
|
||||
@ -16,7 +18,7 @@
|
||||
|
||||
/*------------------------- live & death ----------------------------------*/
|
||||
pScanData CreateScanObject(char *pRecover, char *pHeader,
|
||||
pCounter pCount);
|
||||
pCounter pCount, char *objName);
|
||||
void DeleteScanObject(void *self);
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int AddScanVar(pScanData self, SicsInterp *pSics, SConnection *pCon,
|
||||
|
24
scan.i
24
scan.i
@ -6,16 +6,9 @@
|
||||
Mark Koennecke, October 1997
|
||||
----------------------------------------------------------------------------*/
|
||||
#include "sdynar.h"
|
||||
#include "scanvar.h"
|
||||
#include "stringdict.h"
|
||||
|
||||
typedef struct {
|
||||
char Name[132];
|
||||
pIDrivable pInter;
|
||||
pDummy pObject;
|
||||
float fStart;
|
||||
float fStep;
|
||||
float *fData;
|
||||
int dataList;
|
||||
}VarEntry, *pVarEntry;
|
||||
/*--------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
int i;
|
||||
@ -28,6 +21,7 @@
|
||||
pObjectDescriptor pDes;
|
||||
pICallBack pCall;
|
||||
pDynar pScanVar;
|
||||
char objectName[132];
|
||||
int iScanVar;
|
||||
int iNP;
|
||||
int iMode;
|
||||
@ -50,6 +44,7 @@
|
||||
int (*CollectScanData)
|
||||
(pScanData self,
|
||||
int iP);
|
||||
pStringDict scanFunctions;
|
||||
long lPos;
|
||||
int posSoft;
|
||||
void *pCounterData;
|
||||
@ -63,3 +58,14 @@
|
||||
void *pSpecial;
|
||||
} ScanData;
|
||||
|
||||
|
||||
/*
|
||||
internal helper functions for scan implementations
|
||||
*/
|
||||
|
||||
/*
|
||||
CollectCounterData collects all the data from the configured counter
|
||||
ans stows it away
|
||||
*/
|
||||
CountEntry CollectCounterData(pScanData self);
|
||||
void InitCountEntry(pCountEntry pCount);
|
||||
|
344
scan.tex
344
scan.tex
@ -1,37 +1,46 @@
|
||||
\subsection{Scan}
|
||||
The first version of the scan command was implemented in Tcl. This prooved
|
||||
to be inefficient. Therefore the main loop for scan was reimplemented in
|
||||
C. A scan is in principle simple. However some complications are due to the
|
||||
fact that data files need to be written. Disk files need to be updated after
|
||||
each scan point. It must be possible to create derivations of the scan
|
||||
command which create other data formats or scan strategies. This
|
||||
configurability is catered for the function pointers in the ScanData
|
||||
structure. Individual functions can be exchanged and thus differently
|
||||
behaving scans created.
|
||||
to be inefficient. Therefore scan was reimplemented in C. Scanning
|
||||
seems to be simple but is not because of the many special cases
|
||||
involved:
|
||||
\begin{itemize}
|
||||
\item Scans must be interruptable and continuable
|
||||
\item Data files need to be written in different formats
|
||||
\item Different output has to be generated at various steps
|
||||
\item In polarization measurements, several points with different
|
||||
magnetic field orientations need to be measured at the same instrument
|
||||
position.
|
||||
\item Users might want to be specify complex scan paths or scan on
|
||||
logarithmic axis.
|
||||
\end{itemize}
|
||||
|
||||
I order to cope with all this, the scan module is modifiable in two
|
||||
ways: For each step of the scanning process there is an overloadable
|
||||
function in the scan data structure. The first way to modify scan
|
||||
behavious thus is to write new functions in C and to assign them to
|
||||
the scan module. In order to support scriptable scans another system
|
||||
is in place: Stored in a string dictioanary there are the names of
|
||||
SICS functions which will be called at each scan operation. The scan
|
||||
functions then invoke the functions specified. In order for this to
|
||||
work, the scan must be configured "newscan". These two schemes exits
|
||||
because the scan module is in transition to a refactoring towards the
|
||||
second scheme.
|
||||
|
||||
The principal setup thus is a central scan object which deals with
|
||||
all the scan management: storing variables, positions, counting
|
||||
results etc. and the configuration of the scan. This is augmented by
|
||||
libraries of scan functions which get invoked at the various
|
||||
steps. There is a standard scan library which is doumented here as well.
|
||||
|
||||
|
||||
Another complication is, that users might want to interrupt scans and
|
||||
restart from the last safe position. For this purpose
|
||||
there exists the recover option.
|
||||
|
||||
Scan also uses a scheme for creating scan data data files from a
|
||||
template. For more information about the template file see the SICS Managers
|
||||
documentation.
|
||||
|
||||
There are currently two schemes for modifying scans: The first works
|
||||
by implementing different scan handling functions and to assign them
|
||||
to the function pointers in the ScanData structure. The second works
|
||||
by defining a macro which will be called at each scan point and which
|
||||
has to return the a list with the counts and monitors collected.
|
||||
|
||||
This has grown to be overly complex. A path for a redesign might
|
||||
follow the idea of configurable functions to be called at various
|
||||
steps in scan processing which is already partly implemented.
|
||||
|
||||
|
||||
|
||||
\subsubsection{Scan Variables}
|
||||
Scan variables are held in this data structure:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap1}
|
||||
$\langle$scandata {\footnotesize ?}$\rangle\equiv$
|
||||
$\langle$scanvar {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
@ -42,7 +51,116 @@ $\langle$scandata {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ float fStart;@\\
|
||||
\mbox{}\verb@ float fStep;@\\
|
||||
\mbox{}\verb@ float *fData;@\\
|
||||
\mbox{}\verb@ int dataList;@\\
|
||||
\mbox{}\verb@ }VarEntry, *pVarEntry;@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
The VarEntry structure holds the data for each single scan variable.
|
||||
These are its name, its object data structures, the start and step
|
||||
values for the scan and in dataList the positions actually reached
|
||||
during the scan.
|
||||
|
||||
Scan variables have an interface:
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
$\langle$scanvarint {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/**@\\
|
||||
\mbox{}\verb@ * MakeScanVar creates a scan variable. All the necessary checks are @\\
|
||||
\mbox{}\verb@ * performed@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pSics The interpreter in order to locate the variable.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pCon A connection object for error reporting@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param name The name of the variable to scan@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param start The start position from which to scan@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param step The step width with which to scan.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@return A pointer to a new scan variable object on success, NULL@\\
|
||||
\mbox{}\verb@ * else@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ pVarEntry MakeScanVar(SicsInterp *pSics, SConnection *pCon, char@\\
|
||||
\mbox{}\verb@ *name, float start, float step);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * InitScanVar clears the list of scan points@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pvar The scna variable to clear@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ void InitScanVar(pVarEntry pVar);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * DeleteVarEntry deletes a scan variable.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pData The scan variable entry to delete.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ void DeleteVarEntry(void *pData);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * ScanVarName returns the name of the scan variable@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pVar The scan variable to query.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@return The name of the scan variable. Do not delete pointer.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ char *ScanVarName(pVarEntry pVar);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * ScanVarStart returns the start value for the scan @\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pVar The scan variable to query.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@return The start point for the scan.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ float ScanVarStart(pVarEntry pVar);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * ScanVarStep returns the start value for the scan @\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pVar The scan variable to query.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@return The step width for the scan.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ float ScanVarStep(pVarEntry pVar);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * StartScanVar starts the scan variable to drive to the next@\\
|
||||
\mbox{}\verb@ * position.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pVar The scan variable to start.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pCon The connection to report errors to.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param i The position number to drive to@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@return 1 on success, 0 on failure@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int StartScanVar(pVarEntry pVar, SConnection *pCon, int i);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * AppendScanVar appends a position to the list of positions@\\
|
||||
\mbox{}\verb@ * reached while scanning this variable.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pVar The scan variable to append to.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pos The position to append.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ void AppendScanVar(pVarEntry pVar, float pos);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * GetScanVarPos returns a position for an index.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pVar The scan variable to append to.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param i The position number to retrieve@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@return The positiopn or -99999.99 for an error@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ float GetScanVarPos(pVarEntry pVar, int i);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * CopyScanVar copies the scan positions to the array given.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param pVar The scan variable to copy from@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param fData The array to copy to.@\\
|
||||
\mbox{}\verb@ * @{\tt @}\verb@param np The number of slots in fData.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ void CopyScanVar(pVarEntry pVar, float *fData, int np);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\subsubsection{The Scan Object}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
$\langle$scandata {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ typedef struct {@\\
|
||||
\mbox{}\verb@ int i;@\\
|
||||
@ -55,6 +173,7 @@ $\langle$scandata {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ pObjectDescriptor pDes;@\\
|
||||
\mbox{}\verb@ pICallBack pCall;@\\
|
||||
\mbox{}\verb@ pDynar pScanVar;@\\
|
||||
\mbox{}\verb@ char objectName[132];@\\
|
||||
\mbox{}\verb@ int iScanVar;@\\
|
||||
\mbox{}\verb@ int iNP;@\\
|
||||
\mbox{}\verb@ int iMode;@\\
|
||||
@ -77,6 +196,7 @@ $\langle$scandata {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ int (*CollectScanData)@\\
|
||||
\mbox{}\verb@ (pScanData self,@\\
|
||||
\mbox{}\verb@ int iP);@\\
|
||||
\mbox{}\verb@ pStringDict scanFunctions;@\\
|
||||
\mbox{}\verb@ long lPos;@\\
|
||||
\mbox{}\verb@ int posSoft;@\\
|
||||
\mbox{}\verb@ void *pCounterData;@\\
|
||||
@ -98,11 +218,6 @@ $\langle$scandata {\footnotesize ?}$\rangle\equiv$
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
The VarEntry structure holds the data for each single scan variable.
|
||||
These are its name, its object data structures, the start and step
|
||||
values for the scan and in fData the positions actually reached during
|
||||
the scan.
|
||||
|
||||
The CountEntry structure holds the entries for one counting
|
||||
operations. These are the lCounts collected, up to 10 monitors and the
|
||||
time needed for counting. This is the time read from the counter box.
|
||||
@ -158,6 +273,8 @@ This function together with ScanDrive and the data writing functions allow for
|
||||
\item[CollectScanData] reads all the scan data into the scan's data
|
||||
structures after any scan point. Overload this if a different storage
|
||||
scheme is required especiallay for polarising scans.
|
||||
\item[scanFunctions] A string dictionary holding the names of the
|
||||
configured functions for the various steps of the scan.
|
||||
\item[posSoft] is a flag which is true if scan variable are stored with
|
||||
soft position, i.e. with zeropoints applied.
|
||||
\item[pCounterData] is a pointer to a counter structure. This defines the
|
||||
@ -184,14 +301,14 @@ The functional interface to the scan module includes the following
|
||||
functions:
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap2}
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
$\langle$scaninter {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*------------------------- live & death ----------------------------------*/@\\
|
||||
\mbox{}\verb@ pScanData CreateScanObject(char *pRecover, char *pHeader, @\\
|
||||
\mbox{}\verb@ pCounter pCount);@\\
|
||||
\mbox{}\verb@ pCounter pCount, char *objName);@\\
|
||||
\mbox{}\verb@ void DeleteScanObject(void *self);@\\
|
||||
\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@ int AddScanVar(pScanData self, SicsInterp *pSics, SConnection *pCon, @\\
|
||||
@ -320,8 +437,125 @@ for the scan object.
|
||||
\item[ScanWrapper] is the SICS interpreter object function for
|
||||
interacting with the scan module.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{The Standard Scan Library}
|
||||
The following functions constitute the standard scan library. Please
|
||||
note that the scan file data format is driven by a template. The
|
||||
format of this template is documented in the SICS managers
|
||||
documentation.
|
||||
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap3}
|
||||
\begin{minipage}{\linewidth} \label{scrap5}
|
||||
$\langle$stdscan {\footnotesize ?}$\rangle\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * write the header of the scan file@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int WriteHeader(pScanData self);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * WriteScanPoints is called for each point to write the scan data@\\
|
||||
\mbox{}\verb@ * to screen and to file.@\\
|
||||
\mbox{}\verb@ */ @\\
|
||||
\mbox{}\verb@ int WriteScanPoints(pScanData self, int iPoint);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * Called before the scan to prepare. The default implementation@\\
|
||||
\mbox{}\verb@ * checks if all scan positions are available and configures the@\\
|
||||
\mbox{}\verb@ * counter.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int PrepareScan(pScanData self);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * second version of PrepareScan which does not check scan limits@\\
|
||||
\mbox{}\verb@ */ @\\
|
||||
\mbox{}\verb@ int NonCheckPrepare(pScanData self);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * ScanDrive handles driving to the scan point iPoint.@\\
|
||||
\mbox{}\verb@ */ @\\
|
||||
\mbox{}\verb@ int ScanDrive(pScanData self, int iPoint);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * ScanCount is called at each scan step to do the counting.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int ScanCount(pScanData self, int iPoint);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * CollectScanData stores the scans count results into @\\
|
||||
\mbox{}\verb@ * the scan data structure and prints the information about the@\\
|
||||
\mbox{}\verb@ * scan progress.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int CollectScanData(pScanData self, int iPoint);@\\
|
||||
\mbox{}\verb@ int CollectScanDataJochen(pScanData self, int iPoint);@\\
|
||||
\mbox{}\verb@/*===================================================================*/@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * Script invocation for writing the scan header.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int ScriptWriteHeader(pScanData self); @\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * Script writing each scan point@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int ScriptWriteScanPoints(pScanData self, int iPoint);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * Script preparation of the scan.@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int ScriptPrepareScan(pScanData self);@\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * Script driving to a scan point@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int ScriptScanDrive(pScanData self, int iPoint); @\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * Script counting a scan point@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int ScriptScanCount(pScanData self, int iPoint); @\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * Script collecting scan data for each scan point@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ int ScriptScanCollect(pScanData self, int iPoint); @\\
|
||||
\mbox{}\verb@ /**@\\
|
||||
\mbox{}\verb@ * ConfigureScript assigns the script invocation functions for@\\
|
||||
\mbox{}\verb@ * scan@\\
|
||||
\mbox{}\verb@ */@\\
|
||||
\mbox{}\verb@ void ConfigureScript(pScanData self);@\\
|
||||
\mbox{}\verb@/*=====================================================================*/@\\
|
||||
\mbox{}\verb@ int StandardScanWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,@\\
|
||||
\mbox{}\verb@ int argc, char *argv[]);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
\footnotesize\addtolength{\baselineskip}{-1ex}
|
||||
\begin{list}{}{\setlength{\itemsep}{-\parsep}\setlength{\itemindent}{-\leftmargin}}
|
||||
\item Macro referenced in scrap ?.
|
||||
\end{list}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap6}
|
||||
\verb@"scanvar.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*-----------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ Header file for the SICS ScanVariable. This is a support module for@\\
|
||||
\mbox{}\verb@ the SICS scan system.@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Evolved during refactoring scan in November 2004@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ copyright: see file COPYRIGHT@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, November 2004@\\
|
||||
\mbox{}\verb@-------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSSCANVAR@\\
|
||||
\mbox{}\verb@#define SICSSCANVAR@\\
|
||||
\mbox{}\verb@#include "sics.h"@\\
|
||||
\mbox{}\verb@@$\langle$scanvar {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@/*---------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@@$\langle$scanvarint {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap7}
|
||||
\verb@"scan.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
@ -333,6 +567,8 @@ interacting with the scan module.
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Mark Koennecke, October 1997@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Extracted scan variable: Mark Koennecke, November 2004@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@-----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSSCAN1@\\
|
||||
@ -348,7 +584,7 @@ interacting with the scan module.
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap4}
|
||||
\begin{minipage}{\linewidth} \label{scrap8}
|
||||
\verb@"scan.i"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
@ -360,7 +596,45 @@ interacting with the scan module.
|
||||
\mbox{}\verb@ Mark Koennecke, October 1997@\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#include "sdynar.h"@\\
|
||||
\mbox{}\verb@#include "scanvar.h"@\\
|
||||
\mbox{}\verb@#include "stringdict.h"@\\
|
||||
\mbox{}\verb@@$\langle$scandata {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*@\\
|
||||
\mbox{}\verb@ internal helper functions for scan implementations@\\
|
||||
\mbox{}\verb@*/@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*@\\
|
||||
\mbox{}\verb@ CollectCounterData collects all the data from the configured counter@\\
|
||||
\mbox{}\verb@ ans stows it away@\\
|
||||
\mbox{}\verb@*/@\\
|
||||
\mbox{}\verb@CountEntry CollectCounterData(pScanData self);@\\
|
||||
\mbox{}\verb@void InitCountEntry(pCountEntry pCount);@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
\end{minipage}\\[4ex]
|
||||
\end{flushleft}
|
||||
\begin{flushleft} \small
|
||||
\begin{minipage}{\linewidth} \label{scrap9}
|
||||
\verb@"stdscan.h"@ {\footnotesize ? }$\equiv$
|
||||
\vspace{-1ex}
|
||||
\begin{list}{}{} \item
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@/*--------------------------------------------------------------------------@\\
|
||||
\mbox{}\verb@ S T A N D A R D S C A N@\\
|
||||
\mbox{}\verb@ @\\
|
||||
\mbox{}\verb@ This is a library of scan functions for the SICS standard scan. @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ copyright: see copyright.h@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ Extracted from scan.c: Mark Koennecke, November 2004 @\\
|
||||
\mbox{}\verb@----------------------------------------------------------------------------*/@\\
|
||||
\mbox{}\verb@#ifndef SICSSTDSCAN@\\
|
||||
\mbox{}\verb@#define SICSSTDSCAN@\\
|
||||
\mbox{}\verb@@$\langle$stdscan {\footnotesize ?}$\rangle$\verb@@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@#endif@\\
|
||||
\mbox{}\verb@@$\diamond$
|
||||
\end{list}
|
||||
\vspace{-2ex}
|
||||
|
284
scan.w
284
scan.w
@ -1,35 +1,44 @@
|
||||
\subsection{Scan}
|
||||
The first version of the scan command was implemented in Tcl. This prooved
|
||||
to be inefficient. Therefore the main loop for scan was reimplemented in
|
||||
C. A scan is in principle simple. However some complications are due to the
|
||||
fact that data files need to be written. Disk files need to be updated after
|
||||
each scan point. It must be possible to create derivations of the scan
|
||||
command which create other data formats or scan strategies. This
|
||||
configurability is catered for the function pointers in the ScanData
|
||||
structure. Individual functions can be exchanged and thus differently
|
||||
behaving scans created.
|
||||
to be inefficient. Therefore scan was reimplemented in C. Scanning
|
||||
seems to be simple but is not because of the many special cases
|
||||
involved:
|
||||
\begin{itemize}
|
||||
\item Scans must be interruptable and continuable
|
||||
\item Data files need to be written in different formats
|
||||
\item Different output has to be generated at various steps
|
||||
\item In polarization measurements, several points with different
|
||||
magnetic field orientations need to be measured at the same instrument
|
||||
position.
|
||||
\item Users might want to be specify complex scan paths or scan on
|
||||
logarithmic axis.
|
||||
\end{itemize}
|
||||
|
||||
I order to cope with all this, the scan module is modifiable in two
|
||||
ways: For each step of the scanning process there is an overloadable
|
||||
function in the scan data structure. The first way to modify scan
|
||||
behavious thus is to write new functions in C and to assign them to
|
||||
the scan module. In order to support scriptable scans another system
|
||||
is in place: Stored in a string dictioanary there are the names of
|
||||
SICS functions which will be called at each scan operation. The scan
|
||||
functions then invoke the functions specified. In order for this to
|
||||
work, the scan must be configured "newscan". These two schemes exits
|
||||
because the scan module is in transition to a refactoring towards the
|
||||
second scheme.
|
||||
|
||||
The principal setup thus is a central scan object which deals with
|
||||
all the scan management: storing variables, positions, counting
|
||||
results etc. and the configuration of the scan. This is augmented by
|
||||
libraries of scan functions which get invoked at the various
|
||||
steps. There is a standard scan library which is doumented here as well.
|
||||
|
||||
|
||||
Another complication is, that users might want to interrupt scans and
|
||||
restart from the last safe position. For this purpose
|
||||
there exists the recover option.
|
||||
|
||||
Scan also uses a scheme for creating scan data data files from a
|
||||
template. For more information about the template file see the SICS Managers
|
||||
documentation.
|
||||
|
||||
There are currently two schemes for modifying scans: The first works
|
||||
by implementing different scan handling functions and to assign them
|
||||
to the function pointers in the ScanData structure. The second works
|
||||
by defining a macro which will be called at each scan point and which
|
||||
has to return the a list with the counts and monitors collected.
|
||||
|
||||
This has grown to be overly complex. A path for a redesign might
|
||||
follow the idea of configurable functions to be called at various
|
||||
steps in scan processing which is already partly implemented.
|
||||
|
||||
|
||||
@d scandata @{
|
||||
|
||||
\subsubsection{Scan Variables}
|
||||
Scan variables are held in this data structure:
|
||||
@d scanvar @{
|
||||
typedef struct {
|
||||
char Name[132];
|
||||
pIDrivable pInter;
|
||||
@ -37,7 +46,91 @@ steps in scan processing which is already partly implemented.
|
||||
float fStart;
|
||||
float fStep;
|
||||
float *fData;
|
||||
int dataList;
|
||||
}VarEntry, *pVarEntry;
|
||||
@}
|
||||
The VarEntry structure holds the data for each single scan variable.
|
||||
These are its name, its object data structures, the start and step
|
||||
values for the scan and in dataList the positions actually reached
|
||||
during the scan.
|
||||
|
||||
Scan variables have an interface:
|
||||
@d scanvarint @{
|
||||
/**
|
||||
* MakeScanVar creates a scan variable. All the necessary checks are
|
||||
* performed
|
||||
* @@param pSics The interpreter in order to locate the variable.
|
||||
* @@param pCon A connection object for error reporting
|
||||
* @@param name The name of the variable to scan
|
||||
* @@param start The start position from which to scan
|
||||
* @@param step The step width with which to scan.
|
||||
* @@return A pointer to a new scan variable object on success, NULL
|
||||
* else
|
||||
*/
|
||||
pVarEntry MakeScanVar(SicsInterp *pSics, SConnection *pCon, char
|
||||
*name, float start, float step);
|
||||
/**
|
||||
* InitScanVar clears the list of scan points
|
||||
* @@param pvar The scna variable to clear
|
||||
*/
|
||||
void InitScanVar(pVarEntry pVar);
|
||||
/**
|
||||
* DeleteVarEntry deletes a scan variable.
|
||||
* @@param pData The scan variable entry to delete.
|
||||
*/
|
||||
void DeleteVarEntry(void *pData);
|
||||
/**
|
||||
* ScanVarName returns the name of the scan variable
|
||||
* @@param pVar The scan variable to query.
|
||||
* @@return The name of the scan variable. Do not delete pointer.
|
||||
*/
|
||||
char *ScanVarName(pVarEntry pVar);
|
||||
/**
|
||||
* ScanVarStart returns the start value for the scan
|
||||
* @@param pVar The scan variable to query.
|
||||
* @@return The start point for the scan.
|
||||
*/
|
||||
float ScanVarStart(pVarEntry pVar);
|
||||
/**
|
||||
* ScanVarStep returns the start value for the scan
|
||||
* @@param pVar The scan variable to query.
|
||||
* @@return The step width for the scan.
|
||||
*/
|
||||
float ScanVarStep(pVarEntry pVar);
|
||||
/**
|
||||
* StartScanVar starts the scan variable to drive to the next
|
||||
* position.
|
||||
* @@param pVar The scan variable to start.
|
||||
* @@param pCon The connection to report errors to.
|
||||
* @@param i The position number to drive to
|
||||
* @@return 1 on success, 0 on failure
|
||||
*/
|
||||
int StartScanVar(pVarEntry pVar, SConnection *pCon, int i);
|
||||
/**
|
||||
* AppendScanVar appends a position to the list of positions
|
||||
* reached while scanning this variable.
|
||||
* @@param pVar The scan variable to append to.
|
||||
* @@param pos The position to append.
|
||||
*/
|
||||
void AppendScanVar(pVarEntry pVar, float pos);
|
||||
/**
|
||||
* GetScanVarPos returns a position for an index.
|
||||
* @@param pVar The scan variable to append to.
|
||||
* @@param i The position number to retrieve
|
||||
* @@return The positiopn or -99999.99 for an error
|
||||
*/
|
||||
float GetScanVarPos(pVarEntry pVar, int i);
|
||||
/**
|
||||
* CopyScanVar copies the scan positions to the array given.
|
||||
* @@param pVar The scan variable to copy from
|
||||
* @@param fData The array to copy to.
|
||||
* @@param np The number of slots in fData.
|
||||
*/
|
||||
void CopyScanVar(pVarEntry pVar, float *fData, int np);
|
||||
@}
|
||||
|
||||
\subsubsection{The Scan Object}
|
||||
@d scandata @{
|
||||
/*--------------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
int i;
|
||||
@ -50,6 +143,7 @@ steps in scan processing which is already partly implemented.
|
||||
pObjectDescriptor pDes;
|
||||
pICallBack pCall;
|
||||
pDynar pScanVar;
|
||||
char objectName[132];
|
||||
int iScanVar;
|
||||
int iNP;
|
||||
int iMode;
|
||||
@ -72,6 +166,7 @@ steps in scan processing which is already partly implemented.
|
||||
int (*CollectScanData)
|
||||
(pScanData self,
|
||||
int iP);
|
||||
pStringDict scanFunctions;
|
||||
long lPos;
|
||||
int posSoft;
|
||||
void *pCounterData;
|
||||
@ -86,10 +181,6 @@ steps in scan processing which is already partly implemented.
|
||||
} ScanData;
|
||||
@}
|
||||
|
||||
The VarEntry structure holds the data for each single scan variable.
|
||||
These are its name, its object data structures, the start and step
|
||||
values for the scan and in fData the positions actually reached during
|
||||
the scan.
|
||||
|
||||
The CountEntry structure holds the entries for one counting
|
||||
operations. These are the lCounts collected, up to 10 monitors and the
|
||||
@ -146,6 +237,8 @@ This function together with ScanDrive and the data writing functions allow for
|
||||
\item[CollectScanData] reads all the scan data into the scan's data
|
||||
structures after any scan point. Overload this if a different storage
|
||||
scheme is required especiallay for polarising scans.
|
||||
\item[scanFunctions] A string dictionary holding the names of the
|
||||
configured functions for the various steps of the scan.
|
||||
\item[posSoft] is a flag which is true if scan variable are stored with
|
||||
soft position, i.e. with zeropoints applied.
|
||||
\item[pCounterData] is a pointer to a counter structure. This defines the
|
||||
@ -174,7 +267,7 @@ functions:
|
||||
@d scaninter @{
|
||||
/*------------------------- live & death ----------------------------------*/
|
||||
pScanData CreateScanObject(char *pRecover, char *pHeader,
|
||||
pCounter pCount);
|
||||
pCounter pCount, char *objName);
|
||||
void DeleteScanObject(void *self);
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int AddScanVar(pScanData self, SicsInterp *pSics, SConnection *pCon,
|
||||
@ -295,6 +388,105 @@ for the scan object.
|
||||
\item[ScanWrapper] is the SICS interpreter object function for
|
||||
interacting with the scan module.
|
||||
\end{description}
|
||||
|
||||
\subsubsection{The Standard Scan Library}
|
||||
The following functions constitute the standard scan library. Please
|
||||
note that the scan file data format is driven by a template. The
|
||||
format of this template is documented in the SICS managers
|
||||
documentation.
|
||||
|
||||
@d stdscan @{
|
||||
/**
|
||||
* write the header of the scan file
|
||||
*/
|
||||
int WriteHeader(pScanData self);
|
||||
/**
|
||||
* WriteScanPoints is called for each point to write the scan data
|
||||
* to screen and to file.
|
||||
*/
|
||||
int WriteScanPoints(pScanData self, int iPoint);
|
||||
/**
|
||||
* Called before the scan to prepare. The default implementation
|
||||
* checks if all scan positions are available and configures the
|
||||
* counter.
|
||||
*/
|
||||
int PrepareScan(pScanData self);
|
||||
/**
|
||||
* second version of PrepareScan which does not check scan limits
|
||||
*/
|
||||
int NonCheckPrepare(pScanData self);
|
||||
/**
|
||||
* ScanDrive handles driving to the scan point iPoint.
|
||||
*/
|
||||
int ScanDrive(pScanData self, int iPoint);
|
||||
/**
|
||||
* ScanCount is called at each scan step to do the counting.
|
||||
*/
|
||||
int ScanCount(pScanData self, int iPoint);
|
||||
/**
|
||||
* CollectScanData stores the scans count results into
|
||||
* the scan data structure and prints the information about the
|
||||
* scan progress.
|
||||
*/
|
||||
int CollectScanData(pScanData self, int iPoint);
|
||||
int CollectScanDataJochen(pScanData self, int iPoint);
|
||||
/*===================================================================*/
|
||||
/**
|
||||
* Script invocation for writing the scan header.
|
||||
*/
|
||||
int ScriptWriteHeader(pScanData self);
|
||||
/**
|
||||
* Script writing each scan point
|
||||
*/
|
||||
int ScriptWriteScanPoints(pScanData self, int iPoint);
|
||||
/**
|
||||
* Script preparation of the scan.
|
||||
*/
|
||||
int ScriptPrepareScan(pScanData self);
|
||||
/**
|
||||
* Script driving to a scan point
|
||||
*/
|
||||
int ScriptScanDrive(pScanData self, int iPoint);
|
||||
/**
|
||||
* Script counting a scan point
|
||||
*/
|
||||
int ScriptScanCount(pScanData self, int iPoint);
|
||||
/**
|
||||
* Script collecting scan data for each scan point
|
||||
*/
|
||||
int ScriptScanCollect(pScanData self, int iPoint);
|
||||
/**
|
||||
* ConfigureScript assigns the script invocation functions for
|
||||
* scan
|
||||
*/
|
||||
void ConfigureScript(pScanData self);
|
||||
/*=====================================================================*/
|
||||
int StandardScanWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
@}
|
||||
|
||||
|
||||
|
||||
@o scanvar.h @{
|
||||
/*-----------------------------------------------------------------------
|
||||
Header file for the SICS ScanVariable. This is a support module for
|
||||
the SICS scan system.
|
||||
|
||||
Evolved during refactoring scan in November 2004
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, November 2004
|
||||
-------------------------------------------------------------------------*/
|
||||
#ifndef SICSSCANVAR
|
||||
#define SICSSCANVAR
|
||||
#include "sics.h"
|
||||
@<scanvar@>
|
||||
/*---------------------------------------------------------------------*/
|
||||
@<scanvarint@>
|
||||
#endif
|
||||
@}
|
||||
|
||||
@o scan.h @{
|
||||
/*---------------------------------------------------------------------------
|
||||
S C A N
|
||||
@ -303,6 +495,8 @@ interacting with the scan module.
|
||||
|
||||
Mark Koennecke, October 1997
|
||||
|
||||
Extracted scan variable: Mark Koennecke, November 2004
|
||||
|
||||
copyright: see copyright.h
|
||||
-----------------------------------------------------------------------------*/
|
||||
#ifndef SICSSCAN1
|
||||
@ -322,9 +516,37 @@ interacting with the scan module.
|
||||
Mark Koennecke, October 1997
|
||||
----------------------------------------------------------------------------*/
|
||||
#include "sdynar.h"
|
||||
#include "scanvar.h"
|
||||
#include "stringdict.h"
|
||||
@<scandata@>
|
||||
|
||||
/*
|
||||
internal helper functions for scan implementations
|
||||
*/
|
||||
|
||||
/*
|
||||
CollectCounterData collects all the data from the configured counter
|
||||
ans stows it away
|
||||
*/
|
||||
CountEntry CollectCounterData(pScanData self);
|
||||
void InitCountEntry(pCountEntry pCount);
|
||||
@}
|
||||
|
||||
|
||||
@o stdscan.h @{
|
||||
/*--------------------------------------------------------------------------
|
||||
S T A N D A R D S C A N
|
||||
|
||||
This is a library of scan functions for the SICS standard scan.
|
||||
|
||||
copyright: see copyright.h
|
||||
|
||||
Extracted from scan.c: Mark Koennecke, November 2004
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef SICSSTDSCAN
|
||||
#define SICSSTDSCAN
|
||||
@<stdscan@>
|
||||
|
||||
#endif
|
||||
@}
|
||||
|
||||
|
154
scanvar.c
Normal file
154
scanvar.c
Normal file
@ -0,0 +1,154 @@
|
||||
/*-----------------------------------------------------------------------
|
||||
Implementation file for the SICS ScanVariable. This is a support module
|
||||
for the SICS scan system.
|
||||
|
||||
Evolved during refactoring scan in November 2004
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, November 2004
|
||||
-------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "fortify.h"
|
||||
#include "sics.h"
|
||||
#include "scanvar.h"
|
||||
#include "lld.h"
|
||||
#include "devexec.h"
|
||||
/*----------------------------------------------------------------------*/
|
||||
pVarEntry MakeScanVar(SicsInterp *pSics, SConnection *pCon, char
|
||||
*name, float start, float step){
|
||||
CommandList *pCom = NULL;
|
||||
pIDrivable pDriv = NULL;
|
||||
pDummy pData = NULL;
|
||||
pVarEntry pVar = NULL;
|
||||
char pBueffel[512];
|
||||
|
||||
/*
|
||||
allocate space
|
||||
*/
|
||||
pVar = (pVarEntry)malloc(sizeof(VarEntry));
|
||||
if(pVar == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory allocating scan variable",eError);
|
||||
return NULL;
|
||||
}
|
||||
memset(pVar,0,sizeof(VarEntry));
|
||||
|
||||
/* find the thing */
|
||||
pCom = FindCommand(pSics,name);
|
||||
if(!pCom){
|
||||
snprintf(pBueffel,511,"ERROR: Cannot find variable %s to scan",name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return NULL;
|
||||
}
|
||||
pData = (pDummy)pCom->pData;
|
||||
if(!pData){
|
||||
snprintf(pBueffel,511,"ERROR: Cannot find data for variable %s",name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return NULL;
|
||||
}
|
||||
pDriv = pData->pDescriptor->GetInterface(pData,DRIVEID);
|
||||
if(!pDriv){
|
||||
snprintf(pBueffel,511,
|
||||
"ERROR: variable %s is NOT driveable and cannot be scanned",name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* got everything, fill in the VarEntry structure */
|
||||
strcpy(pVar->Name,name);
|
||||
pVar->pInter = pDriv;
|
||||
pVar->pObject = pData;
|
||||
pVar->fStart = start;
|
||||
pVar->fStep = step;
|
||||
pVar->dataList = LLDcreate(sizeof(float));
|
||||
|
||||
return pVar;
|
||||
}
|
||||
/*------------------------------------------------------------------*/
|
||||
void InitScanVar(pVarEntry pVar){
|
||||
LLDdelete(pVar->dataList);
|
||||
pVar->dataList = LLDcreate(sizeof(float));
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
void DeleteVarEntry(void *pData){
|
||||
pVarEntry pVar = NULL;
|
||||
|
||||
pVar = (pVarEntry)pData;
|
||||
|
||||
if(pVar == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
if(pVar->fData){
|
||||
free(pVar->fData);
|
||||
}
|
||||
LLDdelete(pVar->dataList);
|
||||
free(pVar);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
char *ScanVarName(pVarEntry pVar){
|
||||
return pVar->Name;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
float ScanVarStart(pVarEntry pVar){
|
||||
return pVar->fStart;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
float ScanVarStep(pVarEntry pVar){
|
||||
return pVar->fStep;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int StartScanVar(pVarEntry pVar, SConnection *pCon, int i){
|
||||
float fVal;
|
||||
pDummy pDum;
|
||||
char pBueffel[512];
|
||||
int status;
|
||||
|
||||
pDum = (pDummy)pVar->pObject;
|
||||
fVal = pVar->fStart + i * pVar->fStep;
|
||||
status = StartDevice(pServ->pExecutor,
|
||||
pVar->Name,
|
||||
pDum->pDescriptor,
|
||||
pVar->pObject,
|
||||
pCon,
|
||||
fVal);
|
||||
if(!status){
|
||||
snprintf(pBueffel,511,"ERROR: Failed to start %s",pVar->Name);
|
||||
SCWrite(pCon,pBueffel,eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void AppendScanVar(pVarEntry pVar, float pos){
|
||||
float fVal = pos;
|
||||
LLDnodeAppendFrom(pVar->dataList,&fVal);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
float GetScanVarPos(pVarEntry pVar, int i){
|
||||
int count = 0, status;
|
||||
|
||||
status = LLDnodePtr2First(pVar->dataList);
|
||||
while(count < i && (status = LLDnodePtr2Next(pVar->dataList)) != 0){
|
||||
count++;
|
||||
}
|
||||
if(count == i){
|
||||
return LLDnodeFloat(pVar->dataList);
|
||||
} else {
|
||||
return -99999.99;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
void CopyScanVar(pVarEntry pVar, float *fData, int np){
|
||||
int i, count = 0, status;
|
||||
|
||||
status = LLDnodePtr2First(pVar->dataList);
|
||||
while(status > 0 && count < np){
|
||||
fData[count] = LLDnodeFloat(pVar->dataList);
|
||||
count++;
|
||||
status = LLDnodePtr2Next(pVar->dataList);
|
||||
}
|
||||
}
|
||||
|
100
scanvar.h
Normal file
100
scanvar.h
Normal file
@ -0,0 +1,100 @@
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
Header file for the SICS ScanVariable. This is a support module for
|
||||
the SICS scan system.
|
||||
|
||||
Evolved during refactoring scan in November 2004
|
||||
|
||||
copyright: see file COPYRIGHT
|
||||
|
||||
Mark Koennecke, November 2004
|
||||
-------------------------------------------------------------------------*/
|
||||
#ifndef SICSSCANVAR
|
||||
#define SICSSCANVAR
|
||||
#include "sics.h"
|
||||
|
||||
typedef struct {
|
||||
char Name[132];
|
||||
pIDrivable pInter;
|
||||
pDummy pObject;
|
||||
float fStart;
|
||||
float fStep;
|
||||
float *fData;
|
||||
int dataList;
|
||||
}VarEntry, *pVarEntry;
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* MakeScanVar creates a scan variable. All the necessary checks are
|
||||
* performed
|
||||
* @param pSics The interpreter in order to locate the variable.
|
||||
* @param pCon A connection object for error reporting
|
||||
* @param name The name of the variable to scan
|
||||
* @param start The start position from which to scan
|
||||
* @param step The step width with which to scan.
|
||||
* @return A pointer to a new scan variable object on success, NULL
|
||||
* else
|
||||
*/
|
||||
pVarEntry MakeScanVar(SicsInterp *pSics, SConnection *pCon, char
|
||||
*name, float start, float step);
|
||||
/**
|
||||
* InitScanVar clears the list of scan points
|
||||
* @param pvar The scna variable to clear
|
||||
*/
|
||||
void InitScanVar(pVarEntry pVar);
|
||||
/**
|
||||
* DeleteVarEntry deletes a scan variable.
|
||||
* @param pData The scan variable entry to delete.
|
||||
*/
|
||||
void DeleteVarEntry(void *pData);
|
||||
/**
|
||||
* ScanVarName returns the name of the scan variable
|
||||
* @param pVar The scan variable to query.
|
||||
* @return The name of the scan variable. Do not delete pointer.
|
||||
*/
|
||||
char *ScanVarName(pVarEntry pVar);
|
||||
/**
|
||||
* ScanVarStart returns the start value for the scan
|
||||
* @param pVar The scan variable to query.
|
||||
* @return The start point for the scan.
|
||||
*/
|
||||
float ScanVarStart(pVarEntry pVar);
|
||||
/**
|
||||
* ScanVarStep returns the start value for the scan
|
||||
* @param pVar The scan variable to query.
|
||||
* @return The step width for the scan.
|
||||
*/
|
||||
float ScanVarStep(pVarEntry pVar);
|
||||
/**
|
||||
* StartScanVar starts the scan variable to drive to the next
|
||||
* position.
|
||||
* @param pVar The scan variable to start.
|
||||
* @param pCon The connection to report errors to.
|
||||
* @param i The position number to drive to
|
||||
* @return 1 on success, 0 on failure
|
||||
*/
|
||||
int StartScanVar(pVarEntry pVar, SConnection *pCon, int i);
|
||||
/**
|
||||
* AppendScanVar appends a position to the list of positions
|
||||
* reached while scanning this variable.
|
||||
* @param pVar The scan variable to append to.
|
||||
* @param pos The position to append.
|
||||
*/
|
||||
void AppendScanVar(pVarEntry pVar, float pos);
|
||||
/**
|
||||
* GetScanVarPos returns a position for an index.
|
||||
* @param pVar The scan variable to append to.
|
||||
* @param i The position number to retrieve
|
||||
* @return The positiopn or -99999.99 for an error
|
||||
*/
|
||||
float GetScanVarPos(pVarEntry pVar, int i);
|
||||
/**
|
||||
* CopyScanVar copies the scan positions to the array given.
|
||||
* @param pVar The scan variable to copy from
|
||||
* @param fData The array to copy to.
|
||||
* @param np The number of slots in fData.
|
||||
*/
|
||||
void CopyScanVar(pVarEntry pVar, float *fData, int np);
|
||||
|
||||
#endif
|
@ -259,8 +259,8 @@
|
||||
{
|
||||
printf("ERROR: cannot open logfile %s for writing\n",
|
||||
pFile);
|
||||
|
||||
exit(1);
|
||||
fLogFile = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
749
stdscan.c
Normal file
749
stdscan.c
Normal file
@ -0,0 +1,749 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
S T A N D A R D S C A N
|
||||
|
||||
This is a library of scan functions for the SICS standard scan.
|
||||
|
||||
copyright: see copyright.h
|
||||
|
||||
Extracted from scan.c: Mark Koennecke, November 2004
|
||||
----------------------------------------------------------------------------*/
|
||||
#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 "splitter.h"
|
||||
#include "danu.h"
|
||||
#include "userscan.h"
|
||||
#include "motor.h"
|
||||
#include "nxscript.h"
|
||||
#include "nxutil.h"
|
||||
#include "site.h"
|
||||
#include "lld.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
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,ScanVarName(pScanVar));
|
||||
if(pMot != NULL)
|
||||
{
|
||||
MotorGetPar(pMot,"softzero",&fVal);
|
||||
fprintf(self->fd,"%s zero = %8.3f\n",ScanVarName(pScanVar),
|
||||
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);
|
||||
fclose(self->fd);
|
||||
self->fd = NULL;
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
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 ",ScanVarName(pVar));
|
||||
strcat(pLine,pItem);
|
||||
sprintf(pItem,"%s, ",ScanVarName(pVar));
|
||||
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",GetScanVarPos(pVar,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;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
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 = ScanVarStart(pVar);
|
||||
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) * ScanVarStep(pVar);
|
||||
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;
|
||||
}
|
||||
InitScanVar(pVar);
|
||||
}
|
||||
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 = ScanVarStart(pVar);
|
||||
InitScanVar(pVar);
|
||||
}
|
||||
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;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int CollectScanDataIntern(pScanData self, int iPoint, int jochenFlag)
|
||||
{
|
||||
pVarEntry pVar = NULL;
|
||||
void *pDings;
|
||||
int i, iRet, status;
|
||||
char pStatus[512], pItem[20];
|
||||
char pHead[512];
|
||||
float fVal;
|
||||
CountEntry sCount;
|
||||
|
||||
assert(self);
|
||||
assert(self->pCon);
|
||||
InitCountEntry(&sCount);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
AppendScanVar(pVar,fVal);
|
||||
sprintf(pItem,"%-10.10s",ScanVarName(pVar));
|
||||
strcat(pHead,pItem);
|
||||
sprintf(pItem,"%-10.3f",fVal);
|
||||
strcat(pStatus,pItem);
|
||||
}
|
||||
}
|
||||
|
||||
/* store counter data */
|
||||
sCount = CollectCounterData(self);
|
||||
|
||||
/*
|
||||
format header
|
||||
*/
|
||||
strcat(pHead,"Counts ");
|
||||
|
||||
sprintf(pItem,"%-15d",sCount.lCount);
|
||||
strcat(pStatus,pItem);
|
||||
|
||||
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);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int CollectScanData(pScanData self, int iPoint)
|
||||
{
|
||||
return CollectScanDataIntern(self,iPoint,0);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int CollectScanDataJochen(pScanData self, int iPoint)
|
||||
{
|
||||
return CollectScanDataIntern(self,iPoint,1);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int StartToDrive(pScanData self, int iPoint)
|
||||
{
|
||||
pVarEntry pVar = NULL;
|
||||
void *pDings;
|
||||
int i, iRet, status;
|
||||
|
||||
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)
|
||||
{
|
||||
iRet = StartScanVar(pVar,self->pCon,iPoint);
|
||||
if(!iRet)
|
||||
{
|
||||
status = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
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;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
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;
|
||||
}
|
||||
/*====================== script invocation functions ====================*/
|
||||
static pDynString GetStandardInvocation(pScanData self, char *function){
|
||||
pDynString result = NULL;
|
||||
char value[132];
|
||||
|
||||
result = CreateDynString(80,80);
|
||||
if(result == NULL){
|
||||
SCWrite(self->pCon,"ERROR: out of memory in scan invocation",eError);
|
||||
return NULL;
|
||||
}
|
||||
if(StringDictGet(self->scanFunctions,function,value,131) != 1){
|
||||
snprintf(value,131,"ERROR: scan function %s not found",function);
|
||||
SCWrite(self->pCon,value,eError);
|
||||
DeleteDynString(result);
|
||||
return NULL;
|
||||
}
|
||||
DynStringCopy(result,value);
|
||||
DynStringConcatChar(result,' ');
|
||||
DynStringConcat(result, self->objectName);
|
||||
DynStringConcatChar(result,' ');
|
||||
value[0] = '\0';
|
||||
StringDictGet(self->scanFunctions,"userdata",value,131);
|
||||
DynStringConcat(result,value);
|
||||
DynStringConcatChar(result,' ');
|
||||
return result;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int StandardScriptInvoke(pScanData self, char *function){
|
||||
pDynString command = NULL;
|
||||
int status;
|
||||
|
||||
command = GetStandardInvocation(self,function);
|
||||
if(command == NULL){
|
||||
return 0;
|
||||
}
|
||||
status = InterpExecute(self->pSics, self->pCon,
|
||||
GetCharArray(command));
|
||||
DeleteDynString(command);
|
||||
if(status != 1) {
|
||||
return 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int StandardScriptInvokeWithPoint(pScanData self,
|
||||
char *function, int iPoint){
|
||||
pDynString command = NULL;
|
||||
int status;
|
||||
char pNumber[50];
|
||||
|
||||
command = GetStandardInvocation(self,function);
|
||||
if(command == NULL){
|
||||
return 0;
|
||||
}
|
||||
snprintf(pNumber,49,"%d",iPoint);
|
||||
DynStringConcat(command,pNumber);
|
||||
status = InterpExecute(self->pSics, self->pCon,
|
||||
GetCharArray(command));
|
||||
DeleteDynString(command);
|
||||
if(status != 1) {
|
||||
return 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int ScriptWriteHeader(pScanData self){
|
||||
return StandardScriptInvoke(self,"writeheader");
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
int ScriptPrepareScan(pScanData self){
|
||||
return StandardScriptInvoke(self,"prepare");
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
int ScriptScanDrive(pScanData self, int iPoint){
|
||||
return StandardScriptInvokeWithPoint(self,"drive",iPoint);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
int ScriptScanCount(pScanData self, int iPoint){
|
||||
return StandardScriptInvokeWithPoint(self,"count",iPoint);
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int ScriptScanCollect(pScanData self, int iPoint){
|
||||
return StandardScriptInvokeWithPoint(self,"collect",iPoint);
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
int ScriptWriteScanPoints(pScanData self, int iPoint){
|
||||
return StandardScriptInvokeWithPoint(self,"writepoint",iPoint);
|
||||
}
|
||||
/*---------------------------------------------------------------------*/
|
||||
void ConfigureScript(pScanData self){
|
||||
assert(self);
|
||||
|
||||
self->PrepareScan = ScriptPrepareScan;
|
||||
self->WriteHeader = ScriptWriteHeader;
|
||||
self->WriteScanPoints = ScriptWriteScanPoints;
|
||||
self->ScanDrive = ScriptScanDrive;
|
||||
self->ScanCount = ScriptScanCount;
|
||||
self->CollectScanData = ScriptScanCollect;
|
||||
}
|
||||
/*======================================================================*/
|
||||
int StandardScanWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]){
|
||||
pScanData self = NULL;
|
||||
int iPoint;
|
||||
char pError[132];
|
||||
|
||||
if(argc < 4) {
|
||||
SCWrite(pCon,"ERROR: not enough arguments to stdscan",eError);
|
||||
return 0;
|
||||
}
|
||||
strtolower(argv[1]);
|
||||
self = (pScanData)FindCommandData(pSics,argv[2],"ScanObject");
|
||||
assert(self);
|
||||
|
||||
if(strcmp(argv[1],"writeheader") == 0){
|
||||
return WriteHeader(self);
|
||||
} else if(strcmp(argv[1],"prepare") == 0){
|
||||
return PrepareScan(self);
|
||||
}
|
||||
|
||||
/*
|
||||
from here on we need a scan point
|
||||
*/
|
||||
if(argc < 5) {
|
||||
SCWrite(pCon,"ERROR: not enough arguments to stdscan",eError);
|
||||
return 0;
|
||||
}
|
||||
iPoint = atoi(argv[4]);
|
||||
|
||||
if(strcmp(argv[1],"drive") == 0){
|
||||
return ScanDrive(self,iPoint);
|
||||
} else if(strcmp(argv[1],"count") == 0){
|
||||
return ScanCount(self,iPoint);
|
||||
} else if(strcmp(argv[1],"collect") == 0){
|
||||
return CollectScanData(self,iPoint);
|
||||
} else if(strcmp(argv[1],"writepoint") == 0){
|
||||
return WriteScanPoints(self,iPoint);
|
||||
} else {
|
||||
snprintf(pError,131,"ERROR: subcommand %s to stdscan not found",
|
||||
argv[1]);
|
||||
SCWrite(pCon,pError,eError);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
83
stdscan.h
Normal file
83
stdscan.h
Normal file
@ -0,0 +1,83 @@
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
S T A N D A R D S C A N
|
||||
|
||||
This is a library of scan functions for the SICS standard scan.
|
||||
|
||||
copyright: see copyright.h
|
||||
|
||||
Extracted from scan.c: Mark Koennecke, November 2004
|
||||
----------------------------------------------------------------------------*/
|
||||
#ifndef SICSSTDSCAN
|
||||
#define SICSSTDSCAN
|
||||
|
||||
/**
|
||||
* write the header of the scan file
|
||||
*/
|
||||
int WriteHeader(pScanData self);
|
||||
/**
|
||||
* WriteScanPoints is called for each point to write the scan data
|
||||
* to screen and to file.
|
||||
*/
|
||||
int WriteScanPoints(pScanData self, int iPoint);
|
||||
/**
|
||||
* Called before the scan to prepare. The default implementation
|
||||
* checks if all scan positions are available and configures the
|
||||
* counter.
|
||||
*/
|
||||
int PrepareScan(pScanData self);
|
||||
/**
|
||||
* second version of PrepareScan which does not check scan limits
|
||||
*/
|
||||
int NonCheckPrepare(pScanData self);
|
||||
/**
|
||||
* ScanDrive handles driving to the scan point iPoint.
|
||||
*/
|
||||
int ScanDrive(pScanData self, int iPoint);
|
||||
/**
|
||||
* ScanCount is called at each scan step to do the counting.
|
||||
*/
|
||||
int ScanCount(pScanData self, int iPoint);
|
||||
/**
|
||||
* CollectScanData stores the scans count results into
|
||||
* the scan data structure and prints the information about the
|
||||
* scan progress.
|
||||
*/
|
||||
int CollectScanData(pScanData self, int iPoint);
|
||||
int CollectScanDataJochen(pScanData self, int iPoint);
|
||||
/*===================================================================*/
|
||||
/**
|
||||
* Script invocation for writing the scan header.
|
||||
*/
|
||||
int ScriptWriteHeader(pScanData self);
|
||||
/**
|
||||
* Script writing each scan point
|
||||
*/
|
||||
int ScriptWriteScanPoints(pScanData self, int iPoint);
|
||||
/**
|
||||
* Script preparation of the scan.
|
||||
*/
|
||||
int ScriptPrepareScan(pScanData self);
|
||||
/**
|
||||
* Script driving to a scan point
|
||||
*/
|
||||
int ScriptScanDrive(pScanData self, int iPoint);
|
||||
/**
|
||||
* Script counting a scan point
|
||||
*/
|
||||
int ScriptScanCount(pScanData self, int iPoint);
|
||||
/**
|
||||
* Script collecting scan data for each scan point
|
||||
*/
|
||||
int ScriptScanCollect(pScanData self, int iPoint);
|
||||
/**
|
||||
* ConfigureScript assigns the script invocation functions for
|
||||
* scan
|
||||
*/
|
||||
void ConfigureScript(pScanData self);
|
||||
/*=====================================================================*/
|
||||
int StandardScanWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
|
||||
#endif
|
5
tclev.c
5
tclev.c
@ -328,7 +328,8 @@
|
||||
free(pPriv);
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
pEVDriver CreateTclDriver(int argc, char *argv[],char *pName, SConnection *pCon)
|
||||
pEVDriver CreateTclDriver(int argc, char *argv[],char *pName,
|
||||
SConnection *pCon)
|
||||
{
|
||||
pEVDriver pNew = NULL;
|
||||
pTclEv pPriv = NULL;
|
||||
@ -348,7 +349,7 @@
|
||||
memset(pPriv,0,sizeof(TclEv));
|
||||
|
||||
/* find the names of all the functions we need in the Tcl Array */
|
||||
pPriv->pTcl = pCon->pSics->pTcl;
|
||||
pPriv->pTcl = InterpGetTcl(pServ->pSics);
|
||||
assert(pPriv->pTcl);
|
||||
pPriv->pArray = strdup(argv[0]);
|
||||
pPtr = Tcl_GetVar2(pPriv->pTcl,argv[0],"Init",TCL_GLOBAL_ONLY);
|
||||
|
Reference in New Issue
Block a user