- 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:
koennecke
2005-01-12 08:42:39 +00:00
parent 5e05be17e0
commit ef1de4589c
35 changed files with 2659 additions and 1203 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -12,6 +12,8 @@
Mark Koennecke, Aprl 2003
Mark Koennecke, December 2004
copyright: see copyright.h
----------------------------------------------------------------------------*/
#ifndef SICSCONNECT
@ -30,34 +32,32 @@ 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 eInterrupt;
int iUserRights;
int inUse;
int iDummy;
int iGrab;
int iErrCode;
int inUse;
int iGrab; /* grab flag for token*/
int parameterChange;
int sicsError;
SicsInterp *pSics;
/* a FIFO */
pCosta pStack;

View File

@ -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;
}

View File

@ -159,6 +159,7 @@
DeleteCallBackInterface(self->pCall);
free(self);
pServ->pExecutor = NULL;
}
/*--------------------------------------------------------------------------*/
void ExeInterest(pExeList self, pDevEntry pDev, char *text) {

View File

@ -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>

View File

@ -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;
}

View File

@ -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);
}
/*--------------------------------------------------------------------*/

View File

@ -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)
{

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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);

View File

@ -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 \

View File

@ -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
View File

@ -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 */

View File

@ -103,7 +103,6 @@ CreateSocketAdress(
sockaddrPtr->sin_addr.s_addr = addr.s_addr;
return 1;
}
/*-------------------------------------------------------------------------*/
mkChannel *NETOpenPort(int iPort)

View File

@ -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);

View File

@ -348,7 +348,10 @@
if(pSICSOptions)
IFDeleteOptions(pSICSOptions);
if(self->pSics)
{
DeleteInterp(self->pSics);
self->pSics = NULL;
}
/* close the server port */
if(self->pServerPort)

View File

@ -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
View File

@ -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

View File

@ -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);

View File

@ -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;

1627
scan.c

File diff suppressed because it is too large Load Diff

4
scan.h
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View 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
View 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

View File

@ -259,8 +259,8 @@
{
printf("ERROR: cannot open logfile %s for writing\n",
pFile);
exit(1);
fLogFile = NULL;
return;
}
}

749
stdscan.c Normal file
View 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
View 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

View File

@ -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);

View File

@ -133,7 +133,7 @@
}
/* invoke command */
CostaLock(self->pCon->pStack);
SCInvoke(self->pCon,self->pCon->pSics,pPtr);
SCInvoke(self->pCon,pServ->pSics,pPtr);
CostaUnlock(self->pCon->pStack);
SendGA(self->pCon);
free(pPtr);