- Added triple axis scan command.
- Introduced simulation mode to simdriv and simcter, i.e they never fail and finish at once. - Started defining MAD compatibility commands in Tcl - Fixed a bug in FOCUS_src which caused it to leak sockets. - Introduced setsockopt SO_REUSEADDR to all new sockets in sinqhm in order to loose the next sinqhm error.
This commit is contained in:
2
Makefile
2
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
|
||||
|
2
danu.dat
2
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
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
10
nxdict.c
10
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! */
|
||||
|
64
sicsstat.tcl
64
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
|
||||
|
32
simcter.c
32
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;
|
||||
|
28
simdriv.c
28
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;
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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 ..
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
@ -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);
|
||||
|
23
tas.h
23
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;
|
||||
|
||||
|
||||
|
36
tas.w
36
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 -------------------------------*/
|
||||
@<tasdata@>
|
||||
|
289
tascom.tcl
Normal file
289
tascom.tcl
Normal file
@ -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]
|
||||
}
|
||||
}
|
16
tasdrive.c
16
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);
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
40
tasinit.c
40
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)
|
||||
{
|
||||
|
18
tasutil.c
18
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]);
|
||||
|
Reference in New Issue
Block a user