diff --git a/Makefile b/Makefile index 706daf48..2c383f58 100644 --- a/Makefile +++ b/Makefile @@ -44,7 +44,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ hklscan.o xytable.o amor2t.o nxamor.o amorscan.o amorstat.o \ circular.o el755driv.o maximize.o sicscron.o tecsdriv.o sanscook.o \ tasinit.o tasutil.o t_rlp.o t_conv.o d_sign.o d_mod.o \ - tasdrive.o + tasdrive.o tasscan.o MOTOROBJ = motor.o el734driv.o simdriv.o el734dc.o pipiezo.o pimotor.o COUNTEROBJ = countdriv.o simcter.o counter.o diff --git a/danu.dat b/danu.dat index e0114da8..07cc6631 100644 --- a/danu.dat +++ b/danu.dat @@ -1,3 +1,3 @@ - 7307 + 7459 NEVER, EVER modify or delete this file You'll risk eternal damnation and a reincarnation as a cockroach!|n \ No newline at end of file diff --git a/evcontroller.c b/evcontroller.c index 340253dd..8b9b20f5 100644 --- a/evcontroller.c +++ b/evcontroller.c @@ -811,7 +811,14 @@ { ObPar *pPar = NULL; assert(self); - + + + if(strcmp(name,"target") == 0) + { + *fVal = self->fTarget; + return 1; + } + pPar = ObParFind(self->pParam,name); if(pPar) { diff --git a/faverage.c b/faverage.c index 52541cce..7c0a1ae2 100644 --- a/faverage.c +++ b/faverage.c @@ -158,7 +158,8 @@ return 0; } - /* another parameter, if available describes the detector bank* + /* another parameter, if available describes the detector bank + */ if(argc > 3) { iRet = Tcl_GetInt(pSics->pTcl,argv[3],&iBank); diff --git a/histmem.c b/histmem.c index ea3bd9f5..2ebc647b 100644 --- a/histmem.c +++ b/histmem.c @@ -61,6 +61,7 @@ #include "sinqhmdriv.i" #include "dynstring.h" #include "event.h" +#include "status.h" /* #define LOADDEBUG 1 @@ -1663,9 +1664,15 @@ { if(!SCMatchRights(pCon,usMugger)) { - SCWrite(pCon,"ERROR: yoy are not authorised for this operation",eError); + SCWrite(pCon,"ERROR: you are not authorised for this operation",eError); return 0; } + if(GetStatus() == eCounting) + { + SCWrite(pCon,"ERROR: cannot modify timebinning while counting", + eError); + return 0; + } if(argc < 5) { SCWrite(pCon,"ERROR: not enough aguments to genbin",eError); diff --git a/nxdict.c b/nxdict.c index cdb5b1b2..7dc51116 100644 --- a/nxdict.c +++ b/nxdict.c @@ -41,7 +41,7 @@ extern void *NXpData; extern void (*NXIReportError)(void *pData, char *pBuffer); /*--------------------------------------------------------------------------*/ -/* #define DEFDEBUG 1*/ +/*#define DEFDEBUG 1*/ /* define DEFDEBUG when you wish to print your definition strings before action. This can help a lot to resolve mysteries when working with dictionaries. @@ -682,7 +682,7 @@ {"-LZW",DLZW}, {"-HUF",DHUF}, {"-RLE",DRLE}, - {"",0} }; + {NULL,0} }; /*-----------------------------------------------------------------------*/ static void NXDIDefToken(ParDat *sStat) @@ -995,7 +995,7 @@ {"DFNT_INT32",DFNT_INT32}, {"DFNT_UINT32",DFNT_UINT32}, {"DFNT_CHAR",DFNT_CHAR}, - {"",0} }; + {NULL,-122} }; @@ -1088,7 +1088,7 @@ iRank = atoi(pParse->pToken); break; case DDIM: - iRet = NXDIParseDim (pParse, (int *) iDim); + iRet = NXDIParseDim(pParse, iDim); if(iRet == NX_ERROR) { LLDdelete(iList); @@ -1153,7 +1153,7 @@ /* we need to create it, if we may */ if(pParse->iMayCreate) { - iRet = NXmakedata (hfil, pName, iType, iRank, (int *) iDim); + iRet = NXmakedata(hfil,pName,iType, iRank,iDim); if(iRet != NX_OK) { /* a comment on this one has already been written! */ diff --git a/sicsstat.tcl b/sicsstat.tcl index 9215d79d..240bed34 100644 --- a/sicsstat.tcl +++ b/sicsstat.tcl @@ -1,3 +1,5 @@ +sicsdatapath /data/koenneck/src/sics/tmp/ +sicsdatapath setAccess 1 arx2 4.290000 arx2 setAccess 1 arx1 0.150000 @@ -22,21 +24,21 @@ etam 0.000000 etam setAccess 2 wav 0.000000 wav setAccess 2 -den 0.000000 +den 0.100000 den setAccess 2 -dql 0.000000 +dql 0.010000 dql setAccess 2 dqk 0.000000 dqk setAccess 2 -dqh 0.000000 +dqh 0.010000 dqh setAccess 2 dkf 0.000000 dkf setAccess 2 -def 0.000000 +def 0.500000 def setAccess 2 dki 0.000000 dki setAccess 2 -dei 0.000000 +dei 0.500000 dei setAccess 2 dagl 0.000000 dagl setAccess 2 @@ -68,7 +70,7 @@ da6 0.000000 da6 setAccess 2 da5 0.000000 da5 setAccess 2 -da4 0.000000 +da4 0.500000 da4 setAccess 2 da3 0.000000 da3 setAccess 2 @@ -76,6 +78,32 @@ da2 0.000000 da2 setAccess 2 da1 0.000000 da1 setAccess 2 +bet4 0.000000 +bet4 setAccess 2 +bet3 0.000000 +bet3 setAccess 2 +bet2 0.000000 +bet2 setAccess 2 +bet1 0.000000 +bet1 setAccess 2 +alf4 0.000000 +alf4 setAccess 2 +alf3 0.000000 +alf3 setAccess 2 +alf2 0.000000 +alf2 setAccess 2 +alf1 0.000000 +alf1 setAccess 2 +local Berty Chimney +local setAccess 2 +output a1,a2,a3,a4 +output setAccess 2 +lastcommand sc qh 0 0 2 3 dqh 0.01 0.0 0.01 .1 +lastcommand setAccess 2 +user Billy Looser +user setAccess 2 +title SimSulfid Test +title setAccess 2 f2 0 f2 setAccess 2 f1 0 @@ -98,7 +126,7 @@ if1v 0.000000 if1v setAccess 2 mn 0 mn setAccess 2 -ti 0.000000 +ti 2.000000 ti setAccess 2 np 9 np setAccess 2 @@ -114,25 +142,25 @@ da 3.354000 da setAccess 1 dm 3.354000 dm setAccess 1 -en 2.800000 +en 3.400000 en setAccess 2 -ql 0.000000 +ql 2.040000 ql setAccess 2 qk 0.000000 qk setAccess 2 -qh 2.000000 +qh 0.040000 qh setAccess 2 kf 1.964944 kf setAccess 2 ef 8.000000 ef setAccess 2 -ki 2.283058 +ki 2.345619 ki setAccess 2 -ei 10.800000 +ei 11.400000 ei setAccess 2 -bz 0.000000 +bz 1.000000 bz setAccess 2 -by 1.000000 +by 0.000000 by setAccess 2 bx 0.000000 bx setAccess 2 @@ -144,18 +172,18 @@ ax 1.000000 ax setAccess 2 cc 90.000000 cc setAccess 2 -bb 90.000000 +bb 67.889999 bb setAccess 2 aa 90.000000 aa setAccess 2 -cs 5.000000 +cs 7.000000 cs setAccess 2 bs 5.000000 bs setAccess 2 as 5.000000 as setAccess 2 # Counter counter -counter SetPreset 1000.000000 +counter SetPreset 2.000000 counter SetMode Timer # Motor agl agl SoftZero -0.490000 @@ -192,7 +220,7 @@ mgl AccessCode 2.000000 # Motor atu atu SoftZero -0.880000 atu SoftLowerLim -16.120001 -atu SoftUpperLim 17.879999 +atu SoftUpperLim 17.759998 atu Fixed -1.000000 atu sign 1.000000 atu InterruptMode 0.000000 diff --git a/simcter.c b/simcter.c index ac3b077b..ffdcfc5d 100644 --- a/simcter.c +++ b/simcter.c @@ -48,9 +48,9 @@ #include "countdriv.h" /*--------------------------------------------------------------------------- A SIMCOUNTER HAS a BUILT IN FAILURE RATE OF 10% FOR TESTING ERROR HANDLING - CODE. + CODE. A negative failure rate means absolute success. */ -#define FAILRATE 0.05 +#define FAILRATE -0.05 /*----------------------------------------------------------------------------*/ static float SimRandom(void) { @@ -76,6 +76,14 @@ pSim = (SimSt *)self->pData; assert(pSim); + /* + no fail, no wait case + */ + if(FAILRATE < .0) + { + return HWIdle; + } + if(SimRandom() < FAILRATE) { return HWFault; @@ -159,6 +167,14 @@ pSim->iPause = 1; + /* + no fail, no wait case + */ + if(FAILRATE < .0) + { + return OKOK; + } + if(SimRandom() < FAILRATE) { return HWFault; @@ -220,6 +236,18 @@ pSim = (SimSt *)self->pData; assert(pSim); + /* + no fail, no wait case + */ + if(FAILRATE < .0) + { + for(i = 0; i < MAXCOUNT; i++) + { + self->lCounts[i] = (long)rand(); + } + return OKOK; + } + if(SimRandom() < FAILRATE) { return HWFault; diff --git a/simdriv.c b/simdriv.c index 9bc94907..aebae817 100644 --- a/simdriv.c +++ b/simdriv.c @@ -73,6 +73,15 @@ assert(self); pDriv = (SIMDriv *)self; + /* + no error checking case + */ + if(pDriv->fFailure < .0) + { + *fPos = pDriv->fPos; + return OKOK; + } + if(SimRandom() < pDriv->fFailure) { *fPos = SimRandom(); @@ -100,6 +109,16 @@ assert(self); pDriv = (SIMDriv *)self; + /* + no failure, no wait situation + */ + if(pDriv->fFailure < .0) + { + pDriv->fPos = fVal; + return OKOK; + } + + /* calculate time for completion */ fDiff = fVal - pDriv->fPos; if(fDiff < .0) fDiff = -fDiff; @@ -187,6 +206,15 @@ assert(self); pDriv = (SIMDriv *)self; + + /* + no wait, no fail situation + */ + if(pDriv->fFailure < .0) + { + return HWIdle; + } + if(RunComplete(pDriv)) { return HWIdle; diff --git a/sinqhm/FOCUS_srv_main.c b/sinqhm/FOCUS_srv_main.c index 53b45f14..7916ce3d 100755 --- a/sinqhm/FOCUS_srv_main.c +++ b/sinqhm/FOCUS_srv_main.c @@ -245,8 +245,12 @@ &FS_bytes_got, &FS_bytes_put, FS_name[index]); if (!status || (ntohl (my_rply_bf.status) != KER__SUCCESS)) { if (ntohl (my_rply_bf.status) != KER__SUCCESS) { - printf ("\n%s: error response to SQHM_CNCT request to %s.\n", - FS_name[index], FS_slaves[i]); + printf ( + "\n%s: %s to %s.\n, status = %d, substatus = %d ", + "error response to SINQHM_CNCT", + FS_name[index], FS_slaves[i], + ntohl(my_rply_bf.status), + ntohl(my_rply_bf.sub_status)); } *iret = -6; /* Tell our parent we've given up */ close (clnt_skt); @@ -1765,14 +1769,77 @@ /* **-------------------------------------------------------------------------- ** FS_do_zero: Action routine for SQHM_ZERO command. + * + * This is only partially functional. The definition for SQHM_ZERO states + * that it is possible to zero only parts of the histogram. The version + * below just forwards a full zero request to all slaves and thus fits + * the bill for FOCUS. Probably for any other instrument as well. + * + * Mark Koennecke, November 2000 */ int FS_do_zero ( /* =========== */ struct rply_buff_struct *reply, - int index, + int indx, int nbins, int first_bin, int hist_no) { + + int i, iret, all_ok = True; + struct req_buff_struct request; + + /* + set up the request structure which zeros the whole histogram + */ + request.bigend = htonl(0x12345678); + request.cmnd = htonl(SQHM_ZERO); + request.u.zero.hist_no = htonl(-1); + request.u.zero.first_bin = htonl(-1); + request.u.zero.n_bins = htonl(-1); + + /* + ** Claim the sem to avoid race conditions with other threads + */ + if (FS_use_sem_tmo) { + iret = semTake (FS_sem_daq, FS_sem_tmo); + }else { + iret = semTake (FS_sem_daq, WAIT_FOREVER); + } + + /* + send the request to all known slaves + */ + for (i = 0; i < FS_n_slaves; i++) { + if (FS_slv_active[i]) { + if (indx == 0) { /* If we are the master-server, send it to the + ** master-servers in the slaves. */ + iret = FS_send_cmnd_to_mstr (&FS_rmt_socknam[i], + &request, sizeof (request), reply, + &FS_bytes_got, &FS_bytes_put); + if (!iret || (ntohl (reply->status) != KER__SUCCESS)) all_ok=False; + }else { + iret = rqst_send_get (FS_skt[indx][i], &request, sizeof (request), + reply, sizeof (*reply), + &FS_bytes_got, &FS_bytes_put, FS_name[indx]); + if (!iret || (ntohl (reply->status) != KER__SUCCESS)) all_ok=False; + } + } + } + if (!all_ok) { /* If error, go no further! */ + printf("Error zeroing histogram no %d\n", i); + semGive (FS_sem_daq); + return all_ok; + } + + /* + tell the world about our success + */ + reply->status = htonl (KER__SUCCESS); + + /* release semaphore */ + semGive (FS_sem_daq); + + return True; } /* @@ -2134,7 +2201,7 @@ uint *in_cntr, uint *out_cntr) { - int status, cnct_skt, rmt_sockname_len; + int status, cnct_skt, rmt_sockname_len, i; int bytes_to_come, nbytes; char *p_nxt_byte; struct sockaddr_in lcl_sockname; @@ -2142,12 +2209,20 @@ ** Create a TCP/IP socket for connecting to SINQHM_SRV root and bind it. */ cnct_skt = socket (AF_INET, SOCK_STREAM, 0); - if (cnct_skt == -1) failInet ("\nFS_send_cmnd_to_mstr: socket error."); + i = 1; + setsockopt(cnct_skt,SOL_SOCKET, SO_REUSEADDR, &i,sizeof(int)); + if (cnct_skt == -1) { + close(cnct_skt); + failInet ("\nFS_send_cmnd_to_mstr: socket error."); + } setup_host (NULL, &lcl_sockname, 0, False); status = bind (cnct_skt, (struct sockaddr *) &lcl_sockname, sizeof (lcl_sockname)); - if (status == -1) failInet ("\nFS_send_cmnd_to_mstr: bind error."); + if (status == -1){ + close(cnct_skt); + failInet ("\nFS_send_cmnd_to_mstr: bind error."); + } /* ** Connect to SINQHM_SRV root. */ @@ -2155,6 +2230,7 @@ status = connect (cnct_skt, (struct sockaddr *) rmt_sockname, rmt_sockname_len); if (status == -1) { + close(cnct_skt); getErrno (&FS_errno); failInet ("\nFS_send_cmnd_to_mstr: connect error"); } @@ -2162,10 +2238,14 @@ ** Send the request to the server */ status = send (cnct_skt, (char *) request, requ_len, 0); - if (status == -1) failInet ("\nFS_send_cmnd_to_mstr -- send error"); + if (status == -1) { + close(cnct_skt); + failInet ("\nFS_send_cmnd_to_mstr -- send error"); + } if (status != requ_len) { printf ("\nFS_send_cmnd_to_mstr -- wrong number of bytes sent: %d %d\n", status, requ_len); + close(cnct_skt); return False; } *out_cntr += requ_len; @@ -2182,17 +2262,21 @@ p_nxt_byte += nbytes; } if (nbytes == -1) { + close(cnct_skt); failInet ("\nFS_send_cmnd_to_mstr -- recv error"); return False; }else if (nbytes == 0) { printf ("\nFS_send_cmnd_to_mstr -- server has closed connection!\n"); + close(cnct_skt); return False; }else if (ntohl (reply->bigend) != 0x12345678) { /* Network byte-order wrong! */ printf ("\nFS_send_cmnd_to_mstr -- big-endian/little-endian problem!\n" " Buffer received in non-network byte order!\n"); + close(cnct_skt); return False; } + close(cnct_skt); return True; } /* @@ -2333,6 +2417,8 @@ " -- socket error in socket_bind")); return skt; } + status = 1; + setsockopt(skt,SOL_SOCKET, SO_REUSEADDR, &status, sizeof(int)); setup_host (NULL, &sockname, port, False); status = bind (skt, (struct sockaddr *) &sockname, sizeof (sockname)); @@ -2513,6 +2599,8 @@ sprintf (buff, "\n%s -- Cnct-Socket socket error", FS_name[0]); failInet (buff); } + status = 1; + setsockopt(FS_cnct_skt, SOL_SOCKET, SO_REUSEADDR, &status, sizeof(int)); setup_host (NULL, &lcl_sockname, FS_port, False); status = bind (FS_cnct_skt, (struct sockaddr *) &lcl_sockname, sizeof (lcl_sockname)); diff --git a/sinqhm/Makefile b/sinqhm/Makefile index 02619906..55ef34bf 100644 --- a/sinqhm/Makefile +++ b/sinqhm/Makefile @@ -12,7 +12,7 @@ #------------ for DigitalUnix (add -DFORTIFY to CFLAGS for fortified version) FF = f90 CC = cc -CFLAGS = -std -g -I. -I../hardsup -I$(PGPLOT_DIR) +CFLAGS = -std -g -I. -I../hardsup -I$(PGPLOT_DIR) -I/data/koenneck/include BIN = $(HOME)/bin LFLAGS = -L../hardsup -L$PGPLOT_DIR #------------ for Linux diff --git a/sinqhm/SinqHM_srv_filler.c b/sinqhm/SinqHM_srv_filler.c index ac3358ab..bc574b4a 100755 --- a/sinqhm/SinqHM_srv_filler.c +++ b/sinqhm/SinqHM_srv_filler.c @@ -675,6 +675,7 @@ } if (FillTimer_expired) { + /* if (Print_hdr) printf ("\nTaking data in TOF Mode\n" " #-Events #-Skip #-TSI Delay-Time Sync-Status\n"); Print_hdr = False; @@ -696,6 +697,7 @@ if (is != 0) { printf ("%s -- failed to set timer\n", Filler_name); } + */ } } /* Our flag has been set. There should be .. diff --git a/sinqhm/SinqHM_srv_main.c b/sinqhm/SinqHM_srv_main.c index d62e611a..0ddc8b39 100755 --- a/sinqhm/SinqHM_srv_main.c +++ b/sinqhm/SinqHM_srv_main.c @@ -213,6 +213,9 @@ cnct_skt = socket (AF_INET, SOCK_STREAM, 0); if (cnct_skt == -1) failInet_port ("\nhmRoot%d -- Cnct-Socket socket error", Port_base); + status = 1; + setsockopt(cnct_skt, SOL_SOCKET, SO_REUSEADDR, &status, sizeof(int)); + lcl_sockname.sin_family = AF_INET; lcl_sockname.sin_port = htons (Port_base); lcl_sockname.sin_addr.s_addr = 0; diff --git a/sinqhm/SinqHM_srv_routines.c b/sinqhm/SinqHM_srv_routines.c index 3ffaed88..5643b8b2 100755 --- a/sinqhm/SinqHM_srv_routines.c +++ b/sinqhm/SinqHM_srv_routines.c @@ -2500,11 +2500,19 @@ ** Output the given text and exit the process. */ int my_errno; + static int showMem = 0; + + if(showMem == 0) + { + memShowInit(); + showMem = 1; + } getErrno (&my_errno); printf ("### Internet Error ###\n"); printf (" ### errno = %d.\n", my_errno); perror (text); + memShow(1); exit (EXIT_FAILURE); } /*--------------------------------------------------------------------------*/ diff --git a/sinqhm/SinqHM_srv_server.c b/sinqhm/SinqHM_srv_server.c index 8c056418..46a440be 100755 --- a/sinqhm/SinqHM_srv_server.c +++ b/sinqhm/SinqHM_srv_server.c @@ -148,6 +148,8 @@ is = semGive (Sem_Server); /* Let our parent continue */ exit (KER__BAD_VALUE); } + status = 1; + setsockopt(cnct_skt, SOL_SOCKET, SO_REUSEADDR, &status, sizeof(int)); my_lcl_sockname.sin_family = AF_INET; my_lcl_sockname.sin_port = htons (port); diff --git a/tas.h b/tas.h index 5d729650..f7264c77 100644 --- a/tas.h +++ b/tas.h @@ -91,8 +91,23 @@ #define ARX1 76 #define ARX2 77 -#define MAXPAR 78 +#define INST 78 +#define TIT 79 +#define USR 80 +#define COM 81 +#define ALF1 82 +#define ALF2 83 +#define ALF3 84 +#define ALF4 85 +#define BET1 86 +#define BET2 87 +#define BET3 88 +#define BET4 89 +#define OUT 90 +#define LOC 91 +#define MAXPAR 92 +#define MAXADD 20 /* --------------------- data structure -------------------------------*/ @@ -100,6 +115,12 @@ typedef struct { pObjectDescriptor pDes; pSicsVariable tasPar[MAXPAR]; pCounter counter; + pScanData pScan; + int iPOL; + int addOutput[MAXADD]; + int addType[MAXADD]; + int addCount; + int iFileNO; }TASdata, *pTASdata; diff --git a/tas.w b/tas.w index 5036ecf9..518ce2fa 100644 --- a/tas.w +++ b/tas.w @@ -38,6 +38,12 @@ typedef struct { pObjectDescriptor pDes; pSicsVariable tasPar[MAXPAR]; pCounter counter; + pScanData pScan; + int iPOL; + int addOutput[MAXADD]; + int addType[MAXADD]; + int addCount; + int iFileNO; }TASdata, *pTASdata; @} \begin{description} @@ -45,12 +51,21 @@ typedef struct { object. \item[floatPar] An array of pointers to float parameters. The parameters are indexed through defined constants. -\item[counter] A pointer to the neutron counter. +\item[pScan] A pointer to a SICS scan object. +\item[iPOL] a flag which is non zer when polarisation analysis is +required. +\item[addOutput] TAS scans may have additional output fields besides +the scan variables in the scan data. This array holds the indices of +such variables. +\item[addType] This array holds the type of additional output +variables. This can be 0 for simple variables or 1 for a motor. +\item[addCount] is the number of additional output variables. +\item[iFileNO] is the number of the current data file. \end{description} The constants for the parameters are defined in the header file. \subsubsection{Exported Functions} -These are mainly the interpreter inetrface functions: +These are mainly the interpreter interface functions: @d tasfunc @{ int TASFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]); @@ -156,8 +171,23 @@ These are mainly the interpreter inetrface functions: #define ARX1 76 #define ARX2 77 -#define MAXPAR 78 +#define INST 78 +#define TIT 79 +#define USR 80 +#define COM 81 +#define ALF1 82 +#define ALF2 83 +#define ALF3 84 +#define ALF4 85 +#define BET1 86 +#define BET2 87 +#define BET3 88 +#define BET4 89 +#define OUT 90 +#define LOC 91 +#define MAXPAR 92 +#define MAXADD 20 /* --------------------- data structure -------------------------------*/ @ diff --git a/tascom.tcl b/tascom.tcl new file mode 100644 index 00000000..ce50073e --- /dev/null +++ b/tascom.tcl @@ -0,0 +1,289 @@ +#--------------------------------------------------------------------------- +# In order to run a triple axis spectrometer, SICS has to be made to behave +# like the ancinet MAD program from ILL. Some of the MAD commands had to +# be implemented in C (see tas*.c) but others can be implemented in Tcl. +# This file contains the procedures and command definitions for this syntax +# adaption from SICS to MAD. +# +# Mark Koennecke, December 2000 +#-------------------------------------------------------------------------- + + +#------------------------------------------------------------------------- +# Perform initialization, but only on first go + +if { [info exists tasinit] == 0 } { + set tasinit 1 + SicsAlias fileeval do User + Publish ou User + Publish fi User + Publish cl User +} + +#-------------------------------------------------------------------------- +# a list of motors, needed at various stages in this + +set tasmot { a1 a2 a3 a4 a5 a6 mcv sro ach mtl mtu stl stu atu mgl sgl \ + sgu agu agl} + +#------------------------------------------------------------------------- +# some MAD variables can be directly mapped to internal SICS variables +# This mapping is done here through a mapping array + +for {set i 0} {$i < [llength $tasmot]} { incr i } { + set mot [lindex $tasmot $i] + set tasmap(l$mot) [format "%s softlowerlim " $mot] + set tasmap(u$mot) [format "%s softupperlim " $mot] +} + +#------------------------------------------------------------------------ +# quite often we need to split a SICS answer of the form x = y and +# extract the y. This is done here. + +proc tasSplit {text} { + set list [split $text =] + return [lindex $list 1] +} + +#------------------------------------------------------------------------- +# motor zero points are handled differently in SICS and MAD: +# - MAD zero's are of opposite sign to SICS +# - Setting a MAD zero point also changes the limits. +# This function takes care of these issues. + +proc madZero args { + set length [llength $args] + if { $length < 1} { + error "ERROR: expected at least motor name as a parameter to madZero" + } + set mot [lindex $args 0] + if {$length == 1 } { +#inquiry case + set zero [tasSplit [$mot softzero]] + return [expr -$zero] + } else { +# a new value has been given. + set val [lindex $args 1] + set val [expr -$val] + set zero [tasSplit [$mot softzero]] + set low [tasSplit [$mot softlowerlim]] + set high [tasSplit [$mot softupperlim]] + set displacement [expr $val - $zero] + $mot softzero $val + $mot softupperlim [expr $high + $displacement] + $mot softlowerlim [expr $low + $displacement] + } +} + +#-------------------------------------------------------------------------- +# This routine throws an error if a bad value for fx is given + +proc fxi {val} { + if { $val != 1 && $val != 2} { + error "ERROR: Invalid value $val for parameter FX" + } else { + fx $val + } +} + +#------------------------------------------------------------------------- +# Changing the scattering sense implies a change of the corresponding +# motors softzero as well: it is rotated by 180 degree. This is done +# by this function + +proc scatSense {par val} { + switch $par { + ss { + set mot a3 + } + sa { + set mot a5 + } + sm { + set mot a1 + } + default { + error "ERROR: unknown scattering sense $par" + } + if {$val != 1 && $val != -1 } { + error "ERROR: invalid scattering sense $val" + } + set oldzero [madZero $mot] + madZero $mot [expr 180 + $oldzero] + $par $val +} + +#-------------------------------------------------------------------------- +# The output command + +proc ou args { + if {[llength $args] == 0 } { + output "" + }else { + output [join $args] + } +} + +#-------------------------------------------------------------------------- +# typeATokenizer extracts tokens from acpmmand string. Tokens can be +# either variable names or - indicating a series of variables. +# Returns the token value or END if the end of the string text is +# reached. Uses and updates a variable pos which indicates the current +# position in the string. + +proc typeATokenizer {text pos} { + upvar pos p + set l [string length $text] +#------- check for end + if {$p >= $l} { + return END + } +#-------- skip spaces + for {} {$p < $l} {incr p} { + set c [string index $text $p] + if {$c == "-" } { + incr p + return "-" + } + if { $c != " " && $c != "," } { + break + } + } + if {$p >= $l} { + return END + } +#---- extract token + set start $p +#---- proceed to next terminator + for {} {$p < $l} {incr p} { + set c [string index $text $p] + if { $c == " " || $c == "," || $c == "-" } { + break + } + } + set stop [expr $p - 1] + return [string range $text $start $stop] +} + +#--------------------------------------------------------------------------- +# The cl(ear) command for unfixing motors + +proc cl args { + global tasmot + if {llength $args] == 0} { +#------ clear all fixed motors + foreach m $tasmot { + if { [tasSplit [$m fixed]] > 0 } { + clientput [format "%s unfixed" $m] + $m fixed -1 + } + } + } +#------ trying to clear individual fixed motors + set command [join $args] + set command [string tolower $command] + set pos 0 + set token [typeATokenizer $command $pos] + while {[string compare $token END] != 0 } { + set last $token + if {$token == "-" } { + set l [llength $tasmot] +#------ handle a range, first find start + for {set start 0} {$start < $l} {incr start} { + set e [lindex $tasmot $start] + if { [string compare $e $last] == 0} { + incr start + break + } + } + if { $start >= $l} { + error [format "ERROR: %s is no motor" $last] + } +#---------- next token is range stop + set stop [typeATokenizer $command $pos] +#---------- now continue to loop until stop is found, thereby unfixing + for {set i $start} { $i < $l} {incr i} { + set e [lindex $tasmot $i] + set ret [catch {$e fixed -1} msg] + if {$ret != 0} { + error [format "ERROR: %s is no motor" $e] + } else { + clientput [format "$s unfixed" $e] + } + if {[string compare $e $stop] == 0 } { + return + } + } + } +#------ should be a single motor here + set ret [catch {$token fixed -1} msg] + if {$ret != 0} { + error [format "ERROR: %s is no motor" $token] + } else { + clientput [format "$s unfixed" $token] + } +#------- do not forget to proceed + set token [typeATokenizer $command $pos] + } +} + +#------------------------------------------------------------------------ +# fi fix motor command + +proc fi args { + global tasmot + if {llength $args] == 0} { +#------ list all fixed motors + foreach m $tasmot { + if { [tasSplit [$m fixed]] > 0 } { + clientput [format "%s fixed" $m] + } + } + } +#------ parse motors to fix + set command [join $args] + set command [string tolower $command] + set pos 0 + set token [typeATokenizer $command $pos] + while {[string compare $token END] != 0 } { + set last $token + if {$token == "-" } { + set l [llength $tasmot] +#------ handle a range, first find start + for {set start 0} {$start < $l} {incr start} { + set e [lindex $tasmot $start] + if { [string compare $e $last] == 0} { + incr start + break + } + } + if { $start >= $l} { + error [format "ERROR: %s is no motor" $last] + } +#---------- next token is range stop + set stop [typeATokenizer $command $pos] +#---------- now continue to loop until stop is found, thereby fixing + for {set i $start} { $i < $l} {incr i} { + set e [lindex $tasmot $i] + set ret [catch {$e fixed 1} msg] + if {$ret != 0} { + error [format "ERROR: %s is no motor" $e] + } else { + clientput [format "$s fixed" $e] + } + if {[string compare $e $stop] == 0 } { + return + } + } + } +#------ should be a single motor here + set ret [catch {$token fixed 1} msg] + if {$ret != 0} { + error [format "ERROR: %s is no motor" $token] + } else { + clientput [format "$s fixed" $token] + } +#------- do not forget to proceed + set token [typeATokenizer $command $pos] + } +} diff --git a/tasdrive.c b/tasdrive.c index ef9aa343..c7b515e0 100644 --- a/tasdrive.c +++ b/tasdrive.c @@ -21,9 +21,10 @@ #include "sicsvar.h" #include "counter.h" #include "motor.h" +#include "scan.h" +#include "splitter.h" #include "tas.h" #include "tasu.h" -#include "splitter.h" /* a token break function, implemented in stptok.c */ @@ -79,6 +80,13 @@ int TASDrive(SConnection *pCon, SicsInterp *pSics, void *pData, self = (pTASdata)pData; assert(self); + /* + check authorization + */ + if(!SCMatchRights(pCon,usUser)) + return 0; + + /* Initialize */ Arg2Text(argc, argv,pLine,255); strtolower(pLine); @@ -180,7 +188,7 @@ int TASDrive(SConnection *pCon, SicsInterp *pSics, void *pData, { sprintf(pBueffel,"Driving %s to %f", tasMotorOrder[i],newPositions[i]); - SCWrite(pCon,pBueffel,eValue); + SCWrite(pCon,pBueffel,eWarning); status = StartMotor(pServ->pExecutor,pSics,pCon, tasMotorOrder[i],newPositions[i]); if(status == 0) @@ -209,7 +217,7 @@ int TASDrive(SConnection *pCon, SicsInterp *pSics, void *pData, { sprintf(pBueffel,"Driving %s to %f", tasVariableOrder[EI+i], self->tasPar[EI+i]->fVal); - SCWrite(pCon,pBueffel,eValue); + SCWrite(pCon,pBueffel,eWarning); } } /* @@ -221,7 +229,7 @@ int TASDrive(SConnection *pCon, SicsInterp *pSics, void *pData, { sprintf(pBueffel,"Driving %s to %f",tasMotorOrder[i], tasTargets[i]); - SCWrite(pCon,pBueffel,eValue); + SCWrite(pCon,pBueffel,eWarning); } } /* diff --git a/tasinit.c b/tasinit.c index 9f1d5c29..4efb83f9 100644 --- a/tasinit.c +++ b/tasinit.c @@ -21,6 +21,8 @@ #include "sicsvar.h" #include "counter.h" #include "motor.h" +#include "scan.h" +#include "scan.i" #include "tas.h" /* @@ -132,6 +134,20 @@ extern char *tasVariableOrder[] = { "mrx2", "arx1", "arx2", + "instrument", + "title", + "user", + "lastcommand", + "alf1", + "alf2", + "alf3", + "alf4", + "bet1", + "bet2", + "bet3", + "bet4", + "output", + "local", NULL}; /*--------------------------------------------------------------------- There is a special feauture in MAD where the count mode is determined @@ -148,7 +164,8 @@ static int MonitorCallback(int iEvent, void *pEvent, void *pUser) if(iEvent != VALUECHANGE) return 0; - SetCounterMode(self->counter,ePreset); + SetCounterMode(self->pScan->pCounterData,ePreset); + SetCounterPreset(self->pScan->pCounterData,self->tasPar[MN]->fVal); return 1; } @@ -160,7 +177,8 @@ static int TimerCallback(int iEvent, void *pEvent, void *pUser) if(iEvent != VALUECHANGE) return 0; - SetCounterMode(self->counter,eTimer); + SetCounterMode(self->pScan->pCounterData,eTimer); + SetCounterPreset(self->pScan->pCounterData,self->tasPar[TI]->fVal); return 1; } /*----------------------------------------------------------------------- @@ -186,6 +204,13 @@ int TASFactory(SConnection *pCon, SicsInterp *pSics, void *pData, pSicsVariable pVar = NULL; CommandList *pCom = NULL; + /* check arguments*/ + if(argc < 2) + { + SCWrite(pCon,"ERROR: insufficient paarameters to MakeTAS",eError); + return 0; + } + /* create a new data structure */ pNew = (pTASdata)malloc(sizeof(TASdata)); if(!pNew) @@ -203,6 +228,7 @@ int TASFactory(SConnection *pCon, SicsInterp *pSics, void *pData, free(pNew); return 0; } + pNew->iPOL = -1; /* connect to all the variables */ iPtr = 0; iError = 0; @@ -227,15 +253,15 @@ int TASFactory(SConnection *pCon, SicsInterp *pSics, void *pData, return 0; } - /* connect to the counter */ - pCom = FindCommand(pSics,"counter"); + /* connect to the scan object */ + pCom = FindCommand(pSics,argv[1]); if(!pCom) { - SCWrite(pCon,"ERROR: no neutron counter for TAS found",eError); + SCWrite(pCon,"ERROR: no scan routine for TAS found",eError); TASKill(pNew); return 0; } - pNew->counter = pCom->pData; + pNew->pScan = (pScanData)pCom->pData; /* Install the callbacks for TI and MN. Sloppy error checking because @@ -260,7 +286,6 @@ int TASFactory(SConnection *pCon, SicsInterp *pSics, void *pData, TASKill(pNew); return 0; } - /* iError = AddCommand(pSics,"sc",TASScan,NULL,pNew); if(!iError) { @@ -268,6 +293,7 @@ int TASFactory(SConnection *pCon, SicsInterp *pSics, void *pData, TASKill(pNew); return 0; } + /* iError = AddCommand(pSics,"set",TASSet,NULL,pNew); if(!iError) { diff --git a/tasscan.c b/tasscan.c new file mode 100644 index 00000000..7fa5f91a --- /dev/null +++ b/tasscan.c @@ -0,0 +1,1358 @@ +/*-------------------------------------------------------------------------- + This is one implementation file for the TASMAD simulation module for + SICS. The requirement is to make SICS look as much as TASMAD as + possible. This includes: + - TASMAD is variable driven + - Sometimes variables are accessed in storage order. + - A complicated calculation has to be done for getting the instruments + settings right. The appropriate F77 routine from TASMAD will be + reused. + - The scan logic is different. + - Output of ILL-formatted data files is required. + + This file implements the MAD sc command for scanning. The general idea is + that specialized action functions are defined for the scan object and the + main SICS scan loop is used as a driver. + + Mark Koennecke, November-December 2000 +---------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include "fortify.h" +#include "sics.h" +#include "sicsvar.h" +#include "counter.h" +#include "motor.h" +#include "scan.h" +#include "scan.i" +#include "tas.h" +#include "tasu.h" +#include "evcontroller.h" +#include "splitter.h" +#include "status.h" + +/*------------------------------------------------------------------------ + a little local utility for making a line of characters + -------------------------------------------------------------------------*/ +static void charLine(char *pBueffel, char c) +{ + int i; + + for(i = 0; i < 80; i++) + { + pBueffel[i] = c; + } + pBueffel[80] = '\n'; + pBueffel[81] = '\0'; +} +/*------------------------------------------------------------------------*/ +static void strtoupper(char *pText) + { + assert(pText); + + while(*pText != '\0') + { + *pText = toupper(*pText); + pText++; + } + } +/*-----------------------------------------------------------------------*/ +static void strcenter(char *str, char *target, int iLength) +{ + int iPtr, i; + + /* + catch the error if target is to long + */ + if(strlen(str) >= iLength) + { + strncpy(target,str,iLength); + } + + iPtr = (iLength - strlen(str))/2; + for(i = 0; i < iPtr;i++) + { + target[i] = ' '; + } + target[iPtr] = '\0'; + strcat(target,str); + for(i = iPtr + strlen(str); i < iLength - 1; i++) + { + target[i] = ' '; + } + target[iLength-1] = '\0'; +} +/*------------------------------------------------------------------------- + TASHeader writes the header of a TAS data file. The format is an + obscure format from ILL ( not ill but Institute Laue Langevin). No + documentation about this exists except the files themselves. This is long + and tiresome code. +---------------------------------------------------------------------------*/ +static int TASHeader(pScanData self) +{ + pTASdata pTAS = (pTASdata)self->pSpecial; + int i, iCount, status, iFileNO; + char pBueffel[1024], pHeader[1024], pWork[132], pWork2[60], pTen[11], *pcPtr; + time_t iDate; + struct tm *psTime; + pVarEntry pVar = NULL; + void *pPtr = NULL; + pMotor pMot; + float fVal, fVal2; + CommandList *pCom = NULL; + pDummy pDum= NULL; + pIDrivable pDrive = NULL; + pEVControl pTem = NULL; + + assert(self); + assert(pTAS); + assert(self->pCon); + assert(self->pSics); + + /* open data file */ + self->fd = fopen(self->pFile,"w"); + if(!self->fd) + { + SCWrite(self->pCon,"ERROR: cannot write data file",eError); + return 0; + } + + /* + extract the file number from the name for entry into the + datafile + */ + pcPtr = strstr(self->pFile,"."); + pcPtr -= 9; /* four for year, 5 for number */ + for(i = 0; i < 5; i++, pcPtr++) + { + pWork[i] = *pcPtr; + } + pWork[5] = '\0'; + iFileNO = atoi(pWork); + + /* the bizarre R, A, V header */ + charLine(pBueffel,'R'); + fputs(pBueffel,self->fd); + fprintf(self->fd,"%8d%8d%8d\n",iFileNO,1,0); + fputs("ILL TAS data in the new ASCII format follow after the line VV...V\n", + self->fd); + charLine(pBueffel,'A'); + fputs(pBueffel,self->fd); + fprintf(self->fd,"%8d%8d\n",42,0); + + /* + format time to TAS format + */ + iDate = time(NULL); + psTime = localtime(&iDate); + memset(pWork,0,59); + strftime(pWork,59,"%d-%b-%Y %H:%M:%S",psTime); + fprintf(self->fd,"%-10s%-12s%-s\n",pTAS->tasPar[INST]->text, + pTAS->tasPar[USR]->text,pWork); + + charLine(pBueffel,'V'); + fputs(pBueffel,self->fd); + + /* + output a plethora of parameters + */ + fprintf(self->fd,"INSTR: %s\n",pTAS->tasPar[INST]->text); + fprintf(self->fd,"EXPNO: \n"); + fprintf(self->fd,"USER_: %s\n",pTAS->tasPar[USR]->text); + fprintf(self->fd,"LOCAL: %s\n",pTAS->tasPar[LOC]->text); + fprintf(self->fd,"FILE_: %d\n",iFileNO); + fprintf(self->fd,"DATE_: %s\n",pWork); + fprintf(self->fd,"TITLE: %s\n",pTAS->tasPar[TIT]->text); + fprintf(self->fd,"COMND: %s\n",pTAS->tasPar[COM]->text); + fprintf(self->fd, + "POSQE: QH=%8.4f, QK=%8.4f, QL=%8.4f, EN=%8.4f, UN=MEV\n", + pTAS->tasPar[QH]->fVal, + pTAS->tasPar[QK]->fVal, + pTAS->tasPar[QL]->fVal, + pTAS->tasPar[EN]->fVal); + /* + build the steps line + */ + sprintf(pBueffel,"STEPS: "); + for(i = 0; i < self->iScanVar; i++) + { + DynarGet(self->pScanVar,i,&pPtr); + pVar = (pVarEntry)pPtr; + if(pVar) + { + strncpy(pWork2,pVar->Name,59); + strtoupper(pWork2); + sprintf(pWork,"D%s=%8.4f, ",pWork2,pVar->fStep); + strcat(pBueffel,pWork); + } + } + strcat(pBueffel,"\n"); + fputs(pBueffel,self->fd); + + /* + a lot of parameters + */ + fprintf(self->fd,"PARAM: DM=%8.4f, DA=%8.4f, SM=%2d, SS=%2d, SA=%2d\n", + pTAS->tasPar[DM]->fVal, + pTAS->tasPar[DA]->fVal, + pTAS->tasPar[SM]->iVal, + pTAS->tasPar[SS]->iVal, + pTAS->tasPar[SA]->iVal); + fprintf(self->fd,"PARAM: FX=%3f, KFIX=%8.4f\n", + pTAS->tasPar[FX]->fVal, + pTAS->tasPar[KF]->fVal); + fprintf(self->fd,"PARAM: ALF1=%8.4f, ALF2=%8.4f, ALF3=%8.4f, ALF4=%8.4f\n", + pTAS->tasPar[ALF1]->fVal, + pTAS->tasPar[ALF2]->fVal, + pTAS->tasPar[ALF3]->fVal, + pTAS->tasPar[ALF4]->fVal); + fprintf(self->fd,"PARAM: BET1=%8.4f, BET2=%8.4f, BET3=%8.4f, BET4=%8.4f\n", + pTAS->tasPar[BET1]->fVal, + pTAS->tasPar[BET2]->fVal, + pTAS->tasPar[BET3]->fVal, + pTAS->tasPar[BET4]->fVal); + fprintf(self->fd,"PARAM: ETAM=%8.4f, ETAA=%8.4f\n", + pTAS->tasPar[ETAM]->fVal, + pTAS->tasPar[ETAA]->fVal); + fprintf(self->fd,"PARAM: AS=%8.4f, BS=%8.4f, CS=%8.4f\n", + pTAS->tasPar[AS]->fVal, + pTAS->tasPar[BS]->fVal, + pTAS->tasPar[CS]->fVal); + fprintf(self->fd,"PARAM: AA=%8.4f, BB=%8.4f, CC=%8.4f\n", + pTAS->tasPar[AA]->fVal, + pTAS->tasPar[BB]->fVal, + pTAS->tasPar[CC]->fVal); + fprintf(self->fd,"PARAM: AX=%8.4f, AY=%8.4f, AZ=%8.4f\n", + pTAS->tasPar[AX]->fVal, + pTAS->tasPar[AY]->fVal, + pTAS->tasPar[AZ]->fVal); + fprintf(self->fd,"PARAM: BX=%8.4f, BY=%8.4f, BZ=%8.4f\n", + pTAS->tasPar[BX]->fVal, + pTAS->tasPar[BY]->fVal, + pTAS->tasPar[BZ]->fVal); + + /* + write motors + */ + fprintf(self->fd,"VARIA: "); + iCount = 0; + for(i = 0; i < MAXMOT;i++) + { + pMot = FindMotor(self->pSics, tasMotorOrder[i]); + if(pMot) + { + status = MotorGetSoftPosition(pMot,self->pCon,&fVal); + if(!status) + { + fVal = -9999.77; + } + if(iCount == 3) + { + iCount = 0; + fprintf(self->fd,"\nVARIA: "); + } + strcpy(pWork2,tasMotorOrder[i]); + strtoupper(pWork2); + fprintf(self->fd,"%-8s=%8.4f, ",pWork2,fVal); + iCount++; + } + else + { + sprintf(pBueffel,"WARNING: motor %s NOT found, %s", + tasMotorOrder[i], + " possible data file corruption"); + SCWrite(self->pCon,pBueffel,eWarning); + } + } + fprintf(self->fd,"\n"); + + /* + write zeros + */ + fprintf(self->fd,"ZEROS: "); + iCount = 0; + for(i = 0; i < MAXMOT;i++) + { + pMot = FindMotor(self->pSics, tasMotorOrder[i]); + if(pMot) + { + status = MotorGetPar(pMot,"softzero",&fVal); + if(!status) + { + fVal = -9999.77; + } + fVal *= -1; + if(iCount == 3) + { + iCount = 0; + fprintf(self->fd,"\nZEROS: "); + } + strcpy(pWork2,tasMotorOrder[i]); + strtoupper(pWork2); + fprintf(self->fd,"%-8s=%8.4f, ",pWork2,fVal); + iCount++; + } + else + { + sprintf(pBueffel,"WARNING: motor %s NOT found, %s", + tasMotorOrder[i], + " possible data file corruption"); + SCWrite(self->pCon,pBueffel,eWarning); + } + } + fprintf(self->fd,"\n"); + + /* + write counter parameters + */ + fVal = GetCounterPreset(self->pCounterData); + if(GetCounterMode(self->pCounterData) == eTimer) + { + fprintf(self->fd,"PARAM: TI=%8.4f\n",fVal); + } + else + { + fprintf(self->fd,"PARAM: MN=%8f\n",fVal); + } + + /* + write temperature data + */ + pCom = FindCommand(self->pSics,"temperature"); + if(pCom) + { + pDum = (pDummy)pCom->pData; + pDrive = pDum->pDescriptor->GetInterface(pDum,DRIVEID); + if(pDrive) /* a proper environment device */ + { + fVal = pDrive->GetValue(pDum,self->pCon); + pTem = (pEVControl)pCom->pData; + EVCGetPar(pTem,"target",&fVal2); + fprintf(self->fd,"PARAM: TT=%8.4f, RT=%8.4f\n",fVal, fVal2); + } + } + + /* + build both the format and the data header line, + start with the scan variables + */ + strcpy(pBueffel,"FORMT: (I4,1X,"); + strcpy(pHeader," PNT"); + for(i = 0; i < self->iScanVar; i++) + { + DynarGet(self->pScanVar,i,&pPtr); + pVar = (pVarEntry)pPtr; + if(pVar) + { + strcat(pBueffel,"F9.4,1X,"); + strncpy(pWork2,pVar->Name,59); + strtoupper(pWork2); + strcenter(pWork2,pTen,10); + strcat(pHeader,pTen); + } + } + /* + put the standard counter things + */ + strcat(pBueffel,"F8.0,1X,F8.0,1X,F9.2,1X,F8.0,1X,F8.0,1X,"); + strcat(pHeader," M1 M2 TIME CNTS M3 "); + /* + now the additional variables + */ + for(i = 0; i < pTAS->addCount; i++) + { + strcat(pBueffel,"F9.4,1X,"); + if(pTAS->addType[i] == 1) /* motor */ + { + strcpy(pWork2,tasMotorOrder[pTAS->addOutput[i]]); + } + else + { + strcpy(pWork2,tasVariableOrder[pTAS->addOutput[i]]); + } + strtoupper(pWork2); + strcenter(pWork2,pTen,11); + strcat(pHeader,pTen); + } + strcat(pBueffel,")"); + + /* + write the final bit + */ + fprintf(self->fd,"%s\nDATA_:\n%s\n",pBueffel,pHeader); + + /* + write header to screen as well + */ + SCWrite(self->pCon,pHeader,eWarning); + + /* + close the file, we will reopen later with append for the data + */ + fclose(self->fd); + self->fd = NULL; + return 1; +} +/*-------------------------------------------------------------------------- + TASScanPoint writes the data at each ScanPoint +---------------------------------------------------------------------------*/ +static int TASScanPoint(pScanData self, int iPoint) +{ + pTASdata pTAS = (pTASdata)self->pSpecial; + pVarEntry pVar = NULL; + void *pPtr = NULL; + int i, status, iPtr; + float fVal; + pMotor pMot = NULL; + long m1, m2, m3, cnts; + char pBueffel[1024], pWork[80]; + + /* + reopen file for appending + */ + self->fd = fopen(self->pFile,"a"); + if(!self->fd) + { + SCWrite(self->pCon,"ERROR: cannot append to data file",eError); + return 0; + } + + /* + write point number + */ + if(pTAS->iPOL > 0) + { + sprintf(pBueffel,"%3d.%1d",iPoint,pTAS->iPOL); + } + else + { + sprintf(pBueffel,"%4d ", iPoint); + } + + /* + write the scan variables + */ + for(i = 0; i < self->iScanVar; i++) + { + DynarGet(self->pScanVar,i,&pPtr); + pVar = (pVarEntry)pPtr; + if(pVar) + { + if(isTASMotor(pVar->Name) >= 0) + { + pMot = FindMotor(self->pSics,pVar->Name); + if(pMot) + { + status = MotorGetSoftPosition(pMot,self->pCon,&fVal); + if(!status) + { + fVal = -9999.77; + } + } + } + else if((iPtr = isTASVar(pVar->Name)) >= 0 ) + { + fVal = pTAS->tasPar[iPtr]->fVal; + } + } + sprintf(pWork,"%8.4f ", fVal); + strcat(pBueffel,pWork); + } + + /* + write monitors and counters + */ + m1 = GetMonitor(self->pCounterData,1,self->pCon); + m2 = GetMonitor(self->pCounterData,2,self->pCon); + m1 = GetMonitor(self->pCounterData,3,self->pCon); + cnts = GetCounts(self->pCounterData,self->pCon); + fVal = GetCountTime(self->pCounterData, self->pCon); + sprintf(pWork,"%8d %8d %9.4f %8d %8d ",m1,m2,fVal, cnts, m3); + strcat(pBueffel,pWork); + + /* + write additional parameters + */ + for(i = 0; i < pTAS->addCount; i++) + { + if(pTAS->addType[i] == 1) /* motor */ + { + pMot = FindMotor(self->pSics,tasMotorOrder[pTAS->addOutput[i]]); + if(pMot) + { + status = MotorGetSoftPosition(pMot,self->pCon,&fVal); + if(!status) + fVal = -9999.77; + } + } + else + { + fVal = pTAS->tasPar[pTAS->addOutput[i]]->fVal; + } + sprintf(pWork,"%9.4f ", fVal); + strcat(pBueffel,pWork); + } + + /* + write both to file and onto screen + */ + fprintf(self->fd,"%s\n",pBueffel); + SCWrite(self->pCon,pBueffel,eWarning); + + /* + close the file + */ + fclose(self->fd); + self->fd = NULL; + return 1; + +} +/*------------------------------------------------------------------------ + TASScanDrive starts all the motors necessary to drive to a new scan + position. It thereby takes care of the TAS calculation if necessary. + -------------------------------------------------------------------------*/ +static int TASScanDrive(pScanData self, int iPoint) +{ + pTASdata pTAS = (pTASdata)self->pSpecial; + pVarEntry pVar = NULL; + void *pPtr = NULL; + int i, status, iPtr; + int iTAS = 0; + pMotor pMot; + unsigned char tasTargetMask[20], tasMask[10]; + float tasTargets[20]; + + /* + initialize masks to 0 + */ + for(i = 0; i < 10; i++) + { + tasMask[i] = 0; + tasTargetMask[i] = 0; + tasTargetMask[i+10] = 0; + tasTargets[i] = .0; + tasTargets[i+10] = .0; + } + + + /* + loop through all the scan variables + */ + for(i = 0; i < self->iScanVar; i++) + { + DynarGet(self->pScanVar,i,&pPtr); + pVar = (pVarEntry)pPtr; + if(pVar) + { + /* set variable if QE-variable */ + if((iPtr = isTASEnergy(pVar->Name)) >= 0) + { + iTAS = 1; + pTAS->tasPar[EI+iPtr]->fVal = + pVar->fStart + iPoint * pVar->fStep; + tasMask[iPtr] = 1; + } + else + { + /* here there is a motor */ + StartMotor(pServ->pExecutor,self->pSics, self->pCon, pVar->Name, + pVar->fStart + iPoint * pVar->fStep); + /* + Ignore errors. TAS scans continue when a motor runs into + a limit. + */ + } + } + } + + /* + now check if we need a TAS calculation: if so do it and start + the motors + */ + if(iTAS) + { + status = TASCalc(pTAS,self->pCon,tasMask, + tasTargets, tasTargetMask); + if(!status) + return; + TASStart(pTAS,self->pCon, + self->pSics,tasTargets,tasTargetMask); + /* + again ignore errors, the scan shall continue if an error was + found + */ + } + + /* + now wait for our motors to arrive, thereby ignoring any error + returns. + */ + status = Wait4Success(GetExecutor()); + + return 1; +} +/*----------------------------------------------------------------------- + RunPolScan does a polarized scan + ------------------------------------------------------------------------*/ +static int RunPolScan(pScanData self, int iPoint) +{ + SCWrite(self->pCon,"ERROR: polarized scans not yet implemented",eError); + return 0; +} +/*--------------------------------------------------------------------------- + TASScanCount starts the counter for a TAS scan or runs the polarization + analysis. +---------------------------------------------------------------------------*/ +static int TASScanCount(pScanData self, int iPoint) +{ + pTASdata pTAS = (pTASdata)self->pSpecial; + float fVal; + int status, iRet; + Status eOld; + + /* + call the polarisation scan function if necessary + */ + if(pTAS->iPOL >= 0) + { + return RunPolScan(self, iPoint); + } + + /* + this is easy, just an ordinary scan, start a counter + */ + fVal = GetCounterPreset(self->pCounterData); + eOld = GetStatus(); + status = DoCount(self->pCounterData,fVal,self->pCon,0); + iRet = Wait4Success(GetExecutor()); + if(iRet == DEVINT) + { + SCWrite(self->pCon,"Counting aborted due to Interrupt",eStatus); + status = 0; + } + else if(iRet == DEVERROR) + { + SCWrite(self->pCon,"Counting finished with Problems",eStatus); + status = 0; + } + else + { + status = 1; + } + SetStatus(eOld); + + return status; +} +/*-------------------------------------------------------------------------- + TAS stores the scan data. This is necessary in order to support things + like peak or center which require the scan data for operation + --------------------------------------------------------------------------*/ + static int TASCollect(pScanData self, int iPoint) + { + pVarEntry pVar = NULL; + void *pDings; + int i, iRet, status, iPtr; + float fVal; + CountEntry sCount; + char *pAns = NULL, *pPtr = NULL ; + pTASdata pTAS = (pTASdata)self->pSpecial; + pMotor pMot; + + 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) + { + if( (iPtr = isTASEnergy(pVar->Name)) >= 0) + { + fVal = pTAS->tasPar[EI+iPtr]->fVal; + } + else + { + pMot = FindMotor(self->pSics,pVar->Name); + if(pMot) + { + MotorGetSoftPosition(pMot,self->pCon,&fVal); + } + } + pVar->fData[iPoint] = fVal; + } + } + + /* store counter data */ + /* monitors */ + for(i = 1; i < 10; i++) + { + sCount.Monitors[i-1] = GetMonitor((pCounter)self->pCounterData,i, + self->pCon); + } + if( self->iChannel != 0 && self->iChannel != -10 ) + { + sCount.Monitors[self->iChannel - 1] = + GetCounts((pCounter)self->pCounterData, + self->pCon); + } + + /* counts, depending on iChannel */ + if(self->iChannel == 0) + { + sCount.lCount = GetCounts((pCounter)self->pCounterData,self->pCon); + } + else + { + sCount.lCount = GetMonitor((pCounter)self->pCounterData, + self->iChannel, self->pCon); + } + + /* get time */ + sCount.fTime = GetCountTime((pCounter)self->pCounterData, + self->pCon); + /* stow away */ + DynarReplace(self->pCounts,self->iCounts,&sCount,sizeof(CountEntry)); + self->iCounts++; + return 1; + } +/*---------------------------------------------------------------------- + SetTASScan sets the special TAS scan functions in the scan data + structure + ------------------------------------------------------------------------*/ +static void SetTASScan(pScanData self, pTASdata pTAS) +{ + self->PrepareScan = NonCheckPrepare; + self->WriteHeader = TASHeader; + self->WriteScanPoints = TASScanPoint; + self->ScanDrive = TASScanDrive; + self->ScanCount = TASScanCount; + self->CollectScanData = TASCollect; + self->pSpecial = pTAS; +} +/*------------------------------------------------------------------------- + AddTASScanVar is the same as the standard AddScanVar but without the + error checking for a drivable parameter + --------------------------------------------------------------------------*/ +static int AddTASScanVar(pScanData self, SicsInterp *pSics, SConnection *pCon, + char *name, float fStart, float fStep) + { + CommandList *pCom = NULL; + pIDrivable pDriv = NULL; + pDummy pData = NULL; + VarEntry pVar; + char pBueffel[512]; + + if(self->iActive) + { + SCWrite(pCon, + "ERROR: cannot change parameters while scan is running",eError); + return 0; + } + + /* find the thing */ + pCom = FindCommand(pSics,name); + if(!pCom) + { + sprintf(pBueffel,"ERROR: Cannot find variable %s to scan",name); + SCWrite(pCon,pBueffel,eError); + return 0; + } + pData = (pDummy)pCom->pData; + if(!pData) + { + sprintf(pBueffel,"ERROR: Cannot find data for variable %s",name); + SCWrite(pCon,pBueffel,eError); + return 0; + } + + /* got everything, fill in the VarEntry structure */ + strcpy(pVar.Name,name); + pVar.pInter = NULL; + pVar.pObject = pData; + pVar.fStart = fStart; + pVar.fStep = fStep; + pVar.fData = NULL; + + /* put it away */ + DynarPutCopy(self->pScanVar,self->iScanVar,&pVar,sizeof(VarEntry)); + self->iScanVar++; + + return 1; + } +/*----------------------------------------------------------------------- + The TAS scan command line contains two types of items: Scan variables + and their center values and normal SICS variables such as the monitor + to use and the steps in each scan variable. As this is decidely easier + this command line is parsed in two pathes: In the first pass all the + variables are set and removed. In the second pass the scan variables + are parsed and entered into the scan data structure. + + ParseVar implements the first pass. + -------------------------------------------------------------------------*/ +#define NONE 0 +#define NUM 1 +#define TXT 2 +extern char *stptok(const char *s, char *tok, size_t toklen, char *brk); + + +static int ParseVar(pTASdata pTAS, char *pBueffel, SConnection *pCon) +{ + char *myBuffer = NULL, pToken[20], *pPtr, pError[132]; + int iPtr, lastToken, lastVar; + VarType vt; + + /* + set up our own buffer + */ + myBuffer = (char *)malloc((strlen(pBueffel)+10) * sizeof(char)); + if(!myBuffer) + { + SCWrite(pCon,"ERROR: out of memory in TASSCan",eError); + return 0; + } + memset(myBuffer,0,10+strlen(pBueffel)); + + /* + parse loop + */ + lastToken = NONE; + lastVar = -1; + pPtr = stptok(pBueffel,pToken,20," ,="); /* step over sc */ + while(pPtr != NULL) + { + pPtr = stptok(pPtr,pToken,20," ,="); + if(strlen(pToken) < 1 || pPtr == NULL) + continue; + switch(lastToken) + { + case NONE: + if(tasNumeric(pToken)) + { + sprintf(pError, + "ERROR: parse error at %s, expected variable", + pToken); + SCWrite(pCon,pError,eError); + return 0; + } + lastToken = TXT; + if( (iPtr = isTASVar(pToken)) >= 0 ) + { + if(isTASEnergy(pToken) >= 0) + { + /* energy variables are scan variables */ + strcpy(myBuffer,pToken); + strcat(myBuffer," "); + } + else + { + lastVar = iPtr; + } + } + else + { + /* this is the motor case */ + strcpy(myBuffer,pToken); + strcat(myBuffer," "); + } + break; + case TXT: + if(tasNumeric(pToken)) + { + lastToken = NUM; + if(lastVar >= 0) + { + vt = GetVarType(pTAS->tasPar[lastVar]); + if(vt == veFloat) + { + VarSetFloat(pTAS->tasPar[lastVar],atof(pToken), + usInternal); + } + else if(vt == veInt) + { + VarSetInt(pTAS->tasPar[lastVar], + (int)atof(pToken), usInternal); + } + else + { + pTAS->tasPar[lastVar]->text = strdup(pToken); + } + lastVar++; + } + else + { + strcat(myBuffer,pToken); + strcat(myBuffer," "); + } + } + else + { + sprintf(pError,"ERROR: parse error at %s, expected number", + pToken); + SCWrite(pCon,pError,eError); + return 0; + } + break; + case NUM: + if(tasNumeric(pToken)) + { + lastToken = NUM; + if(lastVar >= 0) + { + vt = GetVarType(pTAS->tasPar[lastVar]); + if(vt == veFloat) + { + VarSetFloat(pTAS->tasPar[lastVar],atof(pToken), + usInternal); + } + else if(vt == veInt) + { + VarSetInt(pTAS->tasPar[lastVar], + (int)atof(pToken),usInternal); + } + else + { + pTAS->tasPar[lastVar]->text = strdup(pToken); + } + lastVar++; + } + else + { + strcat(myBuffer,pToken); + strcat(myBuffer," "); + } + } + else + { + lastVar = -1; + if( (iPtr = isTASVar(pToken)) >= 0 ) + { + if(isTASEnergy(pToken) >= 0 ) + { + /* energy variables are scan variables */ + strcat(myBuffer,pToken); + strcat(myBuffer," "); + } + else + { + lastVar = iPtr; + } + } + else + { + /* this is the motor case */ + strcat(myBuffer,pToken); + strcat(myBuffer," "); + } + } + break; + } + } + strcpy(pBueffel, myBuffer); + free(myBuffer); + return 1; +} +/*------------------------------------------------------------------- +EnterScanVar adds the scan variable given to the scan. Thereby it +caluclate sthe start of the scan from the center given and NP. To this +and other purposes it locates the scan variable increment. +-----------------------------------------------------------------------*/ + +static int EnterScanVar(pTASdata pTAS, char *name, float fCenter, + SConnection *pCon) +{ + int iPtr; + char pIncrement[30], pError[132]; + float fIncrement, fStart; + + /* + get increment + */ + strcpy(pIncrement,"d"); + strcat(pIncrement,name); + iPtr = isTASVar(pIncrement); + if(iPtr < 0) + { + sprintf(pError,"ERROR: internal error, increment %s not found", + pIncrement); + SCWrite(pCon,pError,eError); + return 0; + } + fIncrement = pTAS->tasPar[iPtr]->fVal; + + /* + calculate start + */ + fStart = fCenter - (pTAS->pScan->iNP/2) * fIncrement; + + /* + put it in + */ + return AddTASScanVar(pTAS->pScan,pTAS->pScan->pSics, pCon, + name, fStart, fIncrement); +} +/*---------------------------------------------------------------------- + ParseScanVars parses the scan variables and enters them into the + scan. Thereby it takes care of the odd MAD syntax and off the fact that + the values given to sc are the center of the scan whereas we need the + start of the scan. Also ParseScanVars locates the increments for the + various variables which are represented as SICS variables. They are + just the variable name prepended with a "d". + ------------------------------------------------------------------------*/ +static int ParseScanVar(pTASdata pTAS, char *pBueffel, SConnection *pCon, + int *iTas) +{ + char pToken[20], *pPtr, pError[132]; + int iPtr, lastToken, lastVar, lastMotor, status; + VarType vt; + + /* + parse loop + */ + lastToken = NONE; + lastVar = lastMotor = -1; + pPtr = pBueffel; + while(pPtr != NULL) + { + pPtr = stptok(pPtr,pToken,20," ,="); + if(strlen(pToken) < 1 || pPtr == NULL) + continue; + switch(lastToken) + { + case NONE: + if(tasNumeric(pToken)) + { + sprintf(pError, + "ERROR: parse error at %s, expected variable", + pToken); + SCWrite(pCon,pError,eError); + return 0; + } + lastToken = TXT; + if( (iPtr = isTASEnergy(pToken)) >= 0) + { + /* QE - variables are scan variables */ + lastVar = iPtr; + (*iTas)++; + } + else if( (iPtr = isTASMotor(pToken)) >= 0) + { + /* as are motors */ + lastMotor = iPtr; + } + else + { + sprintf(pError,"ERROR: cannot scan %s",pToken); + SCWrite(pCon,pError,eError); + return 0; + } + break; + case TXT: + if(tasNumeric(pToken)) + { + lastToken = NUM; + if(lastVar >= 0) + { + /* + add energy variable + */ + status = EnterScanVar(pTAS,tasVariableOrder[EI+lastVar], + atof(pToken),pCon); + pTAS->tasPar[EI+lastVar]->fVal = atof(pToken); + if(!status) + return status; + lastVar++; + } + else if(lastMotor >= 0) + { + /* + add motor + */ + status = EnterScanVar(pTAS,tasMotorOrder[lastMotor], + atof(pToken),pCon); + if(!status) + return status; + lastMotor++; + } + else + { + /* internal error */ + assert(0); + } + } + else + { + sprintf(pError,"ERROR: parse error at %s, expected number", + pToken); + SCWrite(pCon,pError,eError); + return 0; + } + break; + case NUM: + if(tasNumeric(pToken)) + { + lastToken = NUM; + if(lastVar >= 0) + { + /* + add energy variable + */ + status = EnterScanVar(pTAS,tasVariableOrder[EI+lastVar], + atof(pToken),pCon); + pTAS->tasPar[EI+lastVar]->fVal = atof(pToken); + if(!status) + return status; + lastVar++; + } + else if(lastMotor >= 0) + { + /* + add motor + */ + status = EnterScanVar(pTAS,tasMotorOrder[lastMotor], + atof(pToken),pCon); + if(!status) + return status; + lastMotor++; + } + else + { + /* internal error */ + assert(0); + } + } + else + { + lastVar = lastMotor = -1; + if( (iPtr = isTASEnergy(pToken)) >= 0) + { + /* QE - variables are scan variables */ + lastVar = iPtr; + (*iTas)++; + } + else if( (iPtr = isTASMotor(pToken)) >= 0) + { + /* as are motors */ + lastMotor = iPtr; + } + else + { + sprintf(pError,"ERROR: cannot scan %s",pToken); + SCWrite(pCon,pError,eError); + return 0; + } + } + break; + } + } + return 1; +} +/*----------------------------------------------------------------------- + During a TAS scan additional output variables can be printed. These are + defined in a text variable called ouput. ParseOutput now parses this + variable and enters the variables found in there into the TAS data + structure so that they can be printed during the scan. + ------------------------------------------------------------------------*/ +static void ParseOutput(pTASdata pTAS, SConnection *pCon) +{ + char *pText = NULL, *pPtr, pToken[20], pWarn[256]; + int iPtr; + + /* + get a copy of output + */ + pText = (char *)malloc((strlen(pTAS->tasPar[OUT]->text)+10)*sizeof(char)); + if(!pText) + { + SCWrite(pCon,"WARNING: out of memory while parsing output variable", + eWarning); + return; + } + strcpy(pText,pTAS->tasPar[OUT]->text); + + /* + wash it + */ + prepare2Parse(pText); + + /* + parse + */ + pTAS->addCount = 0; + pPtr = pText; + while(pPtr != NULL) + { + pPtr = stptok(pPtr,pToken,20," ,="); + if(strlen(pToken) < 1 || pPtr == NULL) + continue; + + if((iPtr = isTASMotor(pToken)) >= 0) + { + pTAS->addOutput[pTAS->addCount] = iPtr; + pTAS->addType[pTAS->addCount] = 1; + pTAS->addCount++; + } + else if((iPtr = isTASVar(pToken)) >= 0) + { + pTAS->addOutput[pTAS->addCount] = iPtr; + pTAS->addType[pTAS->addCount] = 0; + pTAS->addCount++; + } + else + { + sprintf(pWarn,"WARNING: ignored invalid token > %s < in output", + pToken); + SCWrite(pCon,pWarn,eWarning); + } + } + free(pText); +} +/*-------------------------------------------------------------------------- + Now, after so many lines of code we are really ready to boogey: Parse + the scan command line, set variables, set the scan up and then actually + perform the scan. + --------------------------------------------------------------------------*/ +int TASScan(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]) +{ + pTASdata pTAS = (pTASdata)pData; + char pLine[1024], pToken[20], *pPtr, pWork[70]; + int i, status, iPtr, iTas; + time_t iDate; + struct tm *psTime; + + /* + check authorization + */ + if(!SCMatchRights(pCon,usUser)) + return 0; + + /* Initialize parsing*/ + Arg2Text(argc, argv,pLine,1023); + strtolower(pLine); + + /* + set command text for data file + */ + VarSetText(pTAS->tasPar[COM],pLine, usInternal); + + + /* + first pass: parse simple variables + */ + status = ParseVar(pTAS,pLine,pCon); + if(!status) + return status; + + /* + clear out old scan + */ + ClearScanVar(pTAS->pScan); + + /* + at this stage all simple variables have been set. Now we get the values + of some important inital values which we need for entering the scan + variables. + */ + pTAS->pScan->iNP = pTAS->tasPar[NP]->iVal; + pTAS->pScan->iMode = GetCounterMode(pTAS->pScan->pCounterData); + pTAS->pScan->fPreset = GetCounterPreset(pTAS->pScan->pCounterData); + pTAS->pScan->pCon = pCon; + pTAS->pScan->pSics = pSics; + + /* + now parse the scan variables + */ + iTas = 0; + status = ParseScanVar(pTAS,pLine,pCon, &iTas); + if(!status) + return status; + + /* + parse the output variable in order to get additional stuff to write + */ + ParseOutput(pTAS,pCon); + + /* + print some status information for the looser + */ + iDate = time(NULL); + psTime = localtime(&iDate); + memset(pWork,0,69); + strftime(pWork,69,"%d-%b-%Y %H:%M:%S",psTime); + sprintf(pLine,"%8s %3d Points Scan %3d Scanned Variable(s) %s", + pTAS->tasPar[INST]->text, + pTAS->pScan->iNP, pTAS->pScan->iScanVar, + pWork); + SCWrite(pCon,pLine,eWarning); + if(GetCounterMode(pTAS->pScan->pCounterData) == eTimer) + { + sprintf(pLine," %8f Seconds per point", + GetCounterPreset(pTAS->pScan->pCounterData)); + } + else + { + sprintf(pLine," %8f Monitor Counts per point", + GetCounterPreset(pTAS->pScan->pCounterData)); + + } + SCWrite(pCon,pLine,eWarning); + SCWrite(pCon," ",eWarning); + SCWrite(pCon," ",eWarning); + sprintf(pLine, + " %12s %6s HKLE: %6.2f%6.2f%6.2f%9.4f%7.3f%7.3f%7.3f", + pTAS->tasPar[TIT]->text, + pTAS->tasPar[USR]->text, + pTAS->tasPar[QH]->fVal - (pTAS->pScan->iNP/2)*pTAS->tasPar[DQH]->fVal, + pTAS->tasPar[QL]->fVal - (pTAS->pScan->iNP/2)*pTAS->tasPar[DQL]->fVal, + pTAS->tasPar[QK]->fVal - (pTAS->pScan->iNP/2)*pTAS->tasPar[DQK]->fVal, + pTAS->tasPar[EN]->fVal - (pTAS->pScan->iNP/2)*pTAS->tasPar[DEN]->fVal, + pTAS->tasPar[DQH]->fVal, + pTAS->tasPar[DQL]->fVal, + pTAS->tasPar[DQK]->fVal, + pTAS->tasPar[DEN]->fVal); + SCWrite(pCon,pLine,eWarning); + if(iTas > 0) + { + if(pTAS->tasPar[FX]->iVal == 1) + { + sprintf(pLine," Constant KI Scan: KI= %7.4f Angs-1; EI= %9.4f", + pTAS->tasPar[KI]->fVal, + pTAS->tasPar[EI]->fVal); + } + else + { + sprintf(pLine," Constant KF Scan: KF= %7.4f Angs-1; EF= %9.4f", + pTAS->tasPar[KF]->fVal, + pTAS->tasPar[EF]->fVal); + } + SCWrite(pCon,pLine,eWarning); + } + + /* + set our scan functions + */ + SetTASScan(pTAS->pScan, pTAS); + + + /* + finally scan + */ + status = DoScan(pTAS->pScan, + pTAS->pScan->iNP, + pTAS->pScan->iMode, + pTAS->pScan->fPreset, + pSics, + pCon); + + /* + cleanup a little + */ + ResetScanFunctions(pTAS->pScan); + + return status; +} diff --git a/tasutil.c b/tasutil.c index e712cb1c..74825a3d 100644 --- a/tasutil.c +++ b/tasutil.c @@ -23,6 +23,7 @@ #include "sicsvar.h" #include "counter.h" #include "motor.h" +#include "scan.h" #include "tas.h" #include "tasu.h" @@ -86,10 +87,6 @@ isTASEnergy(char *val) { return iPtr-EMIN; } - else - { - iPtr++; - } } return -1; } @@ -304,6 +301,17 @@ int TASCalc(pTASdata self, SConnection *pCon, ism = (integer)self->tasPar[SM]->iVal; isa = (integer)self->tasPar[SA]->iVal; + /* + initialize the helmholts currents. This needs work when + polarisation anlaysis is really supported. + */ + for(i = 0; i < 4; i++) + { + helmconv[i] = .0; + currents[i] = .0; + currents[i+4] = .0; + } + /* initalise the motorMasks to 0. */ @@ -449,7 +457,7 @@ int TASStart(pTASdata self, SConnection *pCon, SicsInterp *pSics, return 0; } } - if(motorMask[9]) + if(motorMask[8]) { status = StartMotor(pServ->pExecutor,pSics,pCon, "ACH", motorTargets[8]);