- GPIB/ECB modules completed, ecb motor driver in progress
This commit is contained in:
46
Makefile
46
Makefile
@ -14,6 +14,14 @@
|
|||||||
FORTIFYOBJ =
|
FORTIFYOBJ =
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#==========================================================================
|
||||||
|
# assign if the National Instrument GPIB driver is available
|
||||||
|
NI= -DHAVENI
|
||||||
|
NIOBJ= nigpib.o
|
||||||
|
NILIB=-lgpibenet
|
||||||
|
#NI=
|
||||||
|
#NIOBJ=
|
||||||
|
#NILIB=
|
||||||
|
|
||||||
#----- comment or uncomment if a difrac version is required
|
#----- comment or uncomment if a difrac version is required
|
||||||
# Do not forget to remove or add comments to ofac.c as well if changes
|
# Do not forget to remove or add comments to ofac.c as well if changes
|
||||||
@ -50,7 +58,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
|||||||
tasdrive.o tasscan.o synchronize.o definealias.o swmotor.o t_update.o \
|
tasdrive.o tasscan.o synchronize.o definealias.o swmotor.o t_update.o \
|
||||||
hmcontrol.o userscan.o slsmagnet.o rs232controller.o lomax.o \
|
hmcontrol.o userscan.o slsmagnet.o rs232controller.o lomax.o \
|
||||||
polterwrite.o fourlib.o motreg.o motreglist.o anticollider.o \
|
polterwrite.o fourlib.o motreg.o motreglist.o anticollider.o \
|
||||||
s_rnge.o sig_die.o
|
s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) ecb.o ecbdriv.o
|
||||||
|
|
||||||
MOTOROBJ = motor.o el734driv.o simdriv.o el734dc.o pipiezo.o pimotor.o
|
MOTOROBJ = motor.o el734driv.o simdriv.o el734dc.o pipiezo.o pimotor.o
|
||||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||||
@ -63,18 +71,18 @@ VELOOBJ = velo.o velosim.o velodorn.o velodornier.o
|
|||||||
#----- comment or uncomment the following according to operating system
|
#----- comment or uncomment the following according to operating system
|
||||||
|
|
||||||
#------------- for Digital Unix
|
#------------- for Digital Unix
|
||||||
BINTARGET = bin
|
#BINTARGET = bin
|
||||||
HDFROOT=/data/lnslib
|
#HDFROOT=/data/lnslib
|
||||||
CC=cc
|
#CC=cc
|
||||||
EXTRA=
|
#EXTRA=
|
||||||
CFLAGS = -I$(HDFROOT)/include -Ihardsup -DHDF4 -DHDF5 -I. -std1 \
|
#CFLAGS = -I$(HDFROOT)/include -Ihardsup -DHDF4 -DHDF5 -I. -std1 \
|
||||||
-g -warnprotos -c
|
# -g -warnprotos -c
|
||||||
#CFLAGS = -I$(HDFROOT)/include -DFORTIFY -DHDF4 -DHDF5 -Ihardsup -g \
|
#CFLAGS = -I$(HDFROOT)/include -DFORTIFY -DHDF4 -DHDF5 -Ihardsup -g \
|
||||||
# -std1 -warnprotos -c
|
# -std1 -warnprotos -c
|
||||||
LIBS = -L$(HDFROOT)/lib -Lhardsup -lhlib -Lmatrix -lmatrix -Ltecs \
|
#LIBS = -L$(HDFROOT)/lib -Lhardsup -lhlib -Lmatrix -lmatrix -Ltecs \
|
||||||
-ltecsl -ltcl8.0 -lfor $(HDFROOT)/lib/libhdf5.a \
|
# -ltecsl -ltcl8.0 -lfor $(HDFROOT)/lib/libhdf5.a \
|
||||||
$(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \
|
# $(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \
|
||||||
$(HDFROOT)/lib/libjpeg.a -lz -lm -ll -lc
|
# $(HDFROOT)/lib/libjpeg.a -lz -lm -ll -lc
|
||||||
|
|
||||||
#------- for cygnus
|
#------- for cygnus
|
||||||
#HDFROOT=../HDF411
|
#HDFROOT=../HDF411
|
||||||
@ -85,16 +93,16 @@ LIBS = -L$(HDFROOT)/lib -Lhardsup -lhlib -Lmatrix -lmatrix -Ltecs \
|
|||||||
# -lmfhdf -ldf -ljpeg -lz -lm
|
# -lmfhdf -ldf -ljpeg -lz -lm
|
||||||
|
|
||||||
#---------- for linux
|
#---------- for linux
|
||||||
#BINTARGET=../bin
|
BINTARGET=../../bin
|
||||||
#HDFROOT=/usr/local
|
HDFROOT=$(SINQDIR)/linux
|
||||||
#CC=gcc
|
CC=gcc
|
||||||
#CFLAGS = -I$(HDFROOT)/include -DHDF4 -Ihardsup -fwritable-strings \
|
CFLAGS = -I$(HDFROOT)/include -DHDF4 -DHDF5 $(NI) -Ihardsup \
|
||||||
# -DCYGNUS -DNONINTF -g -c
|
-fwritable-strings -DCYGNUS -DNONINTF -g -c
|
||||||
#CFLAGS = -I$(HDFROOT)/include -Ihardsup -fwritable-strings -DFORTIFY \
|
#CFLAGS = -I$(HDFROOT)/include -Ihardsup -fwritable-strings -DFORTIFY \
|
||||||
# -DCYGNUS -DNONINTF -g -c
|
# -DCYGNUS -DNONINTF -g -c
|
||||||
#LIBS= -L$(HDFROOT)/lib -Lhardsup -Ltecs -ltecsl -Lmatrix -lmatrix -lhlib \
|
LIBS= -L$(HDFROOT)/lib -Lhardsup -Ltecs -ltecsl -Lmatrix -lmatrix -lhlib \
|
||||||
# -ltcl8.0 -lmfhdf -ldf -ljpeg -lz -lm -lg2c -ldl
|
$(NILIB) -ltcl -lhdf5 -lmfhdf -ldf -ljpeg -lz -lm -lg2c -ldl
|
||||||
#EXTRA=nintf.o
|
EXTRA=nintf.o
|
||||||
#---------------------------------
|
#---------------------------------
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
|
@ -69,6 +69,7 @@ typedef enum {
|
|||||||
#define HWNoBeam 8
|
#define HWNoBeam 8
|
||||||
#define HWPause 9
|
#define HWPause 9
|
||||||
#define HWWarn 10
|
#define HWWarn 10
|
||||||
|
#define HWRedo 11
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Sics uses some server options for some server configuration parameters.
|
Sics uses some server options for some server configuration parameters.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*----------------------------------------------------------------------
|
/*----------------------------------------------------------------------
|
||||||
This is the implementation file for the AntiCollider, a complex movements
|
This is the implementation file for the AntiCollider, a complex movements
|
||||||
control module for SICS. See anticoliider.tex for more information.
|
control module for SICS. See anticollider.tex for more information.
|
||||||
|
|
||||||
copyright: see file copyright
|
copyright: see file copyright
|
||||||
|
|
||||||
@ -18,7 +18,7 @@
|
|||||||
/*---------------------------------------------------------------------
|
/*---------------------------------------------------------------------
|
||||||
As there should be only one AntiCollider in a system, I use a static
|
As there should be only one AntiCollider in a system, I use a static
|
||||||
pointer to the AntiCollider here in order to facilitate access.
|
pointer to the AntiCollider here in order to facilitate access.
|
||||||
Otherwise more complex mechanisms must be divised in order to pass this
|
Otherwise more complex mechanisms must be devised in order to pass this
|
||||||
pointer into ColliderSetValue and ColliderCheckStatus
|
pointer into ColliderSetValue and ColliderCheckStatus
|
||||||
----------------------------------------------------------------------*/
|
----------------------------------------------------------------------*/
|
||||||
static pAntiCollider myCollider = NULL;
|
static pAntiCollider myCollider = NULL;
|
||||||
|
413
ecb.c
Normal file
413
ecb.c
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
/*-----------------------------------------------------------------------
|
||||||
|
The ECB is a rack controller from Risoe based on a Z80 processor.
|
||||||
|
This module provides some functions for communicating with such a
|
||||||
|
device. This is the implementation file.
|
||||||
|
|
||||||
|
WARNING: This contains code which may be endian dependent!
|
||||||
|
|
||||||
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, January 2002, with some bits taken from the original
|
||||||
|
tascom code.
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <tcl.h>
|
||||||
|
#include "fortify.h"
|
||||||
|
#include "sics.h"
|
||||||
|
#include "ecb.h"
|
||||||
|
#include "ecb.i"
|
||||||
|
/*------------- private defines and error codes ------------------------*/
|
||||||
|
#define ACKN ('\6') /* Acknowledge character */
|
||||||
|
#define READ_BYTES 3
|
||||||
|
#define WRITE_BYTES 4
|
||||||
|
#define ECB_BYTES 65536L
|
||||||
|
|
||||||
|
typedef union /* Used to swap bytes in 'address' and 'byte_count' */
|
||||||
|
{
|
||||||
|
unsigned short word;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned char msb; /* Most significant byte */
|
||||||
|
unsigned char lsb; /* Least significant byte */
|
||||||
|
}b;
|
||||||
|
}Swap;
|
||||||
|
/* ------- error codes */
|
||||||
|
#define ECBILLEGALFUNC -100
|
||||||
|
#define ECBOVERFLOW -101
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
static int ecbSendFunc(pECB self, int func){
|
||||||
|
unsigned char function, response;
|
||||||
|
int count, status;
|
||||||
|
|
||||||
|
/*
|
||||||
|
send function code
|
||||||
|
*/
|
||||||
|
function = (unsigned char)func;
|
||||||
|
count = 1;
|
||||||
|
status = GPIBsend(self->gpib,self->ecbDeviceID,&function,count);
|
||||||
|
if(status < 0){
|
||||||
|
self->lastError = status;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
read acknowledge byte
|
||||||
|
*/
|
||||||
|
status = GPIBread(self->gpib,self->ecbDeviceID,&response,count);
|
||||||
|
if(status < 0){
|
||||||
|
self->lastError = status;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(response != ACKN){
|
||||||
|
self->lastError = ECBILLEGALFUNC;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
int ecbExecute(pECB self, int func, Z80_reg in, Z80_reg *out){
|
||||||
|
int count, status;
|
||||||
|
|
||||||
|
assert(self != NULL);
|
||||||
|
assert(self->gpib != NULL);
|
||||||
|
self->lastError = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
send function code
|
||||||
|
*/
|
||||||
|
status = ecbSendFunc(self,func);
|
||||||
|
if(status <= 0){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
send input register
|
||||||
|
*/
|
||||||
|
count = 4;
|
||||||
|
status = GPIBsend(self->gpib,self->ecbDeviceID, &in, count);
|
||||||
|
if(status < 0){
|
||||||
|
self->lastError = status;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
read result register
|
||||||
|
*/
|
||||||
|
status = GPIBread(self->gpib,self->ecbDeviceID, out, count);
|
||||||
|
if(status < 0){
|
||||||
|
self->lastError = status;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
static int ecbPrepareIO(pECB self, int func, unsigned short address,
|
||||||
|
unsigned short byteCount){
|
||||||
|
Swap save, adr, count;
|
||||||
|
int status, bytes;
|
||||||
|
|
||||||
|
if(byteCount > ECB_BYTES){
|
||||||
|
self->lastError = ECBOVERFLOW;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Swap address and byteCount?? This may be a portability issue!
|
||||||
|
This may not be necessary on some platforms
|
||||||
|
*/
|
||||||
|
save.word = address; /* Swap address bytes */
|
||||||
|
adr.b.lsb = save.b.msb;
|
||||||
|
adr.b.msb = save.b.lsb;
|
||||||
|
save.word = byteCount; /* Swap byte count bytes */
|
||||||
|
count.b.lsb = save.b.msb;
|
||||||
|
count.b.msb = save.b.lsb;
|
||||||
|
|
||||||
|
status = ecbSendFunc(self,func);
|
||||||
|
if(status <= 0){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
send address
|
||||||
|
*/
|
||||||
|
bytes = 2;
|
||||||
|
status = GPIBsend(self->gpib,self->ecbDeviceID,&adr,bytes);
|
||||||
|
if(status < 0){
|
||||||
|
self->lastError = status;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
send byte count
|
||||||
|
*/
|
||||||
|
status = GPIBsend(self->gpib,self->ecbDeviceID,&count,bytes);
|
||||||
|
if(status < 0){
|
||||||
|
self->lastError = status;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
int ecbRead(pECB self, unsigned short address,
|
||||||
|
void *buffer, int byteCount){
|
||||||
|
|
||||||
|
int status, count;
|
||||||
|
|
||||||
|
assert(self != NULL);
|
||||||
|
assert(self->gpib != NULL);
|
||||||
|
self->lastError = 0;
|
||||||
|
|
||||||
|
status = ecbPrepareIO(self,READ_BYTES,address,(unsigned short)byteCount);
|
||||||
|
if(status <= 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
actual read
|
||||||
|
*/
|
||||||
|
status = GPIBread(self->gpib,self->ecbDeviceID, buffer, byteCount);
|
||||||
|
if(status < 0){
|
||||||
|
self->lastError = status;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
int ecbWrite(pECB self, unsigned short address,
|
||||||
|
void *buffer, int byteCount){
|
||||||
|
|
||||||
|
int status, count;
|
||||||
|
|
||||||
|
assert(self != NULL);
|
||||||
|
assert(self->gpib != NULL);
|
||||||
|
self->lastError = 0;
|
||||||
|
|
||||||
|
status = ecbPrepareIO(self,WRITE_BYTES,address,(unsigned short)byteCount);
|
||||||
|
if(status <= 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
actual read
|
||||||
|
*/
|
||||||
|
status = GPIBsend(self->gpib,self->ecbDeviceID, buffer, byteCount);
|
||||||
|
if(status < 0){
|
||||||
|
self->lastError = status;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void ecbErrorDescription(pECB self, char *buffer, int maxBuffer){
|
||||||
|
int positive;
|
||||||
|
|
||||||
|
switch(self->lastError){
|
||||||
|
case ECBILLEGALFUNC:
|
||||||
|
strncpy(buffer,"Illegal ECB function called",maxBuffer);
|
||||||
|
return;
|
||||||
|
case ECBOVERFLOW:
|
||||||
|
strncpy(buffer,
|
||||||
|
"You tried to copy more then 64K onto the poor ECB, REFUSED!",
|
||||||
|
maxBuffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
GPIB error codes
|
||||||
|
*/
|
||||||
|
GPIBerrorDescription(self->gpib,self->lastError,buffer, maxBuffer);
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
void ecbClear(pECB self){
|
||||||
|
GPIBclear(self->gpib, self->ecbDeviceID);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
int fixECBError(pECB self){
|
||||||
|
int pos;
|
||||||
|
|
||||||
|
switch(self->lastError){
|
||||||
|
case ECBILLEGALFUNC:
|
||||||
|
case ECBOVERFLOW:
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
GPIB error
|
||||||
|
*/
|
||||||
|
pos = -self->lastError;
|
||||||
|
switch(pos){
|
||||||
|
case GPIBEABO:
|
||||||
|
return HWRedo;
|
||||||
|
default:
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
int ECBAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]){
|
||||||
|
pECB self = (pECB)pData;
|
||||||
|
Z80_reg in, out;
|
||||||
|
char pBuffer[80], pError[132];
|
||||||
|
int status, iVal, func;
|
||||||
|
|
||||||
|
assert(self != NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Only managers will be allowed to wrestle directly with ECB
|
||||||
|
controllers.
|
||||||
|
*/
|
||||||
|
if(!SCMatchRights(pCon,usMugger)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argc < 2){
|
||||||
|
SCWrite(pCon,"ERROR: keyword required for ECB",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
strtolower(argv[1]);
|
||||||
|
if(strcmp(argv[1],"func") == 0){
|
||||||
|
if(argc < 7){
|
||||||
|
SCWrite(pCon,"ERROR: require function code and four register values",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
status = Tcl_GetInt(pSics->pTcl, argv[2],&func);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
SCWrite(pCon,"ERROR: failed to convert argument to int",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
status = Tcl_GetInt(pSics->pTcl, argv[3],&iVal);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
SCWrite(pCon,"ERROR: failed to convert argument to int",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
in.d = (unsigned char)iVal;
|
||||||
|
status = Tcl_GetInt(pSics->pTcl, argv[4],&iVal);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
SCWrite(pCon,"ERROR: failed to convert argument to int",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
in.e = (unsigned char)iVal;
|
||||||
|
status = Tcl_GetInt(pSics->pTcl, argv[5],&iVal);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
SCWrite(pCon,"ERROR: failed to convert argument to int",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
in.b = (unsigned char)iVal;
|
||||||
|
status = Tcl_GetInt(pSics->pTcl, argv[6],&iVal);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
SCWrite(pCon,"ERROR: failed to convert argument to int",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
in.c = (unsigned char)iVal;
|
||||||
|
|
||||||
|
status = ecbExecute(self,func,in,&out);
|
||||||
|
if(status != 1){
|
||||||
|
ecbErrorDescription(self,pBuffer,79);
|
||||||
|
sprintf(pError,"ERROR: %s", pBuffer);
|
||||||
|
SCWrite(pCon,pError,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
sprintf(pBuffer,"%x %x %x %x",
|
||||||
|
out.d, out.e, out.c, out.c);
|
||||||
|
SCWrite(pCon,pBuffer,eValue);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
SCWrite(pCon,"ERROR: ECB does not understand keyword", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
void ECBKill(void *pData){
|
||||||
|
pECB self = (pECB)pData;
|
||||||
|
|
||||||
|
if(self == NULL){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Detaching here may be dangerous: If the GPIB has been deleted first,
|
||||||
|
this makes a core dump. Best is the GPIB keeps a list of attached
|
||||||
|
things and cleans them itself.
|
||||||
|
|
||||||
|
GPIBdetach(self->gpib,self->ecbDeviceID);
|
||||||
|
*/
|
||||||
|
if(self->pDes){
|
||||||
|
DeleteDescriptor(self->pDes);
|
||||||
|
}
|
||||||
|
free(self);
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
int MakeECB(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]){
|
||||||
|
pECB self = NULL;
|
||||||
|
int address, status, boardNo;
|
||||||
|
pGPIB gpib = NULL;
|
||||||
|
char pError[132];
|
||||||
|
|
||||||
|
/*
|
||||||
|
we need a name, the GPIB controller and an address on the GPIB bus for
|
||||||
|
the ECB as arguments
|
||||||
|
*/
|
||||||
|
if(argc < 5){
|
||||||
|
SCWrite(pCon,"ERROR: insufficient arguments to MakeECB",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
gpib = FindCommandData(pSics,argv[2],"GPIB");
|
||||||
|
if(gpib == NULL){
|
||||||
|
sprintf(pError,"ERROR: no GPIB controller %s found", argv[2]);
|
||||||
|
SCWrite(pCon,pError,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
status = Tcl_GetInt(pSics->pTcl,argv[3], &boardNo);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
sprintf(pError,"ERROR: failed to convert %s to integer",argv[3]);
|
||||||
|
SCWrite(pCon,pError,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
status = Tcl_GetInt(pSics->pTcl,argv[4], &address);
|
||||||
|
if(status != TCL_OK){
|
||||||
|
sprintf(pError,"ERROR: failed to convert %s to integer",argv[4]);
|
||||||
|
SCWrite(pCon,pError,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(address < 0 || address > 30){
|
||||||
|
SCWrite(pCon,"ERROR: invalid GPIB address specified",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
self = (pECB)malloc(sizeof(ECB));
|
||||||
|
if(self == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: no memory to allocate ECB",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memset(self,0,sizeof(ECB));
|
||||||
|
self->pDes = CreateDescriptor("ECB");
|
||||||
|
if(self->pDes == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: no memory to allocate ECB",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
self->gpib = gpib;
|
||||||
|
self->boardNumber = boardNo;
|
||||||
|
self->ecbAddress = address;
|
||||||
|
self->ecbDeviceID =GPIBattach(self->gpib,self->boardNumber,
|
||||||
|
self->ecbAddress,0,
|
||||||
|
13,0,1);
|
||||||
|
if(self->ecbDeviceID <= 0){
|
||||||
|
SCWrite(pCon,"ERROR: failed to initialize ECB connection",
|
||||||
|
eError);
|
||||||
|
ECBKill(self);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
AddCommand(pSics,argv[1],ECBAction,ECBKill,self);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
61
ecb.h
Normal file
61
ecb.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
/*-----------------------------------------------------------------------
|
||||||
|
The ECB is a rack controller from Risoe based on a Z80 processor.
|
||||||
|
This module provides some functions for communicating with such a
|
||||||
|
device.
|
||||||
|
|
||||||
|
WARNING: This contains code which may be endian dependent!
|
||||||
|
|
||||||
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, January 2002, with some bits taken out of the
|
||||||
|
original tascom code.
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
#ifndef ECBCON
|
||||||
|
#define ECBCON
|
||||||
|
#include "gpibcontroller.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char d; /* D register in Z80 */
|
||||||
|
unsigned char e; /* E register in Z80 */
|
||||||
|
unsigned char b; /* B register in Z80 */
|
||||||
|
unsigned char c; /* C register in Z80 */
|
||||||
|
} Z80_reg;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
typedef struct __ECB *pECB;
|
||||||
|
|
||||||
|
int ecbExecute(pECB self, int func, Z80_reg in, Z80_reg *out);
|
||||||
|
int ecbRead(pECB self, unsigned short address,
|
||||||
|
void *buffer, int byteCount);
|
||||||
|
int ecbWrite(pECB self, unsigned short address,
|
||||||
|
void *buffer, int byteCount);
|
||||||
|
void ecbClear(pECB self);
|
||||||
|
int fixECBError(pECB self);
|
||||||
|
void ecbErrorDescription(pECB self, char *buffer, int maxBytes);
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int MakeECB(SConnection *pCon, SicsInterp *pSics,
|
||||||
|
void *pData,
|
||||||
|
int ragc, char *argv[]);
|
||||||
|
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
for byte packing. result must be an 32 bit integer
|
||||||
|
----------------------------------------------------------------------*/
|
||||||
|
typedef union /* Used to extract and load data to Z80 regs. */{
|
||||||
|
unsigned int result;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned char byt0; /* Least significant byte */
|
||||||
|
unsigned char byt1;
|
||||||
|
unsigned char byt2;
|
||||||
|
unsigned char byt3; /* Most significant byte */
|
||||||
|
}b;
|
||||||
|
}Ecb_pack;
|
||||||
|
|
||||||
|
#endif
|
149
ecb.w
Normal file
149
ecb.w
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
\subsection{The ECB Controller}
|
||||||
|
The ECB Controller is an electronic device created by the Risoe
|
||||||
|
neutron scattering institute. At its base is a Z80 8-bit
|
||||||
|
processor. This Z80 processor can perform certain functions such as
|
||||||
|
controlling count operations, running a motor etc. To this purpose
|
||||||
|
further electronic widgets are connected to the Z80's backplane. At
|
||||||
|
the other end is a GPIB controller which allows to discuss with the
|
||||||
|
Z80.
|
||||||
|
|
||||||
|
This module now implements three basic functionalities of the ECB:
|
||||||
|
\begin{itemize}
|
||||||
|
\item Execute a function
|
||||||
|
\item Read some memory
|
||||||
|
\item Write some memory
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
WARNING: this module contains code which may be endian dependend!
|
||||||
|
|
||||||
|
In order to do this we need the following data structure:
|
||||||
|
@d ecbdat @{
|
||||||
|
struct __ECB {
|
||||||
|
pObjectDescriptor pDes;
|
||||||
|
pGPIB gpib;
|
||||||
|
int boardNumber;
|
||||||
|
int ecbAddress;
|
||||||
|
int ecbDeviceID;
|
||||||
|
int lastError;
|
||||||
|
}ECB;
|
||||||
|
@}
|
||||||
|
The fields:
|
||||||
|
\begin{description}
|
||||||
|
\item[pDes] The standard SICS object descriptor.
|
||||||
|
\item[gpib] The GPIB controller used for accessing the ECB.
|
||||||
|
\item[boardNumber] The GPIB board number in the NI driver.
|
||||||
|
\item[ecbAddress] The GPIB address of the ECB controller.
|
||||||
|
\item[ecbDeviceID] The device ID assigned to the ECB when the ECB has
|
||||||
|
been attached to.
|
||||||
|
\item[lastError] The last error which occurred.
|
||||||
|
\end{description}
|
||||||
|
|
||||||
|
A function in the ECB is executed by sending a function number first,
|
||||||
|
followed by the content of the Z80 4 registers. In order to do this a
|
||||||
|
data structure is required for these registers:
|
||||||
|
|
||||||
|
@d z80 @{
|
||||||
|
typedef struct {
|
||||||
|
unsigned char d; /* D register in Z80 */
|
||||||
|
unsigned char e; /* E register in Z80 */
|
||||||
|
unsigned char b; /* B register in Z80 */
|
||||||
|
unsigned char c; /* C register in Z80 */
|
||||||
|
} Z80_reg;
|
||||||
|
@}
|
||||||
|
|
||||||
|
The function interface then looks like:
|
||||||
|
|
||||||
|
@d ecbfunc @{
|
||||||
|
typedef struct __ECB *pECB;
|
||||||
|
|
||||||
|
int ecbExecute(pECB self, int func, Z80_reg in, Z80_reg *out);
|
||||||
|
int ecbRead(pECB self, unsigned short address,
|
||||||
|
void *buffer, int byteCount);
|
||||||
|
int ecbWrite(pECB self, unsigned short address,
|
||||||
|
void *buffer, int byteCount);
|
||||||
|
void ecbClear(pECB self);
|
||||||
|
int fixECBError(pECB self);
|
||||||
|
void ecbErrorDescription(pECB self, char *buffer, int maxBytes);
|
||||||
|
|
||||||
|
@}
|
||||||
|
\begin{description}
|
||||||
|
\item[ecbExecute] tries to execute the ECB function func. The input register
|
||||||
|
content is in in, on success the outpt registers are stored in out.
|
||||||
|
\item[ecbRead] reads byteCount bytes from the ECB address address into
|
||||||
|
buffer. Please note that address in this contest is an address in the
|
||||||
|
ECB's memory space and not the GPIB address.
|
||||||
|
\item[ecbWrite] writes byteCount bytes from buffer to the ECB address
|
||||||
|
address. Please note that address in this contest is an address in the
|
||||||
|
ECB's memory space and not the GPIB address.
|
||||||
|
\item[ecbClear] tries to clear the ECB interface.
|
||||||
|
\item[fixECBError] tries to fix the last ECB error.
|
||||||
|
\item[ecbErrorDescription] retrieves a text description of the last
|
||||||
|
ECB problem. Max maxBytes of description are copied into buffer.
|
||||||
|
\end{description}
|
||||||
|
|
||||||
|
|
||||||
|
There is also an interface to the SICS interpreter for the ECB. This
|
||||||
|
can be useful for debugging and testing and as a tool for scripting
|
||||||
|
auxiliary equipment controlled through the ECB. The interface to the
|
||||||
|
SICS interpreter for the ECB is represented through the ECB Factory
|
||||||
|
function:
|
||||||
|
@d ecbint @{
|
||||||
|
int MakeECB(SConnection *pCon, SicsInterp *pSics,
|
||||||
|
void *pData,
|
||||||
|
int ragc, char *argv[]);
|
||||||
|
@}
|
||||||
|
|
||||||
|
@o ecb.h @{
|
||||||
|
/*-----------------------------------------------------------------------
|
||||||
|
The ECB is a rack controller from Risoe based on a Z80 processor.
|
||||||
|
This module provides some functions for communicating with such a
|
||||||
|
device.
|
||||||
|
|
||||||
|
WARNING: This contains code which may be endian dependent!
|
||||||
|
|
||||||
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, January 2002, with some bits taken out of the
|
||||||
|
original tascom code.
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
#ifndef ECBCON
|
||||||
|
#define ECBCON
|
||||||
|
#include "gpibcontroller.h"
|
||||||
|
|
||||||
|
@<z80@>
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
@<ecbfunc@>
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
@<ecbint@>
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
for byte packing. result must be an 32 bit integer
|
||||||
|
----------------------------------------------------------------------*/
|
||||||
|
typedef union /* Used to extract and load data to Z80 regs. */{
|
||||||
|
unsigned int result;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned char byt0; /* Least significant byte */
|
||||||
|
unsigned char byt1;
|
||||||
|
unsigned char byt2;
|
||||||
|
unsigned char byt3; /* Most significant byte */
|
||||||
|
}b;
|
||||||
|
}Ecb_pack;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@}
|
||||||
|
|
||||||
|
@o ecb.i @{
|
||||||
|
/*-----------------------------------------------------------------------
|
||||||
|
The ECB is a rack controller from Risoe based on a Z80 processor.
|
||||||
|
This module provides some functions for communicating with such a
|
||||||
|
device. This is an internal data structure definition file.
|
||||||
|
|
||||||
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, January 2002, with some bits taken out of the
|
||||||
|
original tascom code.
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
@<ecbdat@>
|
||||||
|
@}
|
||||||
|
|
695
ecbdriv.c
Normal file
695
ecbdriv.c
Normal file
@ -0,0 +1,695 @@
|
|||||||
|
/*------------------------------------------------------------------------
|
||||||
|
This is a motor driver for the Risoe motor controllers within the
|
||||||
|
ECB system. The motor is controlled through functions invoked in the
|
||||||
|
Z80 processor of the ECB system which is connected through a GPIB
|
||||||
|
bus to the wider world. This driver has to do a lot of extra things:
|
||||||
|
- it has to convert from physical values to motor steps.
|
||||||
|
- Quite a few parameters, such as ramping parameters,
|
||||||
|
have to be downloaded to the ECB
|
||||||
|
- Risoe motors may have a virtual encoder or a real encoder.
|
||||||
|
|
||||||
|
This driver support only P2048a motor controllers, as these are the
|
||||||
|
only ones which seem to have arrived at PSI. The P1648 and Tridynamic
|
||||||
|
things are not supported.
|
||||||
|
|
||||||
|
Multiplexed motors: Originally the ECB supported 24 motors. This did
|
||||||
|
prove to be not enough. Therefore another device called P2234e was
|
||||||
|
introduced which allowed to run 8 motors from one controller port. In this
|
||||||
|
case the motor parameters have to be copied to the ECB before
|
||||||
|
driving the motor. Multiplexing is selected through the parameter MULT.
|
||||||
|
MULT 0 means no multiplexing, MULT > 0 makes MULT the number of the
|
||||||
|
motor in the multiplexer. MULT is now also used to flag a download of
|
||||||
|
parameters to the ECB. In such a case MULT is -1.
|
||||||
|
|
||||||
|
|
||||||
|
Some of this code was taken from the tascom driver for the ECB.
|
||||||
|
|
||||||
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, January 2003
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <tcl.h>
|
||||||
|
#include "fortify.h"
|
||||||
|
#include "sics.h"
|
||||||
|
#include "motor.h"
|
||||||
|
#include "obpar.h"
|
||||||
|
#include "ecb.h"
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------
|
||||||
|
Parameter indexes in ObPar array and meanings
|
||||||
|
-------------------------------------------------------------------------*/
|
||||||
|
#define ENCODER 0 /* encoder number, 0 if no encoder */
|
||||||
|
#define CONTROL 1 /* control signals, > 1 means required. */
|
||||||
|
#define RANGE 2 /* 0 = slow, 1 = fast */
|
||||||
|
#define MULT 3 /* 0 = not multiplexed, > 0 multiplex motor number*/
|
||||||
|
#define MULTCHAN 16 /* multiplexer channel */
|
||||||
|
#define ACCTIME 4 /* acceleration time: 500, 1000 or 2000 milSecs */
|
||||||
|
#define ROTDIR 5 /* rotation direction */
|
||||||
|
#define STARTSPEED 6 /* start speed: 100-500 steps/s */
|
||||||
|
#define MAXSPEED 7 /* maximum speed: 100-2000 steps/sec */
|
||||||
|
#define SLOWAUTO 8 /* slow speed in auto mode */
|
||||||
|
#define SLOWMAN 9 /* slow speed in manual mode */
|
||||||
|
#define DELAY 10 /* start delay 0 - 2500 millSecs */
|
||||||
|
#define OFFSET 11 /* encoder offset */
|
||||||
|
#define TOLERANCE 12 /* tolerance in steps */
|
||||||
|
#define STEPS2DEG 13 /* conversion factor motor steps to Degree */
|
||||||
|
#define DEG2STEP 14 /* conversion factor from degree to encoder digits */
|
||||||
|
#define BACKLASH 15 /* motor backlash */
|
||||||
|
|
||||||
|
#define MAXPAR 18 /* 1 extra for the sentinel, do not forget to initialize! */
|
||||||
|
|
||||||
|
/*------------------------------ ECB defines -------------------------*/
|
||||||
|
#define MAX_ENCODER 40
|
||||||
|
#define FENCOR 167 /* read encoder */
|
||||||
|
#define MOREAD 145 /* read motor steps */
|
||||||
|
#define MOPARA 140 /* motor parameter */
|
||||||
|
#define MOCLOA 146
|
||||||
|
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||||
|
#define MOSTEP 141
|
||||||
|
#define MOSTAT 144
|
||||||
|
|
||||||
|
/********************* t-error codes *************************************/
|
||||||
|
#define COMMERROR -300
|
||||||
|
#define ECBMANUELL -301
|
||||||
|
#define ECBINUSE -302
|
||||||
|
#define UNIDENTIFIED -303
|
||||||
|
#define ECBINHIBIT -304
|
||||||
|
#define ECBRUNNING -305
|
||||||
|
#define ECBSTART -306
|
||||||
|
#define ECBLIMIT -307
|
||||||
|
/*================== The Driver data structure ============================*/
|
||||||
|
typedef struct __ECBMotorDriv {
|
||||||
|
/* general motor driver interface
|
||||||
|
fields. REQUIRED!
|
||||||
|
*/
|
||||||
|
float fUpper; /* upper limit */
|
||||||
|
float fLower; /* lower limit */
|
||||||
|
char *name;
|
||||||
|
int (*GetPosition)(void *self,float *fPos);
|
||||||
|
int (*RunTo)(void *self, float fNewVal);
|
||||||
|
int (*GetStatus)(void *self);
|
||||||
|
void (*GetError)(void *self, int *iCode,
|
||||||
|
char *buffer, int iBufLen);
|
||||||
|
int (*TryAndFixIt)(void *self,int iError,
|
||||||
|
float fNew);
|
||||||
|
int (*Halt)(void *self);
|
||||||
|
int (*GetDriverPar)(void *self, char *name,
|
||||||
|
float *value);
|
||||||
|
int (*SetDriverPar)(void *self,SConnection *pCon,
|
||||||
|
char *name, float newValue);
|
||||||
|
void (*ListDriverPar)(void *self, char *motorName,
|
||||||
|
SConnection *pCon);
|
||||||
|
|
||||||
|
|
||||||
|
/* ECB specific fields */
|
||||||
|
pECB ecb; /* ECB controller for everything */
|
||||||
|
int ecbIndex; /* motor index in ECB */
|
||||||
|
long targetInSteps;
|
||||||
|
int errorCode;
|
||||||
|
ObPar driverPar[MAXPAR];
|
||||||
|
} ECBMOTDriv, *pECBMotDriv;
|
||||||
|
/*=======================================================================
|
||||||
|
Reading the motor position means reading the encoder if such a thing
|
||||||
|
is present or the counted motor steps (Pseudo Encoder) if not.
|
||||||
|
If the ECB answers us, the value has to be converted to physical
|
||||||
|
values.
|
||||||
|
----------------------------------------------------------------------*/
|
||||||
|
static int readEncoder(pECBMotDriv self, long *digits){
|
||||||
|
int status;
|
||||||
|
Z80_reg in, out;
|
||||||
|
Ecb_pack data;
|
||||||
|
|
||||||
|
in.c = (unsigned char)ObVal(self->driverPar,ENCODER) + MAX_ENCODER;
|
||||||
|
status = ecbExecute(self->ecb,FENCOR,in,&out);
|
||||||
|
if(!status){
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pack bytes */
|
||||||
|
data.b.byt3 = 0;
|
||||||
|
data.b.byt2 = out.b;
|
||||||
|
data.b.byt1 = out.b;
|
||||||
|
data.b.byt0 = out.e;
|
||||||
|
if(out.c != 1){
|
||||||
|
*digits = -data.result;
|
||||||
|
} else {
|
||||||
|
*digits = data.result;
|
||||||
|
}
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static int readPseudoEncoder(pECBMotDriv self, long *digits){
|
||||||
|
int status;
|
||||||
|
Z80_reg in, out;
|
||||||
|
Ecb_pack data;
|
||||||
|
|
||||||
|
in.c = (unsigned char)self->ecbIndex;
|
||||||
|
status = ecbExecute(self->ecb,MOREAD,in,&out);
|
||||||
|
if(!status){
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pack bytes */
|
||||||
|
data.b.byt3 = 0;
|
||||||
|
data.b.byt2 = out.b;
|
||||||
|
data.b.byt1 = out.b;
|
||||||
|
data.b.byt0 = out.e;
|
||||||
|
if(out.c != 1){
|
||||||
|
*digits = -data.result;
|
||||||
|
} else {
|
||||||
|
*digits = data.result;
|
||||||
|
}
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
int ECBMOTGetPos(void *pData, float *fPos){
|
||||||
|
pECBMotDriv self = (pECBMotDriv)pData;
|
||||||
|
long digits = 0;
|
||||||
|
int status;
|
||||||
|
double step2degree;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
self->errorCode = 0;
|
||||||
|
|
||||||
|
if((int)ObVal(self->driverPar,ENCODER) > 0){
|
||||||
|
status = readEncoder(self, &digits);
|
||||||
|
} else {
|
||||||
|
status = readPseudoEncoder(self, &digits);
|
||||||
|
}
|
||||||
|
step2degree = ObVal(self->driverPar,STEPS2DEG);
|
||||||
|
if(step2degree == 0.0){
|
||||||
|
step2degree = 1.;
|
||||||
|
}
|
||||||
|
*fPos = (float)( (double)digits/step2degree);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
/*========================================================================
|
||||||
|
In order to start a motor we need to do a couple of steps:
|
||||||
|
- check if the motors parameters have been changed or it is a multiplexed
|
||||||
|
motor. In each case download the motor parameters.
|
||||||
|
- the direction of the motor has to be determined, the speed to be
|
||||||
|
selected etc.
|
||||||
|
- Then the motor can be started.
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
static int mustDownload(pECBMotDriv self){
|
||||||
|
int multi;
|
||||||
|
|
||||||
|
multi = (int)nintf(ObVal(self->driverPar,MULT));
|
||||||
|
if(multi > 0 || multi < 0) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
static int checkMotorResult(pECBMotDriv self, Z80_reg out){
|
||||||
|
/*
|
||||||
|
checks the return values from a motor function invocation
|
||||||
|
and sets error codes in case of problems.
|
||||||
|
*/
|
||||||
|
if(out.c == '\0'){
|
||||||
|
switch(out.b){
|
||||||
|
case 128:
|
||||||
|
self->errorCode = ECBMANUELL;
|
||||||
|
break;
|
||||||
|
case 64:
|
||||||
|
self->errorCode = ECBINHIBIT;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
self->errorCode = ECBRUNNING;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
self->errorCode = ECBSTART;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
self->errorCode = ECBLIMIT;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
self->errorCode = ECBINUSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
self->errorCode = UNIDENTIFIED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static int loadAcceleration(pECBMotDriv self){
|
||||||
|
unsigned char parameter;
|
||||||
|
Z80_reg in, out;
|
||||||
|
int accel, status;
|
||||||
|
|
||||||
|
accel = (int)nintf(ObVal(self->driverPar,ACCTIME));
|
||||||
|
if(accel == 500){
|
||||||
|
parameter = 1;
|
||||||
|
}else if(accel == 1000){
|
||||||
|
parameter = 2;
|
||||||
|
}else if(accel == 2000){
|
||||||
|
parameter = 3;
|
||||||
|
} else {
|
||||||
|
parameter = 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
apply rotation direction mask
|
||||||
|
*/
|
||||||
|
if(ObVal(self->driverPar,ROTDIR) < 0){
|
||||||
|
parameter += 128;
|
||||||
|
}
|
||||||
|
in.c = (unsigned char)self->ecbIndex;
|
||||||
|
in.b = 7;
|
||||||
|
in.e = parameter;
|
||||||
|
status = ecbExecute(self->ecb,MOPARA,in,&out);
|
||||||
|
if(!status){
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!checkMotorResult(self, out)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*--------------------------- speed tables ------------------------------*/
|
||||||
|
#define SPEED_TAB3 64 /* Size of speed table */
|
||||||
|
const unsigned int low_2048[SPEED_TAB3] = {
|
||||||
|
1, 2, 3, 4, 5, 6, 8, 10, 12, 14,
|
||||||
|
16, 20, 24, 28, 32, 36, 40, 44, 48, 56,
|
||||||
|
64, 72, 80, 88, 96,104,112,120,128,136,
|
||||||
|
144,152,160,168,176,184,192,200,208,216,
|
||||||
|
224,236,248,260,272,284,296,308,320,332,
|
||||||
|
344,356,368,380,392,404,416,428,440,452,
|
||||||
|
464,476,488,500 };
|
||||||
|
|
||||||
|
#define SPEED_TAB4 96 /* Size of speed table */
|
||||||
|
const unsigned int high_2048[SPEED_TAB4] = {
|
||||||
|
11, 15, 20, 27, 36, 47, 59, 74,
|
||||||
|
93, 107, 124, 143, 165, 190, 213, 239,
|
||||||
|
268, 298, 331, 368, 405, 446, 491, 536,
|
||||||
|
585, 632, 683, 731, 783, 827, 873, 922,
|
||||||
|
974, 1028, 1085, 1146, 1211, 1278, 1349, 1424,
|
||||||
|
1503, 1587, 1675, 1720, 1820, 1913, 2014, 2123,
|
||||||
|
2237, 2360, 2483, 2620, 2755, 2905, 3058, 3221,
|
||||||
|
3384, 3575, 3756, 3945, 4150, 4370, 4600, 4800,
|
||||||
|
5000, 5250, 5533, 5822, 6120, 6440, 6770, 7090,
|
||||||
|
7450, 7800, 8130, 8500, 8900, 9320, 9730, 10200,
|
||||||
|
10700, 11200, 11700, 12200, 12800, 13300, 13900, 14500,
|
||||||
|
15100, 15800, 16700, 17300, 18000, 18600, 19300, 20000 };
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static unsigned char getSpeedIndex(pECBMotDriv self, int value){
|
||||||
|
unsigned char index;
|
||||||
|
const unsigned int *table;
|
||||||
|
int range, length;
|
||||||
|
|
||||||
|
range = (int)nintf(ObVal(self->driverPar,RANGE));
|
||||||
|
if(range == 0){
|
||||||
|
table = low_2048;
|
||||||
|
length = SPEED_TAB3;
|
||||||
|
} else {
|
||||||
|
table = high_2048;
|
||||||
|
length = SPEED_TAB4;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(index = 0; index < length-1; index++){
|
||||||
|
if(table[index] <= value){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
static int loadSpeed(pECBMotDriv self, float value, int code){
|
||||||
|
unsigned char parameter;
|
||||||
|
Z80_reg in, out;
|
||||||
|
int accel, status;
|
||||||
|
|
||||||
|
parameter = getSpeedIndex(self,value);
|
||||||
|
|
||||||
|
in.c = (unsigned char)self->ecbIndex;
|
||||||
|
in.b = code;
|
||||||
|
in.e = parameter;
|
||||||
|
status = ecbExecute(self->ecb,MOPARA,in,&out);
|
||||||
|
if(!status){
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!checkMotorResult(self, out)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------*/
|
||||||
|
static int loadDelay(pECBMotDriv self){
|
||||||
|
int parameter;
|
||||||
|
Z80_reg in, out;
|
||||||
|
int accel, status;
|
||||||
|
unsigned char control;
|
||||||
|
|
||||||
|
parameter = (int)nintf(ObVal(self->driverPar,DELAY));
|
||||||
|
control = (unsigned char)nintf(ObVal(self->driverPar,CONTROL));
|
||||||
|
if(control & 3){
|
||||||
|
parameter = 5;
|
||||||
|
} else{
|
||||||
|
parameter/= 10;
|
||||||
|
}
|
||||||
|
in.c = (unsigned char)self->ecbIndex;
|
||||||
|
in.b = 8;
|
||||||
|
in.e = parameter;
|
||||||
|
status = ecbExecute(self->ecb,MOPARA,in,&out);
|
||||||
|
if(!status){
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!checkMotorResult(self, out)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static int loadMulti(pECBMotDriv self){
|
||||||
|
unsigned char multi, mult_chan;
|
||||||
|
Z80_reg in, out;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
multi = nintf(ObVal(self->driverPar,MULT));
|
||||||
|
if(multi <= 0){
|
||||||
|
return 1; /* not multiplexed */
|
||||||
|
}
|
||||||
|
|
||||||
|
mult_chan = (unsigned char)nintf(ObVal(self->driverPar,MULTCHAN));
|
||||||
|
in.b = -1; /* SET_PORT */
|
||||||
|
in.d = (unsigned char)(multi + (mult_chan << 4));
|
||||||
|
in.e = self->ecbIndex;
|
||||||
|
status = ecbExecute(self->ecb,MOPARA,in,&out);
|
||||||
|
if(status != 1){
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
static int downloadECBParam(pECBMotDriv self){
|
||||||
|
int status, parameter;
|
||||||
|
unsigned char func_code;
|
||||||
|
Z80_reg in, out;
|
||||||
|
|
||||||
|
/*
|
||||||
|
We assume that all parameters have useful values. It is the task of
|
||||||
|
SetDriverPar to ensure just that!
|
||||||
|
*/
|
||||||
|
if(status = loadAcceleration(self) <= 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(status = loadSpeed(self,ObVal(self->driverPar,STARTSPEED),6) <= 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(status = loadSpeed(self,ObVal(self->driverPar,MAXSPEED),5) <= 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(status = loadSpeed(self,ObVal(self->driverPar,SLOWAUTO),4) <= 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(status = loadSpeed(self,ObVal(self->driverPar,SLOWMAN),10) <= 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(status = loadDelay(self) <= 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(status = loadMulti(self) <= 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
It would be good practice to read the parameters written back
|
||||||
|
in order to check them. This does not seem to be supported with the
|
||||||
|
ECB system though.
|
||||||
|
*/
|
||||||
|
if(ObVal(self->driverPar,MULT) < 0.){
|
||||||
|
self->driverPar[MULT].fVal = .0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
int degree2Step(pECBMotDriv self, float degree)
|
||||||
|
{
|
||||||
|
double steps;
|
||||||
|
|
||||||
|
steps = degree*ObVal(self->driverPar,STEPS2DEG);
|
||||||
|
if (ObVal(self->driverPar,ENCODER) > .0)
|
||||||
|
steps = steps*ObVal(self->driverPar,DEG2STEP);
|
||||||
|
if(degree < 0){
|
||||||
|
steps = - steps;
|
||||||
|
}
|
||||||
|
return ((int) steps);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
static int ECBRunTo(void *pData, float newPosition){
|
||||||
|
pECBMotDriv self = (pECBMotDriv)pData;
|
||||||
|
long digits = 0;
|
||||||
|
int status;
|
||||||
|
float oldValue, diff, steps2degree, backlash;
|
||||||
|
Ecb_pack data;
|
||||||
|
Z80_reg in, out;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
if(mustDownload(self)){
|
||||||
|
status = downloadECBParam(self);
|
||||||
|
if(!status){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
read old position
|
||||||
|
*/
|
||||||
|
status = ECBMOTGetPos(self,&oldValue);
|
||||||
|
if(status != 1){
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
do not start if there
|
||||||
|
*/
|
||||||
|
diff = newPosition - oldValue;
|
||||||
|
steps2degree= ObVal(self->driverPar,STEPS2DEG);
|
||||||
|
if(ABS(diff) <= .5/steps2degree + ObVal(self->driverPar,TOLERANCE)){
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
write control data
|
||||||
|
*/
|
||||||
|
in.d = 0;
|
||||||
|
if(diff > .0){
|
||||||
|
in.d |= 32; /* positive direction */
|
||||||
|
}
|
||||||
|
in.d |= 16; /* interrupts */
|
||||||
|
if(nintf(ObVal(self->driverPar,RANGE)) == 1.){
|
||||||
|
in.d |= 64; /* fast speed */
|
||||||
|
}
|
||||||
|
in.c = (unsigned char)self->ecbIndex;
|
||||||
|
status = ecbExecute(self->ecb,MOCLOA,in,&out);
|
||||||
|
if(status != 1){
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
calculate steps
|
||||||
|
*/
|
||||||
|
backlash = ObVal(self->driverPar,BACKLASH);
|
||||||
|
if(diff < 0){
|
||||||
|
diff = -diff;
|
||||||
|
if(backlash > 0){
|
||||||
|
diff += backlash;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(backlash < 0){
|
||||||
|
diff -= backlash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.result = degree2Step(self,diff);
|
||||||
|
|
||||||
|
/*
|
||||||
|
finally start the motor
|
||||||
|
*/
|
||||||
|
in.b = data.b.byt2;
|
||||||
|
in.d = data.b.byt1;
|
||||||
|
in.e = data.b.byt0;
|
||||||
|
in.c = (unsigned char)self->ecbIndex;
|
||||||
|
status = ecbExecute(self->ecb,MOSTEP,in,&out);
|
||||||
|
if(status != 1){
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!checkMotorResult(self, out)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OKOK;
|
||||||
|
}
|
||||||
|
/*=======================================================================*/
|
||||||
|
static int ECBGetStatus(void *pData){
|
||||||
|
pECBMotDriv self = (pECBMotDriv)pData;
|
||||||
|
Z80_reg in, out;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
in.c = (unsigned char)self->ecbIndex;
|
||||||
|
in.b = 12;
|
||||||
|
status = ecbExecute(self->ecb,MOSTAT,in,&out);
|
||||||
|
if(status != 1){
|
||||||
|
self->errorCode = COMMERROR;
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = checkMotorResult(self,out);
|
||||||
|
if(status == 0){
|
||||||
|
if(self->errorCode == ECBRUNNING){
|
||||||
|
self->errorCode = 0;
|
||||||
|
return HWBusy;
|
||||||
|
} else {
|
||||||
|
return HWFault;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return HWIdle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*======================================================================*/
|
||||||
|
static void ECBGetError(void *pData, int *iCode, char *buffer, int bufferlen){
|
||||||
|
pECBMotDriv self = (pECBMotDriv)pData;
|
||||||
|
char pBueffel[132];
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
*iCode = self->errorCode;
|
||||||
|
switch(self->errorCode){
|
||||||
|
case COMMERROR:
|
||||||
|
strncpy(buffer,"communication problem with ECB",bufferlen);
|
||||||
|
break;
|
||||||
|
case ECBMANUELL:
|
||||||
|
strncpy(buffer,"ECB is in manual mode, trying to switch...",bufferlen);
|
||||||
|
break;
|
||||||
|
case ECBINUSE:
|
||||||
|
strncpy(buffer,"Power supply is in use",bufferlen);
|
||||||
|
break;
|
||||||
|
case ECBINHIBIT:
|
||||||
|
strncpy(buffer,"motor is inhibited",bufferlen);
|
||||||
|
break;
|
||||||
|
case ECBRUNNING:
|
||||||
|
strncpy(buffer,"motor is running",bufferlen);
|
||||||
|
break;
|
||||||
|
case ECBSTART:
|
||||||
|
strncpy(buffer,"failed to start motor",bufferlen);
|
||||||
|
break;
|
||||||
|
case ECBLIMIT:
|
||||||
|
strncpy(buffer,"hit limit switch",bufferlen);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strncpy(buffer,"unidentified error code",bufferlen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*=======================================================================*/
|
||||||
|
static int ECBTryAndFixIt(void *pData, int iCode, float fNew){
|
||||||
|
pECBMotDriv self = (pECBMotDriv)pData;
|
||||||
|
int result;
|
||||||
|
Z80_reg in, out;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
switch(iCode){
|
||||||
|
case ECBMANUELL:
|
||||||
|
in.d =1 ;
|
||||||
|
ecbExecute(self->ecb,162,in,&out);
|
||||||
|
result = MOTREDO;
|
||||||
|
break;
|
||||||
|
case COMMERROR:
|
||||||
|
ecbClear(self->ecb);
|
||||||
|
result = MOTREDO;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = MOTFAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*========================================================================*/
|
||||||
|
static int ECBHalt(void *pData){
|
||||||
|
pECBMotDriv self = (pECBMotDriv)pData;
|
||||||
|
Z80_reg in, out;
|
||||||
|
unsigned char par = 2;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
if(nintf(ObVal(self->driverPar,RANGE)) == 1){
|
||||||
|
par |= 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
in.b = 9;
|
||||||
|
in.e = par;
|
||||||
|
ecbExecute(self->ecb,MOPARA,in,&out);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*=======================================================================*/
|
||||||
|
static int ECBGetDriverPar(void *pData,char *name, float *value){
|
||||||
|
pECBMotDriv self = (pECBMotDriv)pData;
|
||||||
|
ObPar *par = NULL;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
par = ObParFind(self->driverPar,name);
|
||||||
|
if(par != NULL){
|
||||||
|
*value = par->fVal;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*=====================================================================*/
|
||||||
|
static int ECBSetDriverPar(void *pData, SConnection *pCon, char *name,
|
||||||
|
float newValue){
|
||||||
|
pECBMotDriv self = (pECBMotDriv)pData;
|
||||||
|
int parNumber;
|
||||||
|
char pBueffel[256];
|
||||||
|
float correctedValue;
|
||||||
|
|
||||||
|
parNumber = ObParIndex(self->driverPar,name);
|
||||||
|
if(parNumber < 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
only managers shall edit these parameters....
|
||||||
|
*/
|
||||||
|
if(!SCMatchRights(pCon,usMugger)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
return 1;
|
||||||
|
}
|
@ -498,6 +498,7 @@
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
memset(pDriv,0,sizeof(EL734Driv));
|
||||||
|
|
||||||
/* fill in some of the data entered */
|
/* fill in some of the data entered */
|
||||||
pDriv->hostname = strdup(hostname);
|
pDriv->hostname = strdup(hostname);
|
||||||
@ -527,7 +528,6 @@
|
|||||||
pDriv->GetError = GetErr;
|
pDriv->GetError = GetErr;
|
||||||
pDriv->GetStatus = GetStat;
|
pDriv->GetStatus = GetStat;
|
||||||
pDriv->Halt = Halt;
|
pDriv->Halt = Halt;
|
||||||
pDriv->ContinueAfterWarn = MoDrivXXXContinue;
|
|
||||||
pDriv->TryAndFixIt = FixError;
|
pDriv->TryAndFixIt = FixError;
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,11 +65,6 @@
|
|||||||
#define MSROK -47
|
#define MSROK -47
|
||||||
#define MSRREF -48
|
#define MSRREF -48
|
||||||
#define MSRFAULT -49
|
#define MSRFAULT -49
|
||||||
/*------------------------------------------------------------------------*/
|
|
||||||
int MoDrivXXXContinue(void *pData)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* --------------------------------------------------------------------------*/
|
/* --------------------------------------------------------------------------*/
|
||||||
static int GetPos(void *self, float *fData)
|
static int GetPos(void *self, float *fData)
|
||||||
{
|
{
|
||||||
@ -502,6 +497,7 @@
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
memset(pDriv,0,sizeof(EL734Driv));
|
||||||
|
|
||||||
/* fill in some of the data entered */
|
/* fill in some of the data entered */
|
||||||
pDriv->hostname = strdup(hostname);
|
pDriv->hostname = strdup(hostname);
|
||||||
@ -531,7 +527,6 @@
|
|||||||
pDriv->GetError = GetErr;
|
pDriv->GetError = GetErr;
|
||||||
pDriv->GetStatus = GetStat;
|
pDriv->GetStatus = GetStat;
|
||||||
pDriv->Halt = Halt;
|
pDriv->Halt = Halt;
|
||||||
pDriv->ContinueAfterWarn = MoDrivXXXContinue;
|
|
||||||
pDriv->TryAndFixIt = FixError;
|
pDriv->TryAndFixIt = FixError;
|
||||||
|
|
||||||
|
|
||||||
|
@ -188,8 +188,8 @@ void pol2det(psdDescription *psd, double gamma, double nu, int *x, int *y){
|
|||||||
g = psd->distance*(1. + tn*tn +tn*tn*td*td);
|
g = psd->distance*(1. + tn*tn +tn*tn*td*td);
|
||||||
zobs = psd->distance*(atan(tn*e) + asin(f/g));
|
zobs = psd->distance*(atan(tn*e) + asin(f/g));
|
||||||
xobs = td*(psd->distance*cos(zobs/psd->distance));
|
xobs = td*(psd->distance*cos(zobs/psd->distance));
|
||||||
*y = (int)nint(psd->yZero + zobs/psd->yScale);
|
*y = (int)rint(psd->yZero + zobs/psd->yScale);
|
||||||
*x = (int)nint(psd->xZero + xobs/psd->xScale);
|
*x = (int)rint(psd->xZero + xobs/psd->xScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------- bisecting geometry code -----------------------------*/
|
/*--------------- bisecting geometry code -----------------------------*/
|
||||||
|
123
gpib.w
Normal file
123
gpib.w
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
\subsection{GPIB Controller}
|
||||||
|
GPIB (or IEEE-488) is a 8 bit bus system. The system contains a
|
||||||
|
controller and up to 30 devices. GPIB will be used at PSI in the Risoe
|
||||||
|
instruments. And possibly others. The main stay GPIB controller will
|
||||||
|
be the National Instruments ENET-100 GPIB/TCPIP bridge. But several
|
||||||
|
drivers will be needed:
|
||||||
|
\begin{itemize}
|
||||||
|
\item A simulation
|
||||||
|
\item The original NI driver
|
||||||
|
\item Possibly a direct board level NI driver (not for ENET, but PCI)
|
||||||
|
\item Possibly a reverse engineered TCP/IP only driver.
|
||||||
|
\end{itemize}
|
||||||
|
For this reason the controller is made in a polymorphic fashion.
|
||||||
|
|
||||||
|
This requires the following data structure:
|
||||||
|
@d gpibdat @{
|
||||||
|
struct __GPIB {
|
||||||
|
pObjectDescriptor pDes;
|
||||||
|
int (*attach)(int boardNo, int address,
|
||||||
|
int secondaryAddress,
|
||||||
|
int tmo, int eot, int eos);
|
||||||
|
int (*detach)(int devID);
|
||||||
|
int (*send)(int devID, void *buffer,
|
||||||
|
int count);
|
||||||
|
int (*read)(int devID, void *buffer,
|
||||||
|
int count);
|
||||||
|
int (*clear)(int devID);
|
||||||
|
void (*getErrorDescription)(int code,
|
||||||
|
char *buffer, int maxCount);
|
||||||
|
}GPIB;
|
||||||
|
@}
|
||||||
|
|
||||||
|
The interface for this controller:
|
||||||
|
@d gpibint @{
|
||||||
|
typedef struct __GPIB *pGPIB;
|
||||||
|
|
||||||
|
int GPIBattach(pGPIB self, int boardNo,
|
||||||
|
int address, int secondaryAddress,
|
||||||
|
int tmo, int eot, int eos);
|
||||||
|
int GPIBdetach(pGPIB self, int devID);
|
||||||
|
int GPIBsend(pGPIB self, int devID, void *buffer, int bytesToWrite);
|
||||||
|
int GPIBread(pGPIB self, int devID, void *buffer, int bytesToRead);
|
||||||
|
void GPIBclear(pGPIB self, int devID);
|
||||||
|
void GPIBerrorDescription(pGPIB self, int code,
|
||||||
|
char *buffer, int maxBuffer);
|
||||||
|
@}
|
||||||
|
|
||||||
|
All functions return a negative value on failure. All functions takes
|
||||||
|
as their first argument a pointer to a GPIB structure.
|
||||||
|
\begin{description}
|
||||||
|
\item[GPIBattach] initialises the connection to a specific device on
|
||||||
|
the GPIB bus. The parameters:
|
||||||
|
\begin{description}
|
||||||
|
\item[boardNo] The NI board number
|
||||||
|
\item[address] The address of the device on the bus.
|
||||||
|
\item[secondaryAddress] The secondary address of th device.
|
||||||
|
\item[tmo] The timeout for this device.
|
||||||
|
\item[eot] termination thing I do not understand.
|
||||||
|
\item[eos] another termination thing.
|
||||||
|
\end{description}
|
||||||
|
This call retuns an integer devID which has to be used in calls to the
|
||||||
|
other functions.
|
||||||
|
\item[GPIBdetach] closes the connection to the device devID.
|
||||||
|
\item[GPIBsend] sends bytesToWrite bytes from buffer to the device
|
||||||
|
identified through devID.
|
||||||
|
\item[GPIBread] reads bytesToRead bytes from the device
|
||||||
|
identified through devID into buffer. buffer has to be large enough to
|
||||||
|
accomodate bytesToRead bytes.
|
||||||
|
\item[GPIBclear] tries to clear the GPIB device.
|
||||||
|
\item[GPIBerrorDescription] copies at max MaxBuffer bytes or error
|
||||||
|
description for code into buffer.
|
||||||
|
\end{description}
|
||||||
|
|
||||||
|
|
||||||
|
There is also an interpreter interface to the GPIB controller:
|
||||||
|
|
||||||
|
@d gpibsics @{
|
||||||
|
int MakeGPIB(SConnection *pCon, SicsInterp *pSics,
|
||||||
|
void *pData,
|
||||||
|
int argc, char *argv[]);
|
||||||
|
int GPIBAction(SConnection *pCon, SicsInterp *pSics,
|
||||||
|
void *pData,
|
||||||
|
int argc, char *argv[]);
|
||||||
|
|
||||||
|
@}
|
||||||
|
|
||||||
|
@o gpibcontroller.h @{
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
Interface to a GPIB controller.
|
||||||
|
|
||||||
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, January 2003
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
#ifndef GPIBCONTROLLER
|
||||||
|
#define GPIBCONTROLLER
|
||||||
|
|
||||||
|
/*
|
||||||
|
error codes
|
||||||
|
*/
|
||||||
|
#define GPIBARG 4
|
||||||
|
#define GPIBEDVR 0
|
||||||
|
#define GPIBENEB 7
|
||||||
|
#define GPIBEABO 6
|
||||||
|
#define GPIBEADR 3
|
||||||
|
#define GPIBEBUS 14
|
||||||
|
#define GPIBENOL 2
|
||||||
|
|
||||||
|
@<gpibint@>
|
||||||
|
|
||||||
|
@<gpibsics@>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@}
|
||||||
|
|
||||||
|
@o gpibcontroller.i @{
|
||||||
|
/*-----------------------------------------------------------------------
|
||||||
|
GPIBcontroller structure. Automatically generated file, modify in
|
||||||
|
gpib.w and run nuweb.
|
||||||
|
-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
@<gpibdat@>
|
||||||
|
@}
|
257
gpibcontroller.c
Normal file
257
gpibcontroller.c
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
/*----------------------------------------------------------------------
|
||||||
|
Interface to a GPIB controller. This is the implementation file.
|
||||||
|
|
||||||
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, January 2003
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <tcl.h>
|
||||||
|
#include "fortify.h"
|
||||||
|
#include "sics.h"
|
||||||
|
#include "splitter.h"
|
||||||
|
#include "gpibcontroller.h"
|
||||||
|
#include "gpibcontroller.i"
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
int GPIBattach(pGPIB self, int boardNo, int address,
|
||||||
|
int secondaryAddress, int tmo, int eot, int eos){
|
||||||
|
return self->attach(boardNo,address,secondaryAddress,tmo,eot,eos);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
int GPIBdetach(pGPIB self, int devID){
|
||||||
|
return self->detach(devID);
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
int GPIBsend(pGPIB self, int devID, void *buffer, int bytesToWrite){
|
||||||
|
return self->send(devID, buffer,bytesToWrite);
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
int GPIBread(pGPIB self, int devID, void *buffer, int bytesToRead){
|
||||||
|
return self->read(devID, buffer,bytesToRead);
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
void GPIBclear(pGPIB self, int devID){
|
||||||
|
return self->clear(devID);
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
void GPIBerrorDescription(pGPIB self, int code, char *buffer, int maxBuf){
|
||||||
|
return self->getErrorDescription(code, buffer,maxBuf);
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------
|
||||||
|
These are void implementations of the functions for simulation
|
||||||
|
purposes
|
||||||
|
----------------------------------------------------------------------*/
|
||||||
|
static int SIMattach(int boardNo, int address, int secondaryAddress,
|
||||||
|
int tmo, int eoi, int eot){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*----------------------------------------------------------------------*/
|
||||||
|
static int SIMdetach(int devID){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static int SIMsend(int devID, void *buffer, int bytesToWrite){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
static int SIMread(int devID, void *buffer, int bytesToRead){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
static int SIMclear(int devID){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static void SIMerror(int code, char *buffer, int maxBuf){
|
||||||
|
strncpy(buffer,"Unknown simulated error",maxBuf);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
void GPIBKill(void *pData){
|
||||||
|
pGPIB self = NULL;
|
||||||
|
if(pData != NULL){
|
||||||
|
self = (pGPIB)pData;
|
||||||
|
if(self->pDes){
|
||||||
|
DeleteDescriptor(self->pDes);
|
||||||
|
}
|
||||||
|
free(pData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
int GPIBAction(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]){
|
||||||
|
pGPIB self = (pGPIB)pData;
|
||||||
|
int boardID, devID, tmo, count, eoi, eot, address,
|
||||||
|
secondaryAddress, status;
|
||||||
|
char pBuffer[1024];
|
||||||
|
|
||||||
|
assert(self != NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Only managers will be allowed to wrestle directly with GPIB
|
||||||
|
controllers.
|
||||||
|
*/
|
||||||
|
if(!SCMatchRights(pCon,usMugger)){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(argc > 1){
|
||||||
|
strtolower(argv[1]);
|
||||||
|
if(strcmp(argv[1],"attach") == 0){
|
||||||
|
/* the attach command */
|
||||||
|
if(argc < 8){
|
||||||
|
SCWrite(pCon,"ERROR: insufficient number of arguments to attach",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
count = 0;
|
||||||
|
count += Tcl_GetInt(pSics->pTcl,argv[2],&boardID);
|
||||||
|
count += Tcl_GetInt(pSics->pTcl,argv[3],&address);
|
||||||
|
count += Tcl_GetInt(pSics->pTcl,argv[4],&secondaryAddress);
|
||||||
|
count += Tcl_GetInt(pSics->pTcl,argv[5],&tmo);
|
||||||
|
count += Tcl_GetInt(pSics->pTcl,argv[6],&eot);
|
||||||
|
count += Tcl_GetInt(pSics->pTcl,argv[7],&eoi);
|
||||||
|
if(count != 6*TCL_OK){
|
||||||
|
SCWrite(pCon,"ERROR: failed to convert arguments to integer",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
status = GPIBattach(self,boardID, address, secondaryAddress,
|
||||||
|
tmo,eot,eoi);
|
||||||
|
if(status > 0){
|
||||||
|
sprintf(pBuffer,"%d",status);
|
||||||
|
SCWrite(pCon,pBuffer,eValue);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
sprintf(pBuffer,"ERROR: error %d on attach", status);
|
||||||
|
SCWrite(pCon,pBuffer,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if(strcmp(argv[1],"detach") == 0){
|
||||||
|
/*
|
||||||
|
detach command
|
||||||
|
*/
|
||||||
|
if(argc < 2){
|
||||||
|
SCWrite(pCon,"ERROR: insufficient number of arguments to dettach",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(Tcl_GetInt(pSics->pTcl,argv[2],&devID) != TCL_OK){
|
||||||
|
SCWrite(pCon,"ERROR: failed to convert arguments to integer",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
status = GPIBdetach(self,devID);
|
||||||
|
if(status > 0){
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
sprintf(pBuffer,"ERROR: error %d on dettach", status);
|
||||||
|
SCWrite(pCon,pBuffer,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if(strcmp(argv[1],"send") == 0){
|
||||||
|
/*
|
||||||
|
send command
|
||||||
|
*/
|
||||||
|
if(argc < 2){
|
||||||
|
SCWrite(pCon,"ERROR: insufficient number of arguments to send",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(Tcl_GetInt(pSics->pTcl,argv[2],&devID) != TCL_OK){
|
||||||
|
SCWrite(pCon,"ERROR: failed to convert arguments to integer",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Arg2Text(argc-2,argv+2,pBuffer,1023);
|
||||||
|
status = GPIBsend(self,devID,pBuffer, strlen(pBuffer));
|
||||||
|
if(status > 0){
|
||||||
|
SCSendOK(pCon);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
sprintf(pBuffer,"ERROR: error %d on send", status);
|
||||||
|
SCWrite(pCon,pBuffer,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else if(strcmp(argv[1],"read") == 0){
|
||||||
|
/*
|
||||||
|
read command
|
||||||
|
*/
|
||||||
|
if(argc < 2){
|
||||||
|
SCWrite(pCon,"ERROR: insufficient number of arguments to read",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(Tcl_GetInt(pSics->pTcl,argv[2],&devID) != TCL_OK){
|
||||||
|
SCWrite(pCon,"ERROR: failed to convert arguments to integer",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
status = GPIBread(self,devID,pBuffer, 1023);
|
||||||
|
if(status > 0){
|
||||||
|
SCWrite(pCon,pBuffer,eValue);
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
sprintf(pBuffer,"ERROR: error %d on send", status);
|
||||||
|
SCWrite(pCon,pBuffer,eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SCWrite(pCon,"ERROR: command not recognized",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SCWrite(pCon,"ERROR: no command given to GPIB",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
#ifdef HAVENI
|
||||||
|
extern void NIassign(pGPIB self);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int MakeGPIB(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]){
|
||||||
|
pGPIB self = NULL;
|
||||||
|
|
||||||
|
if(argc < 3){
|
||||||
|
SCWrite(pCon,"ERROR: insufficient number of arguments to MakeGPIB",
|
||||||
|
eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
self = (pGPIB)malloc(sizeof(GPIB));
|
||||||
|
if(self == NULL){
|
||||||
|
SCWrite(pCon,"ERROR: cannot allocate memory in MakeGPIB",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
memset(self,0,sizeof(GPIB));
|
||||||
|
|
||||||
|
self->pDes = CreateDescriptor("GPIB");
|
||||||
|
strtolower(argv[2]);
|
||||||
|
if(strcmp(argv[2],"sim") == 0){
|
||||||
|
self->attach = SIMattach;
|
||||||
|
self->detach = SIMdetach;
|
||||||
|
self->send = SIMsend;
|
||||||
|
self->read = SIMread;
|
||||||
|
self->clear = SIMclear;
|
||||||
|
self->getErrorDescription = SIMerror;
|
||||||
|
#ifdef HAVENI
|
||||||
|
} else if(strcmp(argv[2],"ni") == 0){
|
||||||
|
NIassign(self);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
SCWrite(pCon,"ERROR: GPIB driver not recognised",eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AddCommand(pSics,argv[1],GPIBAction,GPIBKill,self);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
47
gpibcontroller.h
Normal file
47
gpibcontroller.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
Interface to a GPIB controller.
|
||||||
|
|
||||||
|
copyright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, January 2003
|
||||||
|
------------------------------------------------------------------------*/
|
||||||
|
#ifndef GPIBCONTROLLER
|
||||||
|
#define GPIBCONTROLLER
|
||||||
|
|
||||||
|
/*
|
||||||
|
error codes
|
||||||
|
*/
|
||||||
|
#define GPIBARG 4
|
||||||
|
#define GPIBEDVR 0
|
||||||
|
#define GPIBENEB 7
|
||||||
|
#define GPIBEABO 6
|
||||||
|
#define GPIBEADR 3
|
||||||
|
#define GPIBEBUS 14
|
||||||
|
#define GPIBENOL 2
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct __GPIB *pGPIB;
|
||||||
|
|
||||||
|
int GPIBattach(pGPIB self, int boardNo,
|
||||||
|
int address, int secondaryAddress,
|
||||||
|
int tmo, int eot, int eos);
|
||||||
|
int GPIBdetach(pGPIB self, int devID);
|
||||||
|
int GPIBsend(pGPIB self, int devID, void *buffer, int bytesToWrite);
|
||||||
|
int GPIBread(pGPIB self, int devID, void *buffer, int bytesToRead);
|
||||||
|
void GPIBclear(pGPIB self, int devID);
|
||||||
|
void GPIBerrorDescription(pGPIB self, int code,
|
||||||
|
char *buffer, int maxBuffer);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int MakeGPIB(SConnection *pCon, SicsInterp *pSics,
|
||||||
|
void *pData,
|
||||||
|
int argc, char *argv[]);
|
||||||
|
int GPIBAction(SConnection *pCon, SicsInterp *pSics,
|
||||||
|
void *pData,
|
||||||
|
int argc, char *argv[]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
22
gpibcontroller.i
Normal file
22
gpibcontroller.i
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
/*-----------------------------------------------------------------------
|
||||||
|
GPIBcontroller structure. Automatically generated file, modify in
|
||||||
|
gpib.w and run nuweb.
|
||||||
|
-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
struct __GPIB {
|
||||||
|
pObjectDescriptor pDes;
|
||||||
|
int (*attach)(int boardNo, int address,
|
||||||
|
int secondaryAddress,
|
||||||
|
int tmo, int eot, int eos);
|
||||||
|
int (*detach)(int devID);
|
||||||
|
int (*send)(int devID, void *buffer,
|
||||||
|
int count);
|
||||||
|
int (*read)(int devID, void *buffer,
|
||||||
|
int count);
|
||||||
|
int (*clear)(int devID);
|
||||||
|
void (*getErrorDescription)(int code,
|
||||||
|
char *buffer, int maxCount);
|
||||||
|
}GPIB;
|
||||||
|
|
@ -11,11 +11,11 @@ OBJ= el734_utility.o asynsrv_utility.o stredit.o \
|
|||||||
makeprint.o StrMatch.o
|
makeprint.o StrMatch.o
|
||||||
|
|
||||||
#---------- for Redhat linux
|
#---------- for Redhat linux
|
||||||
#CC= gcc
|
CC= gcc
|
||||||
#CFLAGS= -I/usr/local/include -I. -I../ -DLINUX -g -c
|
CFLAGS= -I$SINQDIR/linux/include -I. -I../ -DLINUX -g -c
|
||||||
#------------ for DigitalUnix
|
#------------ for DigitalUnix
|
||||||
CC=cc
|
#CC=cc
|
||||||
CFLAGS= -I. -I../ -std1 -g -c
|
#CFLAGS= -I. -I../ -std1 -g -c
|
||||||
#CFLAGS= -I/data/koenneck/include -I. -I../ -std1 -g -c
|
#CFLAGS= -I/data/koenneck/include -I. -I../ -std1 -g -c
|
||||||
#------------ for DigitalUnix with Fortify
|
#------------ for DigitalUnix with Fortify
|
||||||
## CC=cc
|
## CC=cc
|
||||||
@ -36,3 +36,9 @@ hlib: $(OBJ)
|
|||||||
clean:
|
clean:
|
||||||
rm -f *.o
|
rm -f *.o
|
||||||
rm -f *.a
|
rm -f *.a
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
27
modriv.h
27
modriv.h
@ -27,10 +27,14 @@
|
|||||||
int (*GetStatus)(void *self);
|
int (*GetStatus)(void *self);
|
||||||
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
||||||
int (*TryAndFixIt)(void *self, int iError,float fNew);
|
int (*TryAndFixIt)(void *self, int iError,float fNew);
|
||||||
int (*ContinueAfterWarn)(void *self);
|
|
||||||
int (*Halt)(void *self);
|
int (*Halt)(void *self);
|
||||||
}
|
int (*GetDriverPar)(void *self, char *name,
|
||||||
MotorDriver;
|
float *value);
|
||||||
|
int (*SetDriverPar)(void *self,SConnection *pCon,
|
||||||
|
char *name, float newValue);
|
||||||
|
void (*ListDriverPar)(void *self, char *motorName,
|
||||||
|
SConnection *pCon);
|
||||||
|
} MotorDriver;
|
||||||
|
|
||||||
/* the first fields above HAVE to be IDENTICAL to those below */
|
/* the first fields above HAVE to be IDENTICAL to those below */
|
||||||
|
|
||||||
@ -46,8 +50,13 @@
|
|||||||
int (*GetStatus)(void *self);
|
int (*GetStatus)(void *self);
|
||||||
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
||||||
int (*TryAndFixIt)(void *self,int iError, float fNew);
|
int (*TryAndFixIt)(void *self,int iError, float fNew);
|
||||||
int (*ContinueAfterWarn)(void *self);
|
|
||||||
int (*Halt)(void *self);
|
int (*Halt)(void *self);
|
||||||
|
int (*GetDriverPar)(void *self, char *name,
|
||||||
|
float *value);
|
||||||
|
int (*SetDriverPar)(void *self,SConnection *pCon,
|
||||||
|
char *name, float newValue);
|
||||||
|
void (*ListDriverPar)(void *self, char *motorName,
|
||||||
|
SConnection *pCon);
|
||||||
|
|
||||||
|
|
||||||
/* EL-734 specific fields */
|
/* EL-734 specific fields */
|
||||||
@ -71,8 +80,13 @@
|
|||||||
int (*GetStatus)(void *self);
|
int (*GetStatus)(void *self);
|
||||||
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
||||||
int (*TryAndFixIt)(void *self,int iError, float fNew);
|
int (*TryAndFixIt)(void *self,int iError, float fNew);
|
||||||
int (*ContinueAfterWarn)(void *self);
|
|
||||||
int (*Halt)(void *self);
|
int (*Halt)(void *self);
|
||||||
|
int (*GetDriverPar)(void *self, char *name,
|
||||||
|
float *value);
|
||||||
|
int (*SetDriverPar)(void *self,SConnection *pCon,
|
||||||
|
char *name, float newValue);
|
||||||
|
void (*ListDriverPar)(void *self, char *motorName,
|
||||||
|
SConnection *pCon);
|
||||||
|
|
||||||
/* Simulation specific fields */
|
/* Simulation specific fields */
|
||||||
float fFailure; /* percent random failures*/
|
float fFailure; /* percent random failures*/
|
||||||
@ -90,8 +104,5 @@
|
|||||||
/* ----------------------- Simulation -----------------------------------*/
|
/* ----------------------- Simulation -----------------------------------*/
|
||||||
MotorDriver *CreateSIM(SConnection *pCon, int argc, char *argv[]);
|
MotorDriver *CreateSIM(SConnection *pCon, int argc, char *argv[]);
|
||||||
void KillSIM(void *pData);
|
void KillSIM(void *pData);
|
||||||
|
|
||||||
/*------------------------ Default ContinueAfterWarn -----------------*/
|
|
||||||
int MoDrivXXXContinue(void *pData);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
43
motor.c
43
motor.c
@ -10,6 +10,7 @@
|
|||||||
revised: Mark Koennecke, June 1997
|
revised: Mark Koennecke, June 1997
|
||||||
callback added: Mark Koennecke, August 1997
|
callback added: Mark Koennecke, August 1997
|
||||||
endscript facility added: Mark Koennecke, August 2002
|
endscript facility added: Mark Koennecke, August 2002
|
||||||
|
Modified to support driver parameters, Mark Koennecke, January 2003
|
||||||
|
|
||||||
Copyright:
|
Copyright:
|
||||||
|
|
||||||
@ -34,7 +35,6 @@
|
|||||||
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
||||||
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
||||||
@ -333,17 +333,8 @@
|
|||||||
self->pDriver->GetError(self->pDriver,&iCode,pError,131);
|
self->pDriver->GetError(self->pDriver,&iCode,pError,131);
|
||||||
sprintf(pBueffel,"WARNING: %s on %s",pError,self->name);
|
sprintf(pBueffel,"WARNING: %s on %s",pError,self->name);
|
||||||
SCWrite(pCon,pBueffel,eStatus);
|
SCWrite(pCon,pBueffel,eStatus);
|
||||||
if(self->pDriver->ContinueAfterWarn(self->pDriver))
|
|
||||||
{
|
|
||||||
iRetry = 0;
|
|
||||||
return HWBusy;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iRetry = 0;
|
|
||||||
return HWIdle;
|
return HWIdle;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
iRetry = 0;
|
iRetry = 0;
|
||||||
return iRet;
|
return iRet;
|
||||||
}
|
}
|
||||||
@ -513,11 +504,21 @@ extern void KillPiPiezo(void *pData);
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
check for a driver parameter
|
||||||
|
*/
|
||||||
|
if(self->pDriver->GetDriverPar != NULL)
|
||||||
|
{
|
||||||
|
return self->pDriver->GetDriverPar(self->pDriver,name,fVal);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
int MotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal)
|
int MotorSetPar(pMotor self, SConnection *pCon, char *name, float fVal)
|
||||||
{
|
{
|
||||||
@ -553,10 +554,6 @@ extern void KillPiPiezo(void *pData);
|
|||||||
}
|
}
|
||||||
|
|
||||||
iRet = ObParSet(self->ParArray,self->name,name,fVal,pCon);
|
iRet = ObParSet(self->ParArray,self->name,name,fVal,pCon);
|
||||||
if(!iRet)
|
|
||||||
{
|
|
||||||
return iRet;
|
|
||||||
}
|
|
||||||
if(strcmp(name,"sign") == 0)
|
if(strcmp(name,"sign") == 0)
|
||||||
{
|
{
|
||||||
if((absf(fVal)-1.0) > 0.01)
|
if((absf(fVal)-1.0) > 0.01)
|
||||||
@ -573,6 +570,17 @@ extern void KillPiPiezo(void *pData);
|
|||||||
ObParInit(self->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser);
|
ObParInit(self->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
try set driver parameters
|
||||||
|
*/
|
||||||
|
if(iRet == 0)
|
||||||
|
{
|
||||||
|
if(self->pDriver->SetDriverPar != NULL)
|
||||||
|
{
|
||||||
|
iRet = self->pDriver->SetDriverPar(self->pDriver,pCon,name,fVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
return iRet;
|
return iRet;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------
|
/*---------------------------------------------------------------------------
|
||||||
@ -988,6 +996,13 @@ extern MotorDriver *MakePiPiezo(Tcl_Interp *pTcl, char *pArray);
|
|||||||
sprintf(pBueffel,"%s.TargetPosition = %f\n", self->name,self->fTarget);
|
sprintf(pBueffel,"%s.TargetPosition = %f\n", self->name,self->fTarget);
|
||||||
SCWrite(pCon,pBueffel,eStatus);
|
SCWrite(pCon,pBueffel,eStatus);
|
||||||
|
|
||||||
|
/*
|
||||||
|
list driver parameters when appropriate
|
||||||
|
*/
|
||||||
|
if(self->pDriver->ListDriverPar != NULL)
|
||||||
|
{
|
||||||
|
self->pDriver->ListDriverPar(self->pDriver,self->name, pCon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
void MotorReset(pMotor pM)
|
void MotorReset(pMotor pM)
|
||||||
|
106
nigpib.c
Normal file
106
nigpib.c
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
This is an implementation of a GPIB driver based on the drivers
|
||||||
|
provided by National Instruments. The driver has been tested
|
||||||
|
with the ENET-100 GPIB-TCP/IP bridge but should also work with
|
||||||
|
NI GPIB boards plugged into the composter.
|
||||||
|
|
||||||
|
copright: see file COPYRIGHT
|
||||||
|
|
||||||
|
Mark Koennecke, January 2002
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <tcl.h>
|
||||||
|
#include "fortify.h"
|
||||||
|
#include "sics.h"
|
||||||
|
#include <ugpib.h>
|
||||||
|
#include "gpibcontroller.i"
|
||||||
|
|
||||||
|
typedef struct __GPIB *pGPIB;
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int NIattach(int boardNo, int address, int secondaryAddress,
|
||||||
|
int tmo, int eot, int eos){
|
||||||
|
int devID;
|
||||||
|
|
||||||
|
devID = ibdev(boardNo, address, secondaryAddress, tmo, eot, eos);
|
||||||
|
if(devID < 0){
|
||||||
|
return -iberr;
|
||||||
|
} else {
|
||||||
|
return devID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------*/
|
||||||
|
static int NIdetach(int devID){
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = ibonl(devID, 0);
|
||||||
|
if(status & ERR){
|
||||||
|
return -iberr;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------*/
|
||||||
|
static int NIwrite(int devID, void *buffer, int bytesToWrite){
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = ibwrt(devID,buffer,bytesToWrite);
|
||||||
|
if(status & ERR){
|
||||||
|
return - iberr;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-------------------------------------------------------------------*/
|
||||||
|
static int NIread(int devID, void *buffer, int bytesToRead){
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = ibrd(devID,buffer,bytesToRead);
|
||||||
|
if(status & ERR){
|
||||||
|
return - iberr;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
static void NIclear(int devID){
|
||||||
|
ibclr(devID);
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------------*/
|
||||||
|
static void NIerror(int code, char *buffer, int maxBuffer){
|
||||||
|
int flag = - code;
|
||||||
|
|
||||||
|
switch(flag){
|
||||||
|
case EDVR:
|
||||||
|
case ENEB:
|
||||||
|
case ECIC:
|
||||||
|
strncpy(buffer,"NI-GPIB not correctly installed or bad address",
|
||||||
|
maxBuffer);
|
||||||
|
return;
|
||||||
|
case EABO:
|
||||||
|
strncpy(buffer,"Timeout on data transfer",maxBuffer);
|
||||||
|
return;
|
||||||
|
case EBUS:
|
||||||
|
strncpy(buffer,"No device connected to GPIB or address errror",
|
||||||
|
maxBuffer);
|
||||||
|
return;
|
||||||
|
case ENOL:
|
||||||
|
strncpy(buffer,"No listeners on bus. Perhaps address error?",
|
||||||
|
maxBuffer);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
strncpy(buffer,"Unrecognised error code, fix nigpib.c",
|
||||||
|
maxBuffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
void NIassign(pGPIB self){
|
||||||
|
self->attach = NIattach;
|
||||||
|
self->detach = NIdetach;
|
||||||
|
self->send = NIwrite;
|
||||||
|
self->read = NIread;
|
||||||
|
self->getErrorDescription = NIerror;
|
||||||
|
}
|
17
obpar.c
17
obpar.c
@ -122,6 +122,23 @@
|
|||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
int ObParIndex(ObPar *self, char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
for(i = 0; self[i].iCode != -100; i++)
|
||||||
|
{
|
||||||
|
if(strcmp(name,self[i].name) == 0)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
int ObParInit(ObPar *self, int i, char *name, float fVal, int iCode)
|
int ObParInit(ObPar *self, int i, char *name, float fVal, int iCode)
|
||||||
{
|
{
|
||||||
|
4
obpar.h
4
obpar.h
@ -42,6 +42,10 @@
|
|||||||
/*
|
/*
|
||||||
finds a ObPar struct for a name, return NULL if none
|
finds a ObPar struct for a name, return NULL if none
|
||||||
*/
|
*/
|
||||||
|
int ObParIndex(ObPar *self, char *name);
|
||||||
|
/*
|
||||||
|
finds an index for name in self. Returns -1 on failure
|
||||||
|
*/
|
||||||
|
|
||||||
int ObParInit(ObPar *self,int i, char *name, float fVal, int iCode);
|
int ObParInit(ObPar *self,int i, char *name, float fVal, int iCode);
|
||||||
/*
|
/*
|
||||||
|
6
ofac.c
6
ofac.c
@ -108,6 +108,8 @@
|
|||||||
#include "lomax.h"
|
#include "lomax.h"
|
||||||
#include "polterwrite.h"
|
#include "polterwrite.h"
|
||||||
#include "anticollider.h"
|
#include "anticollider.h"
|
||||||
|
#include "gpibcontroller.h"
|
||||||
|
#include "ecb.h"
|
||||||
/*----------------------- Server options creation -------------------------*/
|
/*----------------------- Server options creation -------------------------*/
|
||||||
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
|
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
int argc, char *argv[])
|
int argc, char *argv[])
|
||||||
@ -291,6 +293,8 @@
|
|||||||
AddCommand(pInter,"MakeMaxDetector",LoMaxFactory,NULL,NULL);
|
AddCommand(pInter,"MakeMaxDetector",LoMaxFactory,NULL,NULL);
|
||||||
AddCommand(pInter,"PolterInstall",PolterInstall,NULL,NULL);
|
AddCommand(pInter,"PolterInstall",PolterInstall,NULL,NULL);
|
||||||
AddCommand(pInter,"AntiCollisionInstall",AntiColliderFactory,NULL,NULL);
|
AddCommand(pInter,"AntiCollisionInstall",AntiColliderFactory,NULL,NULL);
|
||||||
|
AddCommand(pInter,"MakeGPIB",MakeGPIB,NULL,NULL);
|
||||||
|
AddCommand(pInter,"MakeECB",MakeECB,NULL,NULL);
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void KillIniCommands(SicsInterp *pSics)
|
static void KillIniCommands(SicsInterp *pSics)
|
||||||
@ -351,6 +355,8 @@
|
|||||||
RemoveCommand(pSics,"MakeMaxDetector");
|
RemoveCommand(pSics,"MakeMaxDetector");
|
||||||
RemoveCommand(pSics,"PolterInstall");
|
RemoveCommand(pSics,"PolterInstall");
|
||||||
RemoveCommand(pSics,"AntiColliderInstall");
|
RemoveCommand(pSics,"AntiColliderInstall");
|
||||||
|
RemoveCommand(pSics,"MakeGPIB");
|
||||||
|
RemoveCommand(pSics,"MakeECB");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
13
pimotor.c
13
pimotor.c
@ -33,8 +33,13 @@
|
|||||||
int (*GetStatus)(void *self);
|
int (*GetStatus)(void *self);
|
||||||
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
||||||
int (*TryAndFixIt)(void *self,int iError, float fNew);
|
int (*TryAndFixIt)(void *self,int iError, float fNew);
|
||||||
int (*ContinueAfterWarn)(void *self);
|
|
||||||
int (*Halt)(void *self);
|
int (*Halt)(void *self);
|
||||||
|
int (*GetDriverPar)(void *self, char *name,
|
||||||
|
float *value);
|
||||||
|
int (*SetDriverPar)(void *self,SConnection *pCon,
|
||||||
|
char *name, float newValue);
|
||||||
|
void (*ListDriverPar)(void *self, char *motorName,
|
||||||
|
SConnection *pCon);
|
||||||
|
|
||||||
|
|
||||||
/* C-804 specific fields */
|
/* C-804 specific fields */
|
||||||
@ -281,11 +286,6 @@
|
|||||||
}
|
}
|
||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
/*------------------------------------------------------------------------*/
|
|
||||||
static int PIContinue(void *self)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*--------------------------------------------------------------------------
|
/*--------------------------------------------------------------------------
|
||||||
* The data necessary for initialising the C804 motor is contained in a
|
* The data necessary for initialising the C804 motor is contained in a
|
||||||
* Tcl-Array given as pArray parameter. In case of an error the error is
|
* Tcl-Array given as pArray parameter. In case of an error the error is
|
||||||
@ -433,7 +433,6 @@
|
|||||||
pNew->GetStatus = PIStatus;
|
pNew->GetStatus = PIStatus;
|
||||||
pNew->GetError = PIError;
|
pNew->GetError = PIError;
|
||||||
pNew->TryAndFixIt = PIFixError;
|
pNew->TryAndFixIt = PIFixError;
|
||||||
pNew->ContinueAfterWarn = PIContinue;
|
|
||||||
pNew->Halt = PIHalt;
|
pNew->Halt = PIHalt;
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
|
13
pipiezo.c
13
pipiezo.c
@ -33,8 +33,13 @@
|
|||||||
int (*GetStatus)(void *self);
|
int (*GetStatus)(void *self);
|
||||||
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
void (*GetError)(void *self, int *iCode, char *buffer, int iBufLen);
|
||||||
int (*TryAndFixIt)(void *self,int iError, float fNew);
|
int (*TryAndFixIt)(void *self,int iError, float fNew);
|
||||||
int (*ContinueAfterWarn)(void *self);
|
|
||||||
int (*Halt)(void *self);
|
int (*Halt)(void *self);
|
||||||
|
int (*GetDriverPar)(void *self, char *name,
|
||||||
|
float *value);
|
||||||
|
int (*SetDriverPar)(void *self,SConnection *pCon,
|
||||||
|
char *name, float newValue);
|
||||||
|
void (*ListDriverPar)(void *self, char *motorName,
|
||||||
|
SConnection *pCon);
|
||||||
|
|
||||||
|
|
||||||
/* PiPiezo specific fields */
|
/* PiPiezo specific fields */
|
||||||
@ -271,11 +276,6 @@
|
|||||||
}
|
}
|
||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
/*------------------------------------------------------------------------*/
|
|
||||||
static int PIContinue(void *self)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*--------------------------------------------------------------------------
|
/*--------------------------------------------------------------------------
|
||||||
* The data necessary for initialising the PiPiezo motor is contained in a
|
* The data necessary for initialising the PiPiezo motor is contained in a
|
||||||
* Tcl-Array given as pArray parameter. In case of an error the error is
|
* Tcl-Array given as pArray parameter. In case of an error the error is
|
||||||
@ -383,7 +383,6 @@
|
|||||||
pNew->GetStatus = PIStatus;
|
pNew->GetStatus = PIStatus;
|
||||||
pNew->GetError = PIError;
|
pNew->GetError = PIError;
|
||||||
pNew->TryAndFixIt = PIFixError;
|
pNew->TryAndFixIt = PIFixError;
|
||||||
pNew->ContinueAfterWarn = PIContinue;
|
|
||||||
pNew->Halt = PIHalt;
|
pNew->Halt = PIHalt;
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
|
28
sicsstat.tcl
28
sicsstat.tcl
@ -1,8 +1,20 @@
|
|||||||
# Motor gurke
|
# Motor a77
|
||||||
gurke SoftZero 0.000000
|
a77 sign 1.000000
|
||||||
gurke SoftLowerLim -20.000000
|
a77 SoftZero 0.000000
|
||||||
gurke SoftUpperLim 20.000000
|
a77 SoftLowerLim -30.000000
|
||||||
gurke Fixed -1.000000
|
a77 SoftUpperLim 30.000000
|
||||||
gurke sign 1.000000
|
a77 Fixed -1.000000
|
||||||
gurke InterruptMode 0.000000
|
a77 InterruptMode 0.000000
|
||||||
gurke AccessCode 2.000000
|
a77 AccessCode 2.000000
|
||||||
|
samplename KohlSulfid
|
||||||
|
samplename setAccess 2
|
||||||
|
comment UNKNOWN
|
||||||
|
comment setAccess 2
|
||||||
|
environment UNKNOWN
|
||||||
|
environment setAccess 2
|
||||||
|
subtitle UNKNOWN
|
||||||
|
subtitle setAccess 2
|
||||||
|
user Albert von Villigen
|
||||||
|
user setAccess 2
|
||||||
|
title UNKNOWN
|
||||||
|
title setAccess 2
|
||||||
|
@ -264,6 +264,7 @@
|
|||||||
DeleteTokenList(pList);
|
DeleteTokenList(pList);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
memset(pDriv,0,sizeof(SIMDriv));
|
||||||
|
|
||||||
/* check and enter args, first lowerLimit */
|
/* check and enter args, first lowerLimit */
|
||||||
pCurrent = pList;
|
pCurrent = pList;
|
||||||
@ -329,7 +330,6 @@
|
|||||||
pDriv->GetError = SimError;
|
pDriv->GetError = SimError;
|
||||||
pDriv->TryAndFixIt = SimFix;
|
pDriv->TryAndFixIt = SimFix;
|
||||||
pDriv->Halt = SimHalt;
|
pDriv->Halt = SimHalt;
|
||||||
pDriv->ContinueAfterWarn = MoDrivXXXContinue;
|
|
||||||
pDriv->fSpeed = .01;
|
pDriv->fSpeed = .01;
|
||||||
pDriv->iTime = 0;
|
pDriv->iTime = 0;
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#
|
#
|
||||||
# Markus Zolliker, March 2000
|
# Markus Zolliker, March 2000
|
||||||
# may now be used on different systems without change M.Z.01.2002
|
# may now be used on different systems without change M.Z.01.2002
|
||||||
|
# This only works with tcsh, not with bash under Linux M.K.01.2003
|
||||||
#--------------------------------------------------------------------------
|
#--------------------------------------------------------------------------
|
||||||
#------------ for DigitalUnix (add -DFORTIFY to CC_... for fortified version)
|
#------------ for DigitalUnix (add -DFORTIFY to CC_... for fortified version)
|
||||||
CC_alpha_osf1=cc -std1 -g -warnprotos -I../ -I. -I../hardsup
|
CC_alpha_osf1=cc -std1 -g -warnprotos -I../ -I. -I../hardsup
|
||||||
|
Reference in New Issue
Block a user