From ef1de4589c5bb1c63cbf0142ebfaa07a43b287d8 Mon Sep 17 00:00:00 2001 From: koennecke Date: Wed, 12 Jan 2005 08:42:39 +0000 Subject: [PATCH] - 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 --- SCinter.c | 1 + conman.c | 41 +- conman.h | 30 +- counter.c | 2 +- devexec.c | 1 + doc/manager/iscan.htm | 146 +++- evcontroller.c | 9 +- exeman.c | 2 +- interface.c | 27 +- interface.h | 26 +- interface.tex | 6 + interface.w | 6 + macro.c | 6 +- make_gen | 4 +- mesure.c | 8 +- motor.c | 142 +--- network.c | 1 - nread.c | 1 + nserver.c | 3 + obdes.h | 4 +- ofac.c | 4 + optimise.c | 2 +- oscillate.c | 10 + scan.c | 1627 ++++++++++++++++++----------------------- scan.h | 4 +- scan.i | 24 +- scan.tex | 344 ++++++++- scan.w | 284 ++++++- scanvar.c | 154 ++++ scanvar.h | 100 +++ servlog.c | 4 +- stdscan.c | 749 +++++++++++++++++++ stdscan.h | 83 +++ tclev.c | 5 +- telnet.c | 2 +- 35 files changed, 2659 insertions(+), 1203 deletions(-) create mode 100644 scanvar.c create mode 100644 scanvar.h create mode 100644 stdscan.c create mode 100644 stdscan.h diff --git a/SCinter.c b/SCinter.c index e494c6d0..29daf5e9 100644 --- a/SCinter.c +++ b/SCinter.c @@ -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); diff --git a/conman.c b/conman.c index afb22b83..8f8e3c4a 100644 --- a/conman.c +++ b/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; } diff --git a/conman.h b/conman.h index 09b4a96f..3b4d76d0 100644 --- a/conman.h +++ b/conman.h @@ -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; diff --git a/counter.c b/counter.c index cfaa37a9..b5feb33e 100644 --- a/counter.c +++ b/counter.c @@ -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; } diff --git a/devexec.c b/devexec.c index 9367bb55..a7500d6c 100644 --- a/devexec.c +++ b/devexec.c @@ -159,6 +159,7 @@ DeleteCallBackInterface(self->pCall); free(self); + pServ->pExecutor = NULL; } /*--------------------------------------------------------------------------*/ void ExeInterest(pExeList self, pDevEntry pDev, char *text) { diff --git a/doc/manager/iscan.htm b/doc/manager/iscan.htm index 1c085062..b80c10d4 100644 --- a/doc/manager/iscan.htm +++ b/doc/manager/iscan.htm @@ -3,7 +3,7 @@ The Internal Scan Command -

The Internal Scan Command

+

The Internal Scan Commands

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

+

Scan Concepts +

+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: +

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

The scan object (named here xxscan, but may have another name) understands the following commands:
@@ -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. +
xxscan continue NP mode preset +
Continues an interrupted scan. Used by the recovery feauture.
xxscan silent NP mode preset
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.
xxscan getcounts
Retrieves the counst collected during the scan. +
xxscan getmonitor i +
Prints the monitor values collected during the scan for the +monitor number i +
xxscan gettime +
Prints the counting times for the scan points in the current scan. +
xxscan np +
Prints the number of points in the current scan.
xxscan getvardata n
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. +
xxscan noscanvar +
Prints the number of scan variables +
xxscan getvarpar i +
Prints the name , start and step of the scan variable number i
xxscan interest
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. +
xxscan uuinterest +
As above but the array of counts is transferred in UU encoded +format. +
xxscan dyninterest +
As above but scan points are printed one by one as a list +containing: point number first_scan_var_pos counts.
xxscan uninterest
Uninterest switches automatic notification about scan progress off.
xxscan integrate @@ -87,10 +129,70 @@ object. Currently there are two:
  • amor, a special mode the reflectometer AMOR which writes NeXus files. +
    xxscan storecounts counts time mon1 mon2 ... +
    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. +
    xxscan storecounter +
    Store the counts and monitors in the counter object configured for +the scan into the scan data structure. Increments the scan pointer by +one. +
    xxscan appendvarpos i pos +
    Append pos to the array of positions for scan variable i. To be +used from user defined scan functions. +
    xxscan callback scanstart | scanpoint | scanend +
    Triggers callbacks configured on the scan object. May be used by +user functions implementing own scan loops. +
    xxscan function list +
    Lists the available configurable function names. The calling style +of these functions is described in the next section about stdscan. +
    xxscan function functionname +
    Returns the currently configured function for functionname. +
    xxscan function functionname newfunctionname +
    Sets a new function to be called for the function functionname in +the scan.
  • -

    -

    User Defined Scans

    +

    User Definable Scan Functions

    +

    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: +

    +
    writeheader +
    Is supposed to write the header of the data file +
    prepare +
    Prepare does all the necessary operations necessary before a scan +starts. +
    drive +
    Is called to drive to the next scan point +
    count +
    Is called at each scan point to perform the counting operation +
    collect +
    Is called for each scan point. This function is supposed to store +the scan data into the scan data structure. +
    writepoint +
    Is called for each scan point and is meant to print information +about the scan point to the data file and to the user. +
    userdata +
    This is the name of a user defined object which may be used to +store user data for the scan. +
    +The exact invocations of the functions: + +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. +

    +

    User Defined Scans(Old Style)

    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.

    +

    Differential Scans

    +

    +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: +

    +MakeDiffScan 
    +
    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: + +The diffscan object has two configurable parameters: +
    +
    monitor +
    The monitor number to normalize against. For maximum precision +this should be a monitor with a lot of intensity on it. +
    skip +
    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. +
    +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. +

    diff --git a/evcontroller.c b/evcontroller.c index b9beba76..05d0cd52 100644 --- a/evcontroller.c +++ b/evcontroller.c @@ -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; } diff --git a/exeman.c b/exeman.c index b4c370e5..e9e98a5b 100644 --- a/exeman.c +++ b/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); } /*--------------------------------------------------------------------*/ diff --git a/interface.c b/interface.c index 6435c46c..4055e4b4 100644 --- a/interface.c +++ b/interface.c @@ -41,7 +41,7 @@ #include #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) { diff --git a/interface.h b/interface.h index 9065ba91..13dd8a97 100644 --- a/interface.h +++ b/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 diff --git a/interface.tex b/interface.tex index 4919c407..a49e9625 100644 --- a/interface.tex +++ b/interface.tex @@ -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. diff --git a/interface.w b/interface.w index 02dae748..4daa749f 100644 --- a/interface.w +++ b/interface.w @@ -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. diff --git a/macro.c b/macro.c index fea5423c..a9200b4e 100644 --- a/macro.c +++ b/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); diff --git a/make_gen b/make_gen index edcc7ab5..66852b76 100644 --- a/make_gen +++ b/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 \ diff --git a/mesure.c b/mesure.c index 98a10541..7c29ffac 100644 --- a/mesure.c +++ b/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++) { diff --git a/motor.c b/motor.c index 8246c299..41187f10 100644 --- a/motor.c +++ b/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 */ diff --git a/network.c b/network.c index 716b6dc3..140d39e1 100644 --- a/network.c +++ b/network.c @@ -103,7 +103,6 @@ CreateSocketAdress( sockaddrPtr->sin_addr.s_addr = addr.s_addr; return 1; } - /*-------------------------------------------------------------------------*/ mkChannel *NETOpenPort(int iPort) diff --git a/nread.c b/nread.c index 26477257..eb9963e5 100644 --- a/nread.c +++ b/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); diff --git a/nserver.c b/nserver.c index 5c60b35a..9cff04fd 100644 --- a/nserver.c +++ b/nserver.c @@ -348,7 +348,10 @@ if(pSICSOptions) IFDeleteOptions(pSICSOptions); if(self->pSics) + { DeleteInterp(self->pSics); + self->pSics = NULL; + } /* close the server port */ if(self->pServerPort) diff --git a/obdes.h b/obdes.h index 6fe95697..ccb363d9 100644 --- a/obdes.h +++ b/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" diff --git a/ofac.c b/ofac.c index c30e42b1..c5070f4a 100644 --- a/ofac.c +++ b/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 diff --git a/optimise.c b/optimise.c index 6bf3e19a..d74cae09 100644 --- a/optimise.c +++ b/optimise.c @@ -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); diff --git a/oscillate.c b/oscillate.c index 6c912704..2bf3d915 100644 --- a/oscillate.c +++ b/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; diff --git a/scan.c b/scan.c index c49d1079..0a760682 100644 --- a/scan.c +++ b/scan.c @@ -6,7 +6,15 @@ Mark Koennecke, October 1997, June 2001 - + + Extracted scanvar.c, .h + Extended to allow for storing and retrieving of all scan data from scripts + Changed recover to work with ASCII files using the feautures implemented + above. + Extracted stdscan.h, stdscan.c + + Mark Koennecke, November 2004 + copyright: see copyright.h ----------------------------------------------------------------------------*/ #include "sics.h" @@ -16,6 +24,8 @@ #include #include "fortify.h" #include "sdynar.h" +#include "dynstring.h" +#include "stringdict.h" #include "status.h" #include "sicsvar.h" #include "counter.h" @@ -29,11 +39,9 @@ #include "motor.h" #include "nxscript.h" #include "site.h" +#include "lld.h" +#include "stdscan.h" -extern void SNXFormatTime(char *pBuffer, int iLen); - /* - from nxdata.c - */ /*-----------------------------------------------------------------------*/ static char *fixExtension(char *filename) { @@ -65,27 +73,24 @@ static char *fixExtension(char *filename) } return fixExtension(pRes); } - -/*--------------------- VarEntry Management --------------------------------*/ - static void DeleteVarEntry(void *pData) - { - pVarEntry pVar = NULL; - - pVar = (pVarEntry)pData; - - assert(pVar); - - if(pVar->fData) - { - free(pVar->fData); - } - free(pVar); - } /*---------------------------------------------------------------------------*/ static void DeleteCountEntry(void *pData) { free(pData); } +/*---------------------------------------------------------------------------*/ +void InitCountEntry(pCountEntry pCount) +{ + int i; + + pCount->lCount = -1L; + pCount->i = -1; + pCount->fTime = -1.0; + for(i = 0; i < 10; i++) + { + pCount->Monitors[i] = -1L; + } +} /*--------------------------------------------------------------------------*/ static int DummyWrite(pScanData self) { @@ -96,309 +101,6 @@ static char *fixExtension(char *filename) { return 1; } -/*---------------------------------------------------------------------------*/ - static int WriteHeader(pScanData self) - { - int i, iRet; - FILE *fd; - char pBuffer[512], pError[512], *pPtr, *pName; - CommandList *pCom = NULL; - pSicsVariable pVar = NULL; - pDummy pDum = NULL; - pIDrivable pDriv = NULL; - float fVal; - pMotor pMot = NULL; - pVarEntry pScanVar = NULL; - void *pVoid = NULL; - - assert(self->pSics); - assert(self->pCon); - - /* open data file */ - self->fd = fopen(self->pFile,"w"); - if(!self->fd) - { - SCWrite(self->pCon,"ERROR: cannot write data file",eError); - return 0; - } - - /* open header description file */ - fd = fopen(self->pHeaderFile,"r"); - if(!fd) - { - SCWrite(self->pCon,"ERROR: cannot open header description file",eError); - return 0; - } - - /* loop through description file and act along the way */ - while(fgets(pBuffer,511,fd) != NULL) - { - pPtr = strstr(pBuffer,"!!VAR("); - if(pPtr) /* handle a Sics variable */ - { - /* extract the name */ - pName = pPtr + 6; /* first char of name */ - *pPtr = '\0'; /* this is the starter of the line */ - pPtr = pName; - while( (*pPtr != '\0') && (*pPtr != ')') ) - { - pPtr++; - } - *pPtr = '\0'; - /* find the variable */ - pCom = FindCommand(self->pSics,pName); - if(!pCom) - { - sprintf(pError,"ERROR: variable %s NOT found",pName); - SCWrite(self->pCon,pError,eError); - continue; - } - pVar = (pSicsVariable)pCom->pData; - if(!pVar) - { - sprintf(pError,"ERROR: variable %s NOT found",pName); - SCWrite(self->pCon,pError,eError); - continue; - } - switch(pVar->eType) - { - case veFloat: - sprintf(pError,"%f",pVar->fVal); - break; - case veInt: - sprintf(pError,"%d",pVar->iVal); - break; - case veText: - sprintf(pError,"%s",pVar->text); - break; - } - /* finally write */ - fprintf(self->fd,"%s %s\n",pBuffer,pError); - continue; - }/* end variable */ -/*------- Drivable */ - pPtr = strstr(pBuffer,"!!DRIV("); - if(pPtr) - { - /* extract the name */ - pName = pPtr + 7; /* first char of name */ - *pPtr = '\0'; /* this is the starter of the line */ - pPtr = pName; - while( (*pPtr != '\0') && (*pPtr != ')') ) - { - pPtr++; - } - *pPtr = '\0'; - /* find the variable */ - pCom = FindCommand(self->pSics,pName); - if(!pCom) - { - sprintf(pError,"ERROR: variable %s NOT found",pName); - SCWrite(self->pCon,pError,eError); - continue; - } - pDum = (pDummy)pCom->pData; - if(!pDum) - { - sprintf(pError,"ERROR: variable %s is NOT drivable",pName); - SCWrite(self->pCon,pError,eError); - continue; - } - pDriv = (pIDrivable)pDum->pDescriptor->GetInterface(pDum,DRIVEID); - if(!pDriv) - { - sprintf(pError,"ERROR: variable %s is NOT drivable",pName); - SCWrite(self->pCon,pError,eError); - continue; - } - fVal = pDriv->GetValue(pDum,self->pCon); - fprintf(self->fd,"%s %f\n",pBuffer,fVal); - continue; - } /* end drive */ -/*------- zero point */ - pPtr = strstr(pBuffer,"!!ZERO("); - if(pPtr) - { - /* extract the name */ - pName = pPtr + 7; /* first char of name */ - *pPtr = '\0'; /* this is the starter of the line */ - pPtr = pName; - while( (*pPtr != '\0') && (*pPtr != ')') ) - { - pPtr++; - } - *pPtr = '\0'; - /* find the motor */ - pMot = FindMotor(self->pSics,pName); - if(!pMot) - { - sprintf(pError,"ERROR: motor %s NOT found",pName); - SCWrite(self->pCon,pError,eError); - continue; - } - iRet = MotorGetPar(pMot,"softzero",&fVal); - if(!iRet) - { - SCWrite(self->pCon,"ERROR: failed to read zero point",eError); - continue; - } - fprintf(self->fd,"%s %f\n",pBuffer,fVal); - continue; - } /* end zero point */ -/* ------- date */ - pPtr = strstr(pBuffer,"!!DATE!!"); - if(pPtr) - { - *pPtr = '\0'; - SNXFormatTime(pError,511); - fprintf(self->fd,"%s %s\n",pBuffer,pError); - continue; - } -/*-------- filename */ - pPtr = strstr(pBuffer,"!!FILE!!"); - if(pPtr) - { - *pPtr = '\0'; - fprintf(self->fd,"%s %s\n",pBuffer,self->pFile); - continue; - } -/*------------ scanzero */ - pPtr = strstr(pBuffer,"!!SCANZERO!!"); - if(pPtr) - { - *pPtr = '\0'; - /* write zero point of first scan variable if motor */ - DynarGet(self->pScanVar,0,&pVoid); - pScanVar = (pVarEntry)pVoid; - if(pScanVar) - { - pMot = NULL; - pMot = FindMotor(self->pSics,pScanVar->Name); - if(pMot != NULL) - { - MotorGetPar(pMot,"softzero",&fVal); - fprintf(self->fd,"%s zero = %8.3f\n",pScanVar->Name, fVal); - } - } - } -/* --------- plain text */ - fprintf(self->fd,"%s",pBuffer); - } /* end while */ - - - /* remember position for seeking to it for writing data */ - self->lPos = ftell(self->fd); - - fclose(fd); - fclose(self->fd); - self->fd = NULL; - return 1; - } -/*--------------------------------------------------------------------------*/ - static int WriteScanPoints(pScanData self, int iPoint) - { - int i, i2; - char pLine[512], pItem[30], pInfo[512]; - pVarEntry pVar = NULL; - pCountEntry pData = NULL; - void *pPtr = NULL; - - assert(self->pCon); - assert(self->pSics); - - /* reopen file */ - self->fd = fopen(self->pFile,"r+"); - if(!self->fd) - { - SCWrite(self->pCon, - "ERROR: Failed to reopen scan file, aborting scan", - eError); - return 0; - } - - - /* jump to end of header */ - fseek(self->fd,self->lPos, SEEK_SET); - if(self->iChannel != 0) - { - fprintf(self->fd,"WARNING: Scanning monitor %d\n",self->iChannel); - } - - /* make the data header */ - sprintf(pLine,"%-5s","NP"); - strcpy(pInfo,"Scanning Variables: "); - for(i = 0; i < self->iScanVar;i++) - { - DynarGet(self->pScanVar,i,&pPtr); - pVar = (pVarEntry)pPtr; - if(pVar) - { - sprintf(pItem,"%-9.9s ",pVar->Name); - strcat(pLine,pItem); - sprintf(pItem,"%s, ",pVar->Name); - strcat(pInfo,pItem); - } - } - strcat(pLine," Counts "); - strcat(pLine,"Monitor1 "); - strcat(pLine,"Monitor2 "); - strcat(pLine,"Monitor3 "); - strcat(pLine,"Time "); - sprintf(pItem,"\n%d Points,",self->iNP); - strcat(pInfo,pItem); - if(self->iMode == eTimer) - { - strcat(pInfo," Mode: Timer,"); - } - else - { - strcat(pInfo," Mode: Monitor,"); - } - sprintf(pItem," Preset %f",self->fPreset); - strcat(pInfo,pItem); - fprintf(self->fd,"%s\n",pInfo); - fprintf(self->fd,"%s\n",pLine); - - /* now the scan points */ - for(i = 0; i < self->iCounts; i++) - { - sprintf(pLine,"%-5d",i); - /* print vars */ - for(i2 = 0; i2 < self->iScanVar; i2++) - { - DynarGet(self->pScanVar,i2,&pPtr); - pVar = (pVarEntry)pPtr; - if(pVar) - { - sprintf(pItem,"%-10.3f",pVar->fData[i]); - strcat(pLine,pItem); - } - } - /* print Counts & Monitor */ - DynarGet(self->pCounts,i,&pPtr); - pData = (pCountEntry)pPtr; - if(pData) - { - sprintf(pItem," %-12ld",pData->lCount); - strcat(pLine,pItem); - sprintf(pItem,"%-12ld",pData->Monitors[0]); - strcat(pLine,pItem); - sprintf(pItem,"%-12ld",pData->Monitors[1]); - strcat(pLine,pItem); - sprintf(pItem,"%-12ld",pData->Monitors[2]); - strcat(pLine,pItem); - sprintf(pItem,"%-6.1f",pData->fTime); - strcat(pLine,pItem); - } - fprintf(self->fd,"%s\n",pLine); - } - - /* done */ - fprintf(self->fd,"END-OF-DATA\n"); - fclose(self->fd); - self->fd = NULL; - return 1; - } /*---------------------------------------------------------------------------*/ static void *ScanInterface(void *pData, int iInter) { @@ -413,13 +115,20 @@ static char *fixExtension(char *filename) } return NULL; } -/*-------------------------------------------------------------------------*/ - static int ScanDrive(pScanData self, int iPoint); - static int ScanCount(pScanData self, int iPoint); - static int CollectScanData(pScanData self, int iPoint); - static int PrepareScan(pScanData self); +/*------------------------------------------------------------------------*/ +static void ConfigureScanDict(pStringDict dict) +{ + StringDictAddPair(dict,"writeheader","stdscan writeheader"); + StringDictAddPair(dict,"prepare","stdscan prepare"); + StringDictAddPair(dict,"drive","stdscan drive"); + StringDictAddPair(dict,"count","stdscan count"); + StringDictAddPair(dict,"collect","stdscan collect"); + StringDictAddPair(dict,"writepoint","stdscan writepoint"); + StringDictAddPair(dict,"userdata","unknown"); +} /*--------------------------------------------------------------------------*/ - pScanData CreateScanObject(char *pRecover, char *pHeader,pCounter pCount) + pScanData CreateScanObject(char *pRecover, char *pHeader,pCounter pCount, + char *objName) { pScanData pNew = NULL; @@ -442,7 +151,8 @@ static char *fixExtension(char *filename) /* allocate the dynamic arrays */ pNew->pScanVar = CreateDynar(0,10,10,DeleteVarEntry); pNew->pCounts = CreateDynar(0,10,10,DeleteCountEntry); - if( (!pNew->pScanVar) || (!pNew->pCounts) ) + pNew->scanFunctions = CreateStringDict(); + if( (!pNew->pScanVar) || (!pNew->pCounts) || (!pNew->scanFunctions) ) { DeleteDescriptor(pNew->pDes); free(pNew); @@ -477,7 +187,9 @@ static char *fixExtension(char *filename) pNew->ScanCount = ScanCount; pNew->CollectScanData = CollectScanData; pNew->iWindow = 6; - + strncpy(pNew->objectName,objName, 131); + ConfigureScanDict(pNew->scanFunctions); + return pNew; } /*---------------------------------------------------------------------------*/ @@ -510,6 +222,10 @@ static char *fixExtension(char *filename) { free(self->pCommand); } + if(self->scanFunctions) + { + DeleteStringDict(self->scanFunctions); + } free(self); } /*------------------------------------------------------------------------*/ @@ -534,7 +250,7 @@ static char *fixExtension(char *filename) CommandList *pCom = NULL; pIDrivable pDriv = NULL; pDummy pData = NULL; - VarEntry pVar; + pVarEntry pVar = NULL; char pBueffel[512]; if(self->iActive) @@ -544,39 +260,14 @@ static char *fixExtension(char *filename) return 0; } - /* find the thing */ - pCom = FindCommand(pSics,name); - if(!pCom) + pVar = MakeScanVar(pSics,pCon,name,fStart,fStep); + if(pVar == NULL) { - sprintf(pBueffel,"ERROR: Cannot find variable %s to scan",name); - SCWrite(pCon,pBueffel,eError); - return 0; + return 0; } - pData = (pDummy)pCom->pData; - if(!pData) - { - sprintf(pBueffel,"ERROR: Cannot find data for variable %s",name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - pDriv = pData->pDescriptor->GetInterface(pData,DRIVEID); - if(!pDriv) - { - sprintf(pBueffel,"ERROR: variable %s is NOT driveable and cannot be scanned",name); - SCWrite(pCon,pBueffel,eError); - return 0; - } - - /* got everything, fill in the VarEntry structure */ - strcpy(pVar.Name,name); - pVar.pInter = pDriv; - pVar.pObject = pData; - pVar.fStart = fStart; - pVar.fStep = fStep; - pVar.fData = NULL; /* put it away */ - DynarPutCopy(self->pScanVar,self->iScanVar,&pVar,sizeof(VarEntry)); + DynarPut(self->pScanVar,self->iScanVar,pVar); self->iScanVar++; return 1; @@ -592,47 +283,23 @@ static char *fixExtension(char *filename) self->iScanVar = 0; return 1; } -/*-------------------------------------------------------------------------*/ - struct RecoHead { - int iScanVar; - int iNP; - int iMode; - float fPreset; - int iCounts; - int iChannel; - }; - - struct VarHead { - char pName[256]; - float fStart; - float fStep; - }; /*--------------------------------------------------------------------------*/ static int WriteRecover(pScanData self) { FILE *fd; - struct RecoHead sHead; - struct VarHead sVar; - void *pData; pVarEntry pVar = NULL; + void *pData = NULL; pCountEntry pCount = NULL; - int i; - - fd = fopen(self->pRecover,"wb"); + int i, j, status; + + fd = fopen(self->pRecover,"w"); if(!fd) { return 0; } - /* write Header */ - sHead.iScanVar = self->iScanVar; - sHead.iNP = self->iNP; - sHead.iMode = self->iMode; - sHead.fPreset = self->fPreset; - sHead.iCounts = self->iCounts; - sHead.iChannel = self->iChannel; - fwrite(&sHead,sizeof(struct RecoHead),1,fd); - + fprintf(fd,"%s clear\n",self->objectName); + /* write scan vars */ for(i = 0; i < self->iScanVar; i++) { @@ -640,11 +307,23 @@ static char *fixExtension(char *filename) pVar = (pVarEntry)pData; if(pVar) { - strcpy(sVar.pName,pVar->Name); - sVar.fStep = pVar->fStep; - sVar.fStart = pVar->fStart; - fwrite(&sVar,sizeof(struct VarHead),1,fd); - fwrite(pVar->fData,sizeof(float),sHead.iNP,fd); + fprintf(fd,"%s add %s %f %f\n", self->objectName, ScanVarName(pVar), + ScanVarStart(pVar), ScanVarStep(pVar)); + } + pData = NULL; + } + for(i = 0; i < self->iScanVar; i++) + { + DynarGet(self->pScanVar,i,&pData); + pVar = (pVarEntry)pData; + if(pVar) + { + status = LLDnodePtr2First(pVar->dataList); + while(status != 0) { + fprintf(fd,"%s appendvarpos %d %f\n",self->objectName, + i, LLDnodeFloat(pVar->dataList)); + status = LLDnodePtr2Next(pVar->dataList); + } } pData = NULL; } @@ -654,210 +333,35 @@ static char *fixExtension(char *filename) { DynarGet(self->pCounts,i,&pData); pCount = (pCountEntry)pData; - if(pCount) + if(pCount != NULL) { - fwrite(pCount,sizeof(CountEntry),1,fd); + fprintf(fd,"%s storecounts %d %f %d %d %d %d %d %d %d %d %d %d\n", + self->objectName, + pCount->lCount, + pCount->fTime, + pCount->Monitors[0], + pCount->Monitors[1], + pCount->Monitors[2], + pCount->Monitors[3], + pCount->Monitors[4], + pCount->Monitors[5], + pCount->Monitors[6], + pCount->Monitors[7], + pCount->Monitors[8], + pCount->Monitors[9]); } } - + if(self->iMode == eTimer){ + fprintf(fd,"%s continue %d timer %f\n",self->objectName, + self->iNP,self->fPreset); + }else { + fprintf(fd,"%s continue %d monitor %f\n",self->objectName, + self->iNP,self->fPreset); + } fclose(fd); return 1; } /*-------------------------------------------------------------------------*/ - static int ReadRecover(pScanData self) - { - FILE *fd; - struct RecoHead sHead; - struct VarHead sVar; - pVarEntry pVar; - void *pData; - CountEntry CountData; - int i,iRet; - - assert(self); - assert(self->pCon); - - fd = fopen(self->pRecover,"rb"); - if(!fd) - { - return 0; - } - - /* read Header */ - iRet = fread(&sHead,sizeof(struct RecoHead),1,fd); - if(iRet != 1) - { - SCWrite(self->pCon,"ERROR: Recover File corrupted",eError); - fclose(fd); - return 0; - } - self->iNP = sHead.iNP; - self->iMode = sHead.iMode; - self->fPreset = sHead.fPreset; - self->iCounts = sHead.iCounts; - self->iChannel = sHead.iChannel; - - /* read Scan Variables */ - self->iScanVar = 0; - for(i = 0; i < sHead.iScanVar; i++) - { - iRet = fread(&sVar,sizeof(struct VarHead),1,fd); - if(iRet != 1) - { - SCWrite(self->pCon,"ERROR: Recover File corrupted",eError); - fclose(fd); - return 0; - } - AddScanVar(self,self->pSics,self->pCon, - sVar.pName, sVar.fStart, sVar.fStep); - DynarGet(self->pScanVar,i,&pData); - pVar = (pVarEntry)pData; - pVar->fData = (float *)malloc(sHead.iNP*sizeof(float)); - if(!pVar->fData) - { - SCWrite(self->pCon,"ERROR: out of memory in scan::ReadRecover",eError); - fclose(fd); - return 0; - } - fread(pVar->fData,sizeof(float),sHead.iNP,fd); - } - - /* read counts */ - for(i = 0; i < sHead.iCounts; i++) - { - fread(&CountData,sizeof(CountEntry),1,fd); - DynarPutCopy(self->pCounts,i,&CountData,sizeof(CountEntry)); - } - - fclose(fd); - return 1; - } -/*--------------------------------------------------------------------------*/ - static int PrepareScan(pScanData self) - { - pVarEntry pVar = NULL; - void *pDings; - int i, iRet; - float fVal; - char pBueffel[512]; - char pMessage[1024]; - - assert(self); - assert(self->iNP > 0); - assert(self->pCon); - - /* check boundaries of scan variables and allocate storage */ - for(i = 0; i < self->iScanVar; i++) - { - DynarGet(self->pScanVar,i,&pDings); - pVar = (pVarEntry)pDings; - if(pVar) - { - /* start value */ - fVal = pVar->fStart; - iRet = pVar->pInter->CheckLimits(pVar->pObject, - fVal,pBueffel,511); - if(!iRet) - { - sprintf(pMessage,"ERROR: %s, scan aborted",pBueffel); - SCWrite(self->pCon,pBueffel,eError); - return 0; - } - /* end value */ - fVal = pVar->fStart + (self->iNP - 1) * pVar->fStep; - iRet = pVar->pInter->CheckLimits(pVar->pObject, - fVal,pBueffel,511); - if(!iRet) - { - sprintf(pMessage,"ERROR: %s, scan aborted",pBueffel); - SCWrite(self->pCon,pBueffel,eError); - return 0; - } - /* allocate data space */ - if(pVar->fData) - { - free(pVar->fData); - pVar->fData = NULL; - } - pVar->fData = (float *)malloc(self->iNP * sizeof(float)); - if(!pVar->fData) - { - SCWrite(self->pCon,"ERROR: out of memory in scan, aborting",eError); - return 0; - } - memset(pVar->fData,0,self->iNP * sizeof(float)); - } - else - { - SCWrite(self->pCon, - "WARNING: Internal error, no scan variable, I try to continue", - eWarning); - } - pVar = NULL; - } /* end for */ - - /* configure counter */ - SetCounterMode((pCounter)self->pCounterData,self->iMode); - SetCounterPreset((pCounter)self->pCounterData, self->fPreset); - self->iCounts = 0; - - return 1; - } -/*--------------------------------------------------------------------------*/ - int NonCheckPrepare(pScanData self) - { - pVarEntry pVar = NULL; - void *pDings; - int i, iRet; - float fVal; - char pBueffel[512]; - char pMessage[1024]; - - assert(self); - assert(self->iNP > 0); - assert(self->pCon); - - /* allocate storage for scan variables */ - for(i = 0; i < self->iScanVar; i++) - { - DynarGet(self->pScanVar,i,&pDings); - pVar = (pVarEntry)pDings; - if(pVar) - { - /* start value */ - fVal = pVar->fStart; - - /* allocate data space */ - if(pVar->fData) - { - free(pVar->fData); - pVar->fData = NULL; - } - pVar->fData = (float *)malloc(self->iNP * sizeof(float)); - if(!pVar->fData) - { - SCWrite(self->pCon,"ERROR: out of memory in scan, aborting",eError); - return 0; - } - memset(pVar->fData,0,self->iNP * sizeof(float)); - } - else - { - SCWrite(self->pCon, - "WARNING: Internal error, no scan variable, I try to continue", - eWarning); - } - pVar = NULL; - } /* end for */ - - /* configure counter */ - SetCounterMode((pCounter)self->pCounterData,self->iMode); - SetCounterPreset((pCounter)self->pCounterData, self->fPreset); - self->iCounts = 0; - - return 1; - } -/*-------------------------------------------------------------------------*/ int AppendScanLine(pScanData self, char *line) { /* reopen file */ @@ -887,28 +391,42 @@ extern char *stptok(const char *s, char *t, int len, char *brk); int StoreScanCounts(pScanData self, char *data) { CountEntry sCount; - char pNumber[20], *pPtr; + char pNumber[30], *pPtr; int iCount = 0; + char pBueffel[256]; if(data == NULL) { - SCWrite(self->pCon,"WARNING: StoreScanCounst called without data",eWarning); + SCWrite(self->pCon,"WARNING: StoreScanCounts called without data", + eWarning); return 1; } + InitCountEntry(&sCount); /* parse the data */ pPtr = data; - pPtr = stptok(pPtr,pNumber,19," \t"); + pPtr = stptok(pPtr,pNumber,29," \t"); if(pPtr != NULL) { sCount.lCount = atoi(pNumber); } else { - SCWrite(self->pCon,"ERROR: No data in StoreScanCounts",eError); - return 0; + SCWrite(self->pCon,"WARNING: No data in StoreScanCounts",eWarning); + snprintf(pBueffel,255,"Received: %s", data); + SCWrite(self->pCon,pBueffel,eWarning); + return 1; } - while((pPtr = stptok(pPtr,pNumber,19," \t")) != NULL) + pPtr = stptok(pPtr,pNumber,29," \t"); + if(pPtr != NULL) + { + sCount.fTime = atof(pNumber); + } + if(pPtr == NULL){ + return 1; + } + + while((pPtr = stptok(pPtr,pNumber,29," \t")) != NULL) { sCount.Monitors[iCount] = atoi(pNumber); iCount++; @@ -924,256 +442,101 @@ int StoreScanCounts(pScanData self, char *data) sCount.i = self->iCounts; DynarReplace(self->pCounts,self->iCounts,&sCount,sizeof(CountEntry)); self->iCounts++; + if(self->iCounts > self->iNP){ + self->iNP++; + } return 1; } -/*--------------------------------------------------------------------------*/ - static int StartToDrive(pScanData self, int iPoint) - { - pVarEntry pVar = NULL; - void *pDings; - int i, iRet, status; - float fVal; - pDummy pDum; - char pBueffel[512]; +/*-----------------------------------------------------------------------*/ +CountEntry CollectCounterData(pScanData self) +{ + int i, iRet; + CountEntry sCount; + char *pAns = NULL, *pPtr = NULL ; + Tcl_Interp *pTcl; + float fVal; - assert(self); - assert(self->pCon); - - - /* loop over all scan variables */ - status = 1; - for(i = 0; i < self->iScanVar; i++) - { - DynarGet(self->pScanVar,i,&pDings); - pVar = (pVarEntry)pDings; - if(pVar) - { - pDum = (pDummy)pVar->pObject; - fVal = pVar->fStart + iPoint * pVar->fStep; - iRet = StartDevice(pServ->pExecutor, - pVar->Name, - pDum->pDescriptor, - pVar->pObject, - self->pCon, - fVal); - if(!iRet) - { - sprintf(pBueffel,"ERROR: Failed to start %s",pVar->Name); - SCWrite(self->pCon,pBueffel,eError); - status = 0; - break; - } - } - } - return status; - } -/*------------------------------------------------------------------------*/ - static int CollectScanDataIntern(pScanData self, int iPoint, int jochenFlag) - { - pVarEntry pVar = NULL; - void *pDings; - int i, iRet, status; - float fVal; - char pStatus[512], pItem[20]; - char pHead[512]; - CountEntry sCount; - char *pAns = NULL, *pPtr = NULL ; - Tcl_Interp *pTcl; + InitCountEntry(&sCount); - assert(self); - assert(self->pCon); - - /* prepare output header */ - sprintf(pHead,"%-5.5s","NP"); - sprintf(pStatus,"%-5d",iPoint); - - /* loop over all scan variables */ - status = 1; - for(i = 0; i < self->iScanVar; i++) - { - DynarGet(self->pScanVar,i,&pDings); - pVar = (pVarEntry)pDings; - if(pVar) - { - if(jochenFlag == 1 && - strcmp(pVar->pObject->pDescriptor->name, "Motor") == 0) - { - MotorGetSoftPosition((pMotor)pVar->pObject,self->pCon,&fVal); - } - else - { - fVal = pVar->pInter->GetValue(pVar->pObject,self->pCon); - } - pVar->fData[iPoint] = fVal; - sprintf(pItem,"%-10.10s",pVar->Name); - strcat(pHead,pItem); - sprintf(pItem,"%-10.3f",fVal); - strcat(pStatus,pItem); - } - } - - /* store counter data */ - /* monitors */ - for(i = 1; i < 10; i++) - { - sCount.Monitors[i-1] = GetMonitor((pCounter)self->pCounterData,i, + /* monitors */ + for(i = 1; i < 10; i++) + { + sCount.Monitors[i-1] = GetMonitor((pCounter)self->pCounterData,i, self->pCon); - } - if( self->iChannel != 0 && self->iChannel != -10 ) - { - sCount.Monitors[self->iChannel - 1] = - GetCounts((pCounter)self->pCounterData, - self->pCon); - } - /* counts, depending on iChannel */ - strcat(pHead,"Counts "); - if(self->iChannel == -10) - { - /* execute the Tcl-script for getting the data */ - pTcl = (Tcl_Interp *)self->pSics->pTcl; - if(!self->pCommand) - { - SCWrite(self->pCon, + } + if( self->iChannel != 0 && self->iChannel != -10 ) + { + sCount.Monitors[self->iChannel - 1] = + GetCounts((pCounter)self->pCounterData, + self->pCon); + } + + /* counts, depending on iChannel */ + if(self->iChannel == -10) + { + /* execute the Tcl-script for getting the data */ + pTcl = InterpGetTcl(self->pSics); + if(!self->pCommand) + { + SCWrite(self->pCon, "ERROR: command must be configured for user defined scans", eError); - SCSetInterrupt(self->pCon,eAbortBatch); - return 0; - } - iRet = Tcl_Eval(pTcl,self->pCommand); - if(iRet != TCL_OK) - { - SCWrite(self->pCon,pTcl->result,eError); - return 0; - } - /* interprete the Tcl result as a list of counts - WARNING: this may need to be changed when switching to - future versions of Tcl - */ - pAns = strdup(pTcl->result); - pPtr = strtok(pAns," "); - if(!pPtr) - { - SCWrite(self->pCon,"ERROR: no counts found in Tcl-result",eError); - return 0; - } - sscanf(pPtr,"%f",&fVal); - sCount.lCount = (long)fVal; - i = 0; - while( (pPtr != NULL) && (i < 10)) - { - pPtr = strtok(NULL," "); - if(pPtr) - { - sscanf(pPtr,"%f",&fVal); - sCount.Monitors[i] = (long)fVal; - i++; - } - } - free(pAns); - } - else if(self->iChannel == 0) - { - sCount.lCount = GetCounts((pCounter)self->pCounterData,self->pCon); - } - else - { - sCount.lCount = GetMonitor((pCounter)self->pCounterData, + SCSetInterrupt(self->pCon,eAbortBatch); + return sCount; + } + iRet = Tcl_Eval(pTcl,self->pCommand); + if(iRet != TCL_OK) + { + SCWrite(self->pCon,pTcl->result,eError); + return sCount; + } + /* interprete the Tcl result as a list of counts + WARNING: this may need to be changed when switching to + future versions of Tcl + */ + pAns = strdup(pTcl->result); + pPtr = strtok(pAns," "); + if(!pPtr) + { + SCWrite(self->pCon,"ERROR: no counts found in Tcl-result",eError); + } + sscanf(pPtr,"%f",&fVal); + sCount.lCount = (long)fVal; + i = 0; + while( (pPtr != NULL) && (i < 10)) + { + pPtr = strtok(NULL," "); + if(pPtr) + { + sscanf(pPtr,"%f",&fVal); + sCount.Monitors[i] = (long)fVal; + i++; + } + } + free(pAns); + } + else if(self->iChannel == 0) + { + sCount.lCount = GetCounts((pCounter)self->pCounterData,self->pCon); + } + else + { + sCount.lCount = GetMonitor((pCounter)self->pCounterData, self->iChannel, self->pCon); - } - sprintf(pItem,"%-15d",sCount.lCount); - strcat(pStatus,pItem); - - /* get time */ - sCount.fTime = GetCountTime((pCounter)self->pCounterData, + } + + /* get time */ + sCount.fTime = GetCountTime((pCounter)self->pCounterData, self->pCon); - strcat(pHead,"Monitor1 "); - sprintf(pItem,"%-12d",sCount.Monitors[0]); - strcat(pStatus,pItem); - strcat(pHead,"Monitor2 "); - sprintf(pItem,"%-12d",sCount.Monitors[1]); - strcat(pStatus,pItem); - strcat(pHead,"Monitor3 "); - sprintf(pItem,"%-12d",sCount.Monitors[2]); - strcat(pStatus,pItem); - strcat(pHead,"Time "); - sprintf(pItem,"%-6.1f",sCount.fTime); - strcat(pStatus,pItem); - - /* write progress */ - strcat(pHead,"\n"); - strcat(pStatus,"\n"); - SCWrite(self->pCon,pHead,eWarning); - SCWrite(self->pCon,pStatus,eWarning); - - /* stow away */ - DynarReplace(self->pCounts,self->iCounts,&sCount,sizeof(CountEntry)); - self->iCounts++; - return 1; - } -/*---------------------------------------------------------------------------*/ - static int CollectScanData(pScanData self, int iPoint) - { - return CollectScanDataIntern(self,iPoint,0); - } -/*--------------------------------------------------------------------------*/ - static int CollectScanDataJochen(pScanData self, int iPoint) - { - return CollectScanDataIntern(self,iPoint,1); - } -/*------------------------------------------------------------------------*/ - static int ScanDrive(pScanData self, int iPoint) - { - int iRet; - long lTask; - int status; - - iRet = StartToDrive(self,iPoint); - if(!iRet) - { - SCWrite(self->pCon,"ERROR: Cannot Drive, Scan aborted",eError); - status = 0; - } - else - { - status = 1; - } - /* wait for finish */ - lTask = GetDevexecID(pServ->pExecutor); - if(lTask > 0) - { - TaskWait(pServ->pTasker,lTask); - } - return status; - } -/*--------------------------------------------------------------------------*/ - static int ScanCount(pScanData self, int iPoint) - { - pDummy pDum; - int iRet; - long lTask; - - pDum = (pDummy)self->pCounterData; - iRet = StartDevice(pServ->pExecutor, - "ScanCounter", - pDum->pDescriptor, - self->pCounterData, - self->pCon, - self->fPreset); - if(!iRet) - { - SCWrite(self->pCon,"ERROR: Cannot Count, Scan aborted",eError); - return 0; - } - SetStatus(eCounting); - /* wait for finish */ - lTask = GetDevexecID(pServ->pExecutor); - if(lTask > 0); - { - TaskWait(pServ->pTasker,lTask); - } - return 1; + /* stow away */ + DynarReplace(self->pCounts,self->iCounts,&sCount,sizeof(CountEntry)); + self->iCounts++; + if(self->iCounts > self->iNP){ + self->iNP++; } + return sCount; +} /*---------------------------------------------------------------------------*/ static int ScanLoop(pScanData self) { @@ -1260,7 +623,6 @@ int StoreScanCounts(pScanData self, char *data) WriteRecover(self); } } - return 1; } /*--------------------------------------------------------------------------*/ @@ -1433,10 +795,12 @@ int StoreScanCounts(pScanData self, char *data) return iRet; } /*--------------------------------------------------------------------------*/ - int RecoverScan(pScanData self, SicsInterp *pSics, SConnection *pCon) + int ContinueScan(pScanData self, SicsInterp *pSics, SConnection *pCon, + int argc, char *argv[]) { int iRet; char *pPtr = NULL, pBueffel[512]; + double dVal; assert(pSics); assert(pCon); @@ -1444,12 +808,45 @@ int StoreScanCounts(pScanData self, char *data) self->pCon = pCon; self->pSics = pSics; - /* read recover file */ - iRet = ReadRecover(self); - if(!iRet) + if(argc < 5) { - return iRet; + SCWrite(pCon,"ERROR: not enough arguments to scan continue",eError); + return 0; } + + /* get NP */ + iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&self->iNP); + if(iRet != TCL_OK) + { + sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); + SCWrite(pCon,pBueffel,eError); + return 0; + } + /* interpret Mode */ + if(strcmp(argv[3],"timer") == 0) + { + self->iMode = eTimer; + } + else if(strcmp(argv[3],"monitor") == 0) + { + self->iMode = ePreset; + } + else + { + sprintf(pBueffel,"ERROR: %s not recognized as valid counter mode", + argv[3]); + SCWrite(pCon,pBueffel,eError); + return 0; + } + /* preset */ + iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&dVal); + if(iRet != TCL_OK) + { + sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); + SCWrite(pCon,pBueffel,eError); + return 0; + } + self->fPreset = dVal; /* configure counter */ SetCounterMode((pCounter)self->pCounterData,self->iMode); @@ -1605,9 +1002,7 @@ int StoreScanCounts(pScanData self, char *data) { fData[i] = pVar->fStart + i * pVar->fStep; } - - /* copy the actual scan data */ - memcpy(fData,pVar->fData,iEnd*sizeof(float)); + CopyScanVar(pVar,fData, self->iNP); return 1; } else @@ -1677,7 +1072,7 @@ int StoreScanCounts(pScanData self, char *data) pVar = (pVarEntry)pPtr; if(pVar) { - strncpy(pName,pVar->Name,iLength); + strncpy(pName,ScanVarName(pVar),iLength); return 1; } else @@ -1706,7 +1101,7 @@ int isScanVarSoft(pScanData self){ pVar = (pVarEntry)pPtr; if(pVar) { - *fStep = pVar->fStep; + *fStep = ScanVarStep(pVar); return 1; } else @@ -1763,6 +1158,8 @@ int isScanVarSoft(pScanData self){ assert(self); + InitCountEntry(&sCount); + /* go to a clean state */ ClearScanVar(self); @@ -1786,18 +1183,14 @@ int isScanVarSoft(pScanData self){ { return 0; } - pVar->fData = (float *)malloc(90*sizeof(float)); - if(!pVar->fData) - { - return 0; - } /* create scan data in loop */ fStdDev = FWHM/2.354; for(i = 0; i < 90; i++) { - x = pVar->fData[i] = 10. + 0.1 * i; + x = 10. + 0.1 * i; + AppendScanVar(pVar,x); sCount.i = i; /* gaussian */ fTmp = (x - fPos)/fStdDev; @@ -1853,7 +1246,8 @@ int isScanVarSoft(pScanData self){ SCWrite(pCon,pBueffel,eError); return 0; } - pNew = CreateScanObject(argv[4],argv[3],(pCounter)pCom->pData); + pNew = CreateScanObject(argv[4],argv[3],(pCounter)pCom->pData, + argv[1]); if(!pNew) { SCWrite(pCon,"ERROR: failure to allocate scan data structure", @@ -1872,6 +1266,15 @@ int isScanVarSoft(pScanData self){ SCWrite(pCon,pBueffel,eError); return 0; } + /* + ignore this one, this is cheaper then checking for the existence + of another scan object + */ + AddCommand(pSics, + "stdscan", + StandardScanWrapper, + NULL, + NULL); return 1; } /*--------------------------------------------------------------------------*/ @@ -1920,12 +1323,13 @@ int isScanVarSoft(pScanData self){ GetScanCounts(self,lData,self->iNP); /* format a message */ - strcpy(pPtr,"scan.Counts= "); + strcpy(pPtr,"scan.Counts= {"); for(i = 0; i < self->iNP; i++) { - sprintf(pItem,"{%d} ",lData[i]); + sprintf(pItem,"%d ",lData[i]); strcat(pPtr,pItem); } + strcat(pPtr,"}"); oldWrite = SCGetWriteFunc(pCon); SCSetWriteFunc(pCon,SCOnlySockWrite); SCWrite(pCon,pPtr,eWarning); @@ -1936,6 +1340,58 @@ int isScanVarSoft(pScanData self){ } return 1; } +/*--------------------------------------------------------------------------*/ + static int ScanDynInterest(int iEvent, void *pEventData, void *pUser) + { + pScanData self = NULL; + SConnection *pCon = NULL; + void *pPtr; + pVarEntry pVar; + pCountEntry pCount = NULL; + float fVal; + long lVal; + int i; + char pBueffel[256]; + + self = (pScanData)pEventData; + pCon = (SConnection *)pUser; + + assert(self); + assert(pCon); + + if(iEvent == SCANSTART) + { + SCWrite(pCon,"NewScan",eWarning); + return 1; + } + else if(iEvent == SCANEND) + { + SCWrite(pCon,"ScanEnd",eWarning); + return 1; + } + else if(iEvent == SCANPOINT) + { + i = self->iCounts -1; + DynarGet(self->pScanVar,0,&pPtr); + pVar = (pVarEntry)pPtr; + if(pVar != NULL){ + fVal = GetScanVarPos(pVar,i); + } else { + fVal = -9999.99; + } + DynarGet(self->pCounts,i,&pPtr); + pCount =(pCountEntry)pPtr; + if(pCount != NULL){ + lVal = pCount->lCount; + } else { + lVal = -9999.99; + } + snprintf(pBueffel,255,"%s.scanpoint = {%d %f %d}", + self->objectName,i,fVal,lVal); + SCWrite(pCon,pBueffel,eValue); + } + return 1; + } /*--------------------------------------------------------------------------*/ static int ScanUUInterest(int iEvent, void *pEventData, void *pUser) { @@ -1988,6 +1444,252 @@ int isScanVarSoft(pScanData self){ } return 1; } +/*--------------------------------------------------------------------------*/ +static int GetVarPar(SConnection *pCon, pScanData self, char *scanname, int i) +{ + char pBueffel[512]; + void *pPtr = NULL; + pVarEntry pVar = NULL; + + assert(pCon); + assert(self); + + if(i < 0 || i >= self->iScanVar) + { + SCWrite(pCon,"ERROR: scan variable number out of range",eError); + return 0; + } + + DynarGet(self->pScanVar,i,&pPtr); + pVar = (pVarEntry)pPtr; + if(pVar != NULL) + { + snprintf(pBueffel, 511,"%s.%s = %f = %f", + scanname, + ScanVarName(pVar), + ScanVarStart(pVar), + ScanVarStep(pVar)); + SCWrite(pCon,pBueffel,eValue); + return 1; + } + return 0; +} +/*--------------------------------------------------------------------------*/ +static int AppendVarPos(SConnection *pCon, pScanData self, + int scanVar, float fPos) +{ + char pBueffel[512]; + void *pPtr = NULL; + pVarEntry pVar = NULL; + + assert(pCon); + assert(self); + + if(scanVar < 0 || scanVar >= self->iScanVar) + { + SCWrite(pCon,"ERROR: scan variable number out of range",eError); + return 0; + } + + DynarGet(self->pScanVar,scanVar,&pPtr); + pVar = (pVarEntry)pPtr; + if(pVar != NULL) + { + AppendScanVar(pVar,fPos); + return 1; + } + return 0; +} +/*--------------------------------------------------------------------------*/ +static void PrintScanVars(pScanData self, char *scanname, SConnection *pCon){ + char pBueffel[1024]; + pVarEntry pVar = NULL; + void *pPtr = NULL; + int i; + + assert(pCon); + assert(self); + + snprintf(pBueffel,1023,"%s.scanvars = { ", scanname); + for(i = 0; i < self->iScanVar; i++){ + DynarGet(self->pScanVar,i,&pPtr); + pVar = (pVarEntry)pPtr; + if(pVar != NULL){ + strncat(pBueffel,ScanVarName(pVar),1023-strlen(pBueffel)); + strcat(pBueffel," "); + } + } + strcat(pBueffel,"}"); + SCWrite(pCon,pBueffel,eValue); +} +/*--------------------------------------------------------------------------*/ +static int PrintCountsOrMonitors(pScanData self, SConnection *pCon, + char *name, int iWhich) +{ + pDynString data = NULL; + long *lData = NULL; + char pBueffel[60]; + int i; + + if(self->iNP < 1) + { + SCWrite(pCon,"ERROR: no scan data available",eError); + return 0; + } + + data = CreateDynString(80,80); + lData = (long *)malloc(self->iNP*sizeof(long)); + if(data == NULL || lData == NULL) + { + SCWrite(pCon,"ERROR: out of memory printing counts",eError); + return 0; + } + memset(lData,0,self->iNP*sizeof(long)); + + if(iWhich < 0) + { + GetScanCounts(self,lData,self->iNP); + snprintf(pBueffel,59,"%s.counts = {", name); + } + else + { + GetScanMonitor(self,iWhich,lData,self->iNP); + snprintf(pBueffel,59,"%s.mon%2.2d = {", name, iWhich); + } + DynStringCopy(data,pBueffel); + for(i = 0; i < self->iNP; i++) + { + snprintf(pBueffel,59," %ld", lData[i]); + DynStringConcat(data,pBueffel); + } + DynStringConcatChar(data,'}'); + SCWrite(pCon,GetCharArray(data),eValue); + DeleteDynString(data); + free(lData); + return 1; +} +/*--------------------------------------------------------------------------*/ +static int PrintTimes(pScanData self, SConnection *pCon, + char *name) +{ + pDynString data = NULL; + char pBueffel[60]; + int i, iEnd; + pCountEntry pData = NULL; + void *pPtr = NULL; + + if(self->iNP < 1) + { + SCWrite(pCon,"ERROR: no scan data available",eError); + return 0; + } + + data = CreateDynString(80,80); + if(data == NULL) + { + SCWrite(pCon,"ERROR: out of memory printing counts",eError); + return 0; + } + + snprintf(pBueffel,59,"%s.scantimes = { ",name); + DynStringCopy(data,pBueffel); + for(i = 0; i < self->iNP; i++) + { + DynarGet(self->pCounts,i,&pPtr); + pData = (pCountEntry)pPtr; + if(pData) + { + snprintf(pBueffel,59," %f", pData->fTime); + DynStringConcat(data,pBueffel); + } + } + DynStringConcatChar(data,'}'); + SCWrite(pCon,GetCharArray(data),eValue); + DeleteDynString(data); + return 1; +} +/*------------------------------------------------------------------------*/ +static int ScanInvokeCallback(pScanData self, SConnection *pCon, char *name) +{ + int eventID; + + if(strcmp(name,"scanstart") == 0){ + eventID = SCANSTART; + }else if(strcmp(name,"scanpoint") == 0){ + eventID = SCANPOINT; + }else if(strcmp(name,"scanend") == 0){ + eventID = SCANEND; + } else { + SCWrite(pCon,"ERROR: callback ID not recognised",eError); + return 0; + } + InvokeCallBack(self->pCall,eventID, self); + SCSendOK(pCon); + return 1; +} +/*-----------------------------------------------------------------------*/ +static void ListScanFunctions(pScanData self, SConnection *pCon){ + pDynString result = NULL; + char pValue[256], *pPtr = NULL; + + result = CreateDynString(80,80); + if(result == NULL){ + SCWrite(pCon,"ERROR: failed to allocate memory in function list",eError); + return; + } + while( (pPtr = (char *)StringDictGetNext(self->scanFunctions, + pValue,255)) != NULL){ + DynStringConcat(result, pPtr); + DynStringConcat(result," = "); + DynStringConcat(result, pValue); + DynStringConcatChar(result, '\n'); + } + SCWrite(pCon,GetCharArray(result), eValue); + DeleteDynString(result); +} +/*-------------------------------------------------------------------------*/ +static int InterpretScanFunctions(pScanData self, SConnection *pCon, + int argc, char *argv[]){ + char pValue[256]; + char response[512]; + + if(argc < 3){ + SCWrite(pCon,"ERROR: need subcommand to scan function",eError); + return 0; + } + strtolower(argv[2]); + if(strcmp(argv[2],"list") == 0){ + ListScanFunctions(self,pCon); + return 1; + } + + if(argc > 3){ + /* + set case + */ + Arg2Text(argc-3,&argv[3],pValue,255); + if(!StringDictUpdate(self->scanFunctions,argv[2],pValue)){ + snprintf(pValue,255,"ERROR: scan function %s not found",argv[2]); + SCWrite(pCon,pValue,eError); + return 0; + } + } + + /* + request case + */ + if(StringDictGet(self->scanFunctions,argv[2],pValue,255)){ + snprintf(response,511,"%s function %s = %s",argv[0],argv[2], + pValue); + SCWrite(pCon,response,eValue); + return 1; + } else { + snprintf(pValue,255,"ERROR: scan function %s not found",argv[2]); + SCWrite(pCon,pValue,eError); + return 0; + } + return 0; +} /*---------------------------------------------------------------------------*/ int ScanWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]) @@ -2008,6 +1710,7 @@ int isScanVarSoft(pScanData self){ double x; float fPos, FWHM, fHeight; pSite site = NULL; + SConnection *conSave; self = (pScanData)pData; assert(self); @@ -2020,7 +1723,10 @@ int isScanVarSoft(pScanData self){ return 0; } -/*------------ first interpret commands which do not require user rights */ + /* + first interpret commands which do not require user rights + */ + /*---------- getfile */ if(strcmp(argv[1],"getfile") == 0) { @@ -2028,43 +1734,37 @@ int isScanVarSoft(pScanData self){ SCWrite(pCon,pBueffel,eValue); return 1; } + if(strcmp(argv[1],"getscanvars") == 0) + { + PrintScanVars(self,argv[0],pCon); + return 1; + } /*--------- getcounts */ else if(strcmp(argv[1],"getcounts") == 0) { - /* get some memory */ - if(self->iNP < 1) - { - SCWrite(pCon,"ERROR: no counts available",eError); - return 0; + return PrintCountsOrMonitors(self,pCon,argv[0],-77); + } +/*------------ getmonitor */ + else if(strcmp(argv[1],"getmonitor") == 0) + { + if(argc < 3) + { + SCWrite(pCon,"ERROR: need monitor number to print",eError); + return 0; } - lData = (long *)malloc(self->iNP*sizeof(long)); - if(!lData) + iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&i); + if(iRet != TCL_OK) { - SCWrite(pCon,"ERROR: out of memory in scan",eError); - return 0; - } - pPtr = (char *)malloc((self->iNP*20+20)*sizeof(char)); - if(!pPtr) - { - SCWrite(pCon,"ERROR: out of memory in scan",eError); - return 0; - } - memset(pPtr,0,(self->iNP*20+20)*sizeof(char)); - - /* get counts */ - GetScanCounts(self,lData,self->iNP); - - /* format them */ - strcpy(pPtr,"scan.Counts= "); - for(i = 0; i < self->iNP; i++) - { - sprintf(pItem,"{%d} ",lData[i]); - strcat(pPtr,pItem); - } - SCWrite(pCon,pPtr,eValue); - free(lData); - free(pPtr); - return 1; + sprintf(pBueffel,"ERROR: expected integer, got %s",argv[2]); + SCWrite(pCon,pBueffel,eError); + return 0; + } + return PrintCountsOrMonitors(self,pCon,argv[0],i); + } +/*--------- gettimes */ + else if(strcmp(argv[1],"gettimes") == 0) + { + return PrintTimes(self,pCon,argv[0]); } /*---------- uucounts */ else if(strcmp(argv[1],"uucounts") == 0) @@ -2118,7 +1818,7 @@ int isScanVarSoft(pScanData self){ /* we need an integer parameter saying which */ if(argc >= 3) { - iRet = Tcl_GetInt(pSics->pTcl,argv[2],&i); + iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&i); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: expected integer, got %s",argv[2]); @@ -2168,7 +1868,7 @@ int isScanVarSoft(pScanData self){ } /* format them */ - sprintf(pPtr,"scan.%s = ", pVar->Name); + sprintf(pPtr,"scan.%s = ", ScanVarName(pVar)); for(i = 0; i < self->iNP; i++) { sprintf(pItem,"{%12.3f} ",fData[i]); @@ -2179,6 +1879,28 @@ int isScanVarSoft(pScanData self){ free(pPtr); return 1; } +/*---------getvarpar */ + else if(strcmp(argv[1],"getvarpar") == 0) + { + /* we need an integer parameter saying which */ + if(argc >= 3) + { + iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&i); + if(iRet != TCL_OK) + { + sprintf(pBueffel,"ERROR: expected integer, got %s",argv[2]); + SCWrite(pCon,pBueffel,eError); + return 0; + } + } + else + { + SCWrite(pCon,"ERROR: expected number of variable to retrieve data for ", + eError); + return 0; + } + return GetVarPar(pCon,self,argv[0],i); + } /*-------- interest */ else if(strcmp(argv[1],"interest") == 0) { @@ -2194,6 +1916,21 @@ int isScanVarSoft(pScanData self){ SCSendOK(pCon); return 1; } +/*-------- interest */ + else if(strcmp(argv[1],"dyninterest") == 0) + { + lID = RegisterCallback(self->pCall, SCANSTART, ScanDynInterest, + pCon, NULL); + SCRegister(pCon,pSics, self->pCall,lID); + lID = RegisterCallback(self->pCall, SCANEND, ScanDynInterest, + pCon, NULL); + SCRegister(pCon,pSics, self->pCall,lID); + lID = RegisterCallback(self->pCall, SCANPOINT, ScanDynInterest, + pCon, NULL); + SCRegister(pCon,pSics, self->pCall,lID); + SCSendOK(pCon); + return 1; + } /*-------- uuinterest */ else if(strcmp(argv[1],"uuinterest") == 0) { @@ -2238,14 +1975,14 @@ int isScanVarSoft(pScanData self){ return 0; } /* get numbers */ - iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&fStart); + iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&fStart); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); SCWrite(pCon,pBueffel,eError); return 0; } - iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&fStep); + iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&fStep); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); @@ -2276,6 +2013,16 @@ int isScanVarSoft(pScanData self){ } return 1; } +/* --------callback */ + else if(strcmp(argv[1],"callback") == 0) + { + if(argc < 3) + { + SCWrite(pCon,"ERROR: need callback ID for invocation",eError); + return 0; + } + return ScanInvokeCallback(self,pCon,argv[2]); + } /*------------ configure */ else if(strcmp(argv[1],"configure") == 0) { @@ -2284,7 +2031,7 @@ int isScanVarSoft(pScanData self){ SCWrite(pCon,"ERROR: missing configure option",eError); return 0; } - /* this is for userss only */ + /* this is for users only */ if(!SCMatchRights(pCon,usUser)) return 0; strtolower(argv[2]); @@ -2300,6 +2047,12 @@ int isScanVarSoft(pScanData self){ SCSendOK(pCon); return 1; } + else if(strcmp(argv[2],"script") == 0) + { + ConfigureScript(self); + SCSendOK(pCon); + return 1; + } else if(strcmp(argv[2],"soft") == 0) { ResetScanFunctions(self); @@ -2325,11 +2078,16 @@ int isScanVarSoft(pScanData self){ } } } +/*------------ functions */ + else if(strcmp(argv[1],"function") == 0) + { + return InterpretScanFunctions(self, pCon, argc, argv); + } /*---------- scan */ else if(strcmp(argv[1],"run") == 0) { /* get NP */ - iRet = Tcl_GetInt(pSics->pTcl,argv[2],&lNP); + iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&lNP); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); @@ -2353,7 +2111,7 @@ int isScanVarSoft(pScanData self){ return 0; } /* preset */ - iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&fPreset); + iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&fPreset); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); @@ -2368,11 +2126,16 @@ int isScanVarSoft(pScanData self){ } return iRet; } +/*------------ continue */ + else if(strcmp(argv[1],"continue") == 0) + { + return ContinueScan(self,pSics,pCon,argc,argv); + } /*---------- silent */ else if(strcmp(argv[1],"silent") == 0) { /* get NP */ - iRet = Tcl_GetInt(pSics->pTcl,argv[2],&lNP); + iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&lNP); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); @@ -2396,7 +2159,7 @@ int isScanVarSoft(pScanData self){ return 0; } /* preset */ - iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&fPreset); + iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&fPreset); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); @@ -2411,16 +2174,6 @@ int isScanVarSoft(pScanData self){ } return iRet; } -/*--------- recover */ - else if(strcmp(argv[1],"recover") == 0) - { - iRet = RecoverScan(self,pSics,pCon); - if(iRet) - { - SCSendOK(pCon); - } - return iRet; - } /*----------- setchannel */ else if(strcmp(argv[1],"setchannel") == 0) { @@ -2430,7 +2183,7 @@ int isScanVarSoft(pScanData self){ return 0; } /* convert to int */ - iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iChannel); + iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&iChannel); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: expected integer, got %s", argv[2]); @@ -2473,7 +2226,7 @@ int isScanVarSoft(pScanData self){ if(argc > 2) { /* set value */ - iRet = Tcl_GetInt(pSics->pTcl,argv[2],&iChannel); + iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&iChannel); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); @@ -2533,7 +2286,7 @@ int isScanVarSoft(pScanData self){ SCWrite(pCon,"ERROR expected fPos FWHM Height parameters",eError); return 0; } - iRet = Tcl_GetDouble(pSics->pTcl,argv[2],&x); + iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[2],&x); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); @@ -2541,7 +2294,7 @@ int isScanVarSoft(pScanData self){ return 0; } fPos = x; - iRet = Tcl_GetDouble(pSics->pTcl,argv[3],&x); + iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&x); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); @@ -2549,7 +2302,7 @@ int isScanVarSoft(pScanData self){ return 0; } FWHM = x; - iRet = Tcl_GetDouble(pSics->pTcl,argv[4],&x); + iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[4],&x); if(iRet != TCL_OK) { sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); @@ -2578,6 +2331,43 @@ int isScanVarSoft(pScanData self){ Arg2Text(argc-2,&argv[2],pBueffel,511); return StoreScanCounts(self,pBueffel); } +/*----------------- appendvarpos */ + else if(strcmp(argv[1],"appendvarpos") == 0) + { + if(argc < 4) + { + SCWrite(pCon, + "ERROR: insufficient number of arguments to appendvarpos", + eError); + return 0; + } + iRet = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&i); + if(iRet != TCL_OK) + { + sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); + SCWrite(pCon,pBueffel,eError); + return 0; + } + iRet = Tcl_GetDouble(InterpGetTcl(pSics),argv[3],&fStep); + if(iRet != TCL_OK) + { + sprintf(pBueffel,"ERROR: expected number, got %s",argv[3]); + SCWrite(pCon,pBueffel,eError); + return 0; + } + return AppendVarPos(pCon,self,i,(float)fStep); + } +/*------- savecounter */ + else if(strcmp(argv[1],"savecounter") == 0) + { + conSave = self->pCon; + self->pCon = pCon; + CollectCounterData(self); + self->pCon = conSave; + if(SCGetInterrupt(pCon) >= eAbortScan){ + return 0; + } + } else { sprintf(pBueffel,"ERROR: %s not recognized as subcommand to %s", @@ -2586,8 +2376,3 @@ int isScanVarSoft(pScanData self){ return 0; } } - - - - - diff --git a/scan.h b/scan.h index 5ed7943e..aeea5377 100644 --- a/scan.h +++ b/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, diff --git a/scan.i b/scan.i index a2b8c55e..5bf55307 100644 --- a/scan.i +++ b/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); diff --git a/scan.tex b/scan.tex index aa0ebeb8..bb502b97 100644 --- a/scan.tex +++ b/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} diff --git a/scan.w b/scan.w index 199cc5be..c214690e 100644 --- a/scan.w +++ b/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" +@ +/*---------------------------------------------------------------------*/ +@ +#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" @ + +/* + 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 +@ + +#endif +@} diff --git a/scanvar.c b/scanvar.c new file mode 100644 index 00000000..6f49bf36 --- /dev/null +++ b/scanvar.c @@ -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 +#include +#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); + } +} + diff --git a/scanvar.h b/scanvar.h new file mode 100644 index 00000000..93303639 --- /dev/null +++ b/scanvar.h @@ -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 diff --git a/servlog.c b/servlog.c index d50176fe..5bb33b06 100644 --- a/servlog.c +++ b/servlog.c @@ -259,8 +259,8 @@ { printf("ERROR: cannot open logfile %s for writing\n", pFile); - - exit(1); + fLogFile = NULL; + return; } } diff --git a/stdscan.c b/stdscan.c new file mode 100644 index 00000000..8b20e44d --- /dev/null +++ b/stdscan.c @@ -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 +#include +#include +#include +#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; +} diff --git a/stdscan.h b/stdscan.h new file mode 100644 index 00000000..f2cd1369 --- /dev/null +++ b/stdscan.h @@ -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 diff --git a/tclev.c b/tclev.c index 75cbebb6..e44a2286 100644 --- a/tclev.c +++ b/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); diff --git a/telnet.c b/telnet.c index 6153f47d..e426a197 100644 --- a/telnet.c +++ b/telnet.c @@ -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);