- GPIB/ECB modules completed, ecb motor driver in progress

This commit is contained in:
cvs
2003-01-17 16:09:34 +00:00
parent bbc0b64c43
commit f45c3ebf55
27 changed files with 2030 additions and 84 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

47
motor.c
View File

@ -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,16 +333,7 @@
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)) return HWIdle;
{
iRetry = 0;
return HWBusy;
}
else
{
iRetry = 0;
return HWIdle;
}
} }
iRetry = 0; iRetry = 0;
return iRet; return iRet;
@ -514,7 +505,17 @@ extern void KillPiPiezo(void *pData);
} }
else else
{ {
return 0; /*
check for a driver parameter
*/
if(self->pDriver->GetDriverPar != NULL)
{
return self->pDriver->GetDriverPar(self->pDriver,name,fVal);
}
else
{
return 0;
}
} }
} }
} }
@ -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
View 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
View File

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

View File

@ -42,7 +42,11 @@
/* /*
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);
/* /*
sets a ObPar entry. self is a pointer to the array sets a ObPar entry. self is a pointer to the array

6
ofac.c
View File

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

View File

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

View File

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

View File

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

View File

@ -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
task.h
View File

@ -117,5 +117,4 @@
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#endif #endif

View File

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