forked from epics_driver_modules/motorBase
Changes for multiple motors/group
This commit is contained in:
+174
-123
@@ -4,6 +4,20 @@
|
||||
/*
|
||||
* Original Author: Jon Kelly
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*
|
||||
* 13th May 2005
|
||||
*
|
||||
* 1) The use of multiaxis groups has been enabled with the addition of
|
||||
* variables to the drvXPSC8.cc: XPSC8Name_config function used in the st.cmd.
|
||||
* 2) A cue feature has now been added so that if a command is sent while
|
||||
* a group is busy it is cued until the group becomes static.
|
||||
* 3) The driver waits for a time specified in drvXPSC8.h: XPSC8_QUE_PAUSE when
|
||||
* a command is issued. It then performs all the motions specified in the lapsed
|
||||
* time as a single syncronised motion. The pause is performed in drvXPSC8.cc:
|
||||
* send_mess.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -16,9 +30,8 @@
|
||||
#include "motorRecord.h"
|
||||
#include "motor.h"
|
||||
#include "motordevCom.h"
|
||||
#include "drvXPSC8.h"
|
||||
|
||||
/*#define DLL _declspec(dllexport)*/
|
||||
#include "drvXPSC8.h"
|
||||
#include "xps_c8_driver.h"
|
||||
|
||||
#define STATIC static
|
||||
@@ -31,24 +44,23 @@ extern struct driver_table XPSC8_access;
|
||||
#define MOVING 1
|
||||
|
||||
/*----------------debugging-----------------*/
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#ifdef __GNUG__
|
||||
#ifdef DEBUG
|
||||
volatile int devXPSC8Debug = 0;
|
||||
volatile int devXPSC8Debug = 3;
|
||||
#define Debug(L, FMT, V...) { if(L <= devXPSC8Debug) \
|
||||
{ printf("%s(%d):",__FILE__,__LINE__); \
|
||||
printf(FMT,##V); } }
|
||||
epicsExportAddress(int, devXPSC8Debug);
|
||||
#else
|
||||
#else
|
||||
#define Debug(L, FMT, V...)
|
||||
#endif
|
||||
#else
|
||||
#endif
|
||||
#else
|
||||
#define Debug()
|
||||
#endif
|
||||
|
||||
/* Debugging levels:
|
||||
* devXPSC8Debug >= 3 Print new part of command and command string so far
|
||||
* at the end of XPSC8_build_trans
|
||||
*/
|
||||
|
||||
|
||||
/* ----------------Create the dsets for devXPSC8----------------- */
|
||||
@@ -59,6 +71,7 @@ STATIC long XPSC8_start_trans(struct motorRecord *);
|
||||
STATIC RTN_STATUS XPSC8_build_trans(motor_cmnd, double *, struct motorRecord *);
|
||||
STATIC RTN_STATUS XPSC8_end_trans(struct motorRecord *);
|
||||
|
||||
|
||||
struct motor_dset devXPSC8 =
|
||||
{
|
||||
{8, NULL, (DEVSUPFUN)XPSC8_init, (DEVSUPFUN)XPSC8_init_record, NULL},
|
||||
@@ -109,16 +122,16 @@ STATIC long XPSC8_init(int after)
|
||||
{
|
||||
long rtnval;
|
||||
|
||||
Debug(1, "XPSC8_init, after=%d\n", after);
|
||||
Debug(10, "XPSC8_init, after=%d\n", after);
|
||||
if (after == 0) {
|
||||
drvtabptr = &XPSC8_access;
|
||||
Debug(1, "XPSC8_init, calling driver initialization\n");
|
||||
Debug(10, "XPSC8_init, calling driver initialization\n");
|
||||
(drvtabptr->init)();
|
||||
}
|
||||
|
||||
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr,
|
||||
&XPSC8_cards);
|
||||
Debug(1, "XPSC8_init, end of function\n");
|
||||
Debug(10, "XPSC8_init, end of function\n");
|
||||
return(rtnval);
|
||||
}
|
||||
|
||||
@@ -134,7 +147,7 @@ STATIC long XPSC8_init_record(struct motorRecord *mr)
|
||||
struct XPSC8axis *cntrl;
|
||||
int card, signal;
|
||||
|
||||
Debug(1, "--------XPSC8_init_record \n");
|
||||
Debug(10, "--------XPSC8_init_record \n");
|
||||
rtnval = motor_init_record_com(mr, *drvtabptr->cardcnt_ptr,
|
||||
drvtabptr, XPSC8_cards);
|
||||
/* We have a logic problem here. motor_init has read in the motor
|
||||
@@ -151,10 +164,10 @@ STATIC long XPSC8_init_record(struct motorRecord *mr)
|
||||
control = (struct XPSC8controller *) brdptr->DevicePrivate;
|
||||
cntrl = (struct XPSC8axis *)&control->axis[signal];
|
||||
cntrl->resolution = mr->mres; /* Set the motor resolution */
|
||||
mr->rmp = NINT(cntrl->currentposition[1] / cntrl->resolution);
|
||||
Debug(1, "XPSC8_init_record: card=%d, signal=%d, currentposition[1]=%f"\
|
||||
mr->rmp = NINT((cntrl->currentposition) / (cntrl->resolution));
|
||||
Debug(1, "XPSC8_init_record: card=%d, signal=%d, currentposition=%f"\
|
||||
" resolution=%f, mr->rmp=%d\n",\
|
||||
card, signal, cntrl->currentposition[1], cntrl->resolution, mr->rmp);
|
||||
card, signal, cntrl->currentposition, cntrl->resolution, mr->rmp);
|
||||
return(rtnval);
|
||||
}
|
||||
|
||||
@@ -162,7 +175,6 @@ STATIC long XPSC8_init_record(struct motorRecord *mr)
|
||||
/* start building a transaction */
|
||||
STATIC long XPSC8_start_trans(struct motorRecord *mr)
|
||||
{
|
||||
Debug(1, "--------XPSC8_start_trans\n");
|
||||
long rtnval;
|
||||
rtnval = motor_start_trans_com(mr, XPSC8_cards);
|
||||
return(rtnval);
|
||||
@@ -172,7 +184,6 @@ STATIC long XPSC8_start_trans(struct motorRecord *mr)
|
||||
/* end building a transaction */
|
||||
STATIC RTN_STATUS XPSC8_end_trans(struct motorRecord *mr)
|
||||
{
|
||||
Debug(1, "--------XPSC8_end_trans\n");
|
||||
RTN_STATUS rtnval;
|
||||
rtnval = motor_end_trans_com(mr, drvtabptr);
|
||||
return(rtnval);
|
||||
@@ -181,23 +192,26 @@ STATIC RTN_STATUS XPSC8_end_trans(struct motorRecord *mr)
|
||||
|
||||
|
||||
/* add a part to the transaction */
|
||||
STATIC RTN_STATUS XPSC8_build_trans(motor_cmnd command, double *parms, struct motorRecord *mr)
|
||||
STATIC RTN_STATUS XPSC8_build_trans(motor_cmnd command,\
|
||||
double *parms, \
|
||||
struct motorRecord *mr)
|
||||
{
|
||||
struct motor_trans *trans = (struct motor_trans *) mr->dpvt;
|
||||
struct mess_node *motor_call;
|
||||
struct controller *brdptr;
|
||||
struct XPSC8controller *control;
|
||||
struct XPSC8axis *cntrl;
|
||||
double dval=0.,resolution,steps;
|
||||
struct XPSC8group *groupcntrl; /*XPS group specific data */
|
||||
double dval=0.0,resolution,steps;
|
||||
int ival=0;
|
||||
RTN_STATUS rtnval=OK;
|
||||
int card, signal;
|
||||
int groupnumber, groupsize;
|
||||
int axisingroup, groupstatus;
|
||||
int status;
|
||||
|
||||
int positioner, status;
|
||||
|
||||
positioner = 1; /* Means only move one axis at a time */
|
||||
if (parms != NULL){
|
||||
dval = parms[0]; /* I assume this is the record DVAL which you set*/
|
||||
dval = parms[0]; /* This is the record DVAL which you set */
|
||||
/* to move e.g. dval = 10mm and command = MOVE_ABS*/
|
||||
ival = NINT(parms[0]);
|
||||
}
|
||||
@@ -207,195 +221,233 @@ STATIC RTN_STATUS XPSC8_build_trans(motor_cmnd command, double *parms, struct mo
|
||||
signal = motor_call->signal;
|
||||
brdptr = (*trans->tabptr->card_array)[card];
|
||||
|
||||
Debug(11, "XPSC8_build_trans: After brdptr command\n");
|
||||
Debug(10, "XPSC8_build_trans: After brdptr command\n");
|
||||
|
||||
if (brdptr == NULL)
|
||||
return(rtnval = ERROR);
|
||||
|
||||
control = (struct XPSC8controller *) brdptr->DevicePrivate;
|
||||
cntrl = (struct XPSC8axis *)&control->axis[signal];
|
||||
|
||||
groupstatus = cntrl->groupstatus; /* From XPS controller */
|
||||
axisingroup = cntrl->axisingroup; /* Pull in group info */
|
||||
groupnumber = cntrl->groupnumber;
|
||||
|
||||
groupcntrl = (struct XPSC8group *)&control->group[groupnumber];
|
||||
groupsize = groupcntrl->groupsize; /* Number of motors in group */
|
||||
|
||||
cntrl->resolution = mr->mres; /* Read in the motor resolution */
|
||||
resolution = cntrl->resolution;
|
||||
steps = resolution * dval;
|
||||
steps = resolution * dval; /* This could be a position or velocity */
|
||||
|
||||
/* mr->dllm = cntrl->minlimit;*/ /* set the epics limits to the XPS limits */
|
||||
/* mr->dhlm = cntrl->maxlimit; */
|
||||
|
||||
Debug(1, "XPSC8_build_trans: card=%d, signal=%d, command=%d, ival=%d"\
|
||||
Debug(10, "XPSC8_build_trans: card=%d, signal=%d, command=%d, ival=%d"\
|
||||
" dval=%f, steps=%f\n",\
|
||||
card, signal, command, ival, dval, steps);
|
||||
|
||||
Debug(1, "XPSC8_build_trans: resolution=%f\n",resolution);
|
||||
Debug(10, "XPSC8_build_trans: resolution=%f\n",resolution);
|
||||
if (XPSC8_table[command] > motor_call->type)
|
||||
motor_call->type = XPSC8_table[command];
|
||||
Debug(11, "XPSC8_build_trans: After cntrl command\n");
|
||||
if (trans->state != BUILD_STATE)
|
||||
return(rtnval = ERROR);
|
||||
Debug(11, "XPSC8_build_trans: After cntrl command\n");
|
||||
/* Take a lock so that only 1 thread can be talking to the XPSC8 at
|
||||
* once. I don't know if this is needed? */
|
||||
|
||||
epicsMutexLock(control->XPSC8Lock);
|
||||
|
||||
/* No need to deal with initialization, premove or postmove strings,
|
||||
XPSC8 does not support */
|
||||
|
||||
Debug(1, "build_trans: Top Of Switch command=%d, cntrl->moving=%d"\
|
||||
" GStat=%d-\n", command,cntrl->moving,cntrl->groupstatus);
|
||||
|
||||
Debug(10, "build_trans: Top Of Switch command=%d, cntrl->moving=%d"\
|
||||
" \n GroupStat=%d\n", command,cntrl->moving,cntrl->groupstatus);
|
||||
|
||||
Debug(5,"Build_trans: com=%d, axis=%d, moving=%d socket=%i psocket=%i\n",\
|
||||
command,signal,cntrl->moving,cntrl->socket,cntrl->devpollsocket);
|
||||
|
||||
status = GroupStatusGet(cntrl->devpollsocket, cntrl->groupname,
|
||||
&cntrl->groupstatus);
|
||||
if (status != 0)
|
||||
printf("BuildTrans Error performing GroupStatusGet status=%d\n", status);
|
||||
|
||||
groupstatus = cntrl->groupstatus; /* Update groupstatus */
|
||||
|
||||
switch (command) {
|
||||
case MOVE_ABS:/* command 0*/
|
||||
|
||||
Debug(1, "XPSC8_build_trans: command=%d, Move_ABS moving=%d steps=%f\n",\
|
||||
command,cntrl->moving, steps);
|
||||
|
||||
if ((groupstatus < 10) || (groupstatus == 47)) {
|
||||
/* ie not initialized state or Jogging!*/
|
||||
break;}
|
||||
|
||||
/* If there is no cue, update the cue array to make sure you don't move */
|
||||
/* the wrong motors */
|
||||
if ((groupcntrl->cuesize == 0) && (groupstatus > 9 && groupstatus < 20)){
|
||||
status = GroupPositionCurrentGet(cntrl->devpollsocket,
|
||||
cntrl->groupname,
|
||||
groupsize,
|
||||
groupcntrl->positionarray); /* Array! */
|
||||
|
||||
if ((cntrl->moving) == MOVING) {
|
||||
printf("--STILL MOVING--\n");
|
||||
goto done;
|
||||
} /* This is set in drvXPSC8.cc*/
|
||||
if (status != 0) {
|
||||
printf(" Error performing GroupPositionCurrentGet\n");
|
||||
}
|
||||
}
|
||||
|
||||
Debug(11, "Move_ABS socket=%d posiname=%s posit=%d dval=%f\n",\
|
||||
cntrl->socket, cntrl->positionername, positioner, dval);
|
||||
epicsThreadSleep(0.1);
|
||||
|
||||
status = GroupMoveAbsolute(cntrl->socket, cntrl->positionername,
|
||||
positioner, &steps);
|
||||
if (status != 0) {
|
||||
printf(" Error performing GroupMoveAbsolute\n");
|
||||
}
|
||||
|
||||
Debug(1, "--After GroupMoveAbsolute command=%d,Move_ABS moving=%d \n",\
|
||||
command,cntrl->moving);
|
||||
|
||||
|
||||
/* Always add the move to the cue */
|
||||
groupcntrl->positionarray[axisingroup] = steps;
|
||||
++groupcntrl->cuesize; /* Add 1 to cue total */
|
||||
if (groupcntrl->cuesize == 1)
|
||||
groupcntrl->cueflag = 1;/* If first call set flag */
|
||||
if (groupcntrl->cuesize > 1)
|
||||
Debug(2,"******Adding move to an existing cue***\n");
|
||||
|
||||
/* The communication and looping has been moved to drvXPSC8 send_mess */
|
||||
|
||||
break;
|
||||
|
||||
case MOVE_REL:
|
||||
/* Using the SGamma setings in stages.ini */
|
||||
if (cntrl->moving == MOVING) goto done;
|
||||
/* This is set in drvXPSC8.cc*/
|
||||
status = GroupMoveRelative(cntrl->socket, cntrl->positionername,
|
||||
positioner, &steps);
|
||||
if (status != 0) printf(" Error performing GroupMoveRelative\n");
|
||||
break;
|
||||
case MOVE_REL:/*1*/
|
||||
/* The motor record seems to impliment the relative move by
|
||||
calculating the new position and calling MOVE_ABS */
|
||||
|
||||
case HOME_FOR:
|
||||
case HOME_REV:
|
||||
/* If motion has been killed the group will need to be initialized*/
|
||||
case HOME_FOR:
|
||||
|
||||
case HOME_REV: /*3*/
|
||||
if (cntrl->groupstatus == 43 ) { /* Allready Homing */
|
||||
break;}
|
||||
|
||||
/* If motion has been killed the group will need to be initialized*/
|
||||
/* and homed before the motors can be driven again */
|
||||
if (cntrl->groupstatus < 10 ) {
|
||||
|
||||
if (cntrl->groupstatus < 10 ) {
|
||||
/* ie not initialized state!*/
|
||||
status = GroupInitialize(cntrl->pollsocket,cntrl->groupname);
|
||||
status = GroupInitialize(cntrl->devpollsocket,cntrl->groupname);
|
||||
if (status != 0) {
|
||||
printf("HOME Command Error performing GroupInitialise\n");
|
||||
}
|
||||
status = GroupStatusGet(cntrl->pollsocket, cntrl->groupname,
|
||||
&cntrl->groupstatus);
|
||||
if (status != 0) {
|
||||
printf(" Error performing GroupStatusGet\n");
|
||||
}
|
||||
Debug(1, "XPSC8_build_trans:****** Perform GroupInitialize\n");
|
||||
|
||||
status = GroupHomeSearch(cntrl->socket,cntrl->groupname);
|
||||
if (status != 0) {
|
||||
printf(" Error performing GroupHomeSearch\n");
|
||||
}
|
||||
Debug(1, "XPSC8_build_trans:******* Perform GroupHomeSearch\n");
|
||||
}
|
||||
|
||||
break;
|
||||
goto home_rev_end;
|
||||
}
|
||||
|
||||
status = GroupKill(cntrl->pollsocket,cntrl->groupname);
|
||||
|
||||
/* Else kill all the motions an home */
|
||||
|
||||
status = GroupKill(cntrl->devpollsocket,cntrl->groupname);
|
||||
if (status != 0) {
|
||||
printf(" Error performing GroupKill\n");
|
||||
}
|
||||
|
||||
status = GroupInitialize(cntrl->pollsocket,cntrl->groupname);
|
||||
status = GroupInitialize(cntrl->devpollsocket,cntrl->groupname);
|
||||
if (status != 0) {
|
||||
printf("HOME Command Error performing GroupInitialise\n");
|
||||
}
|
||||
|
||||
|
||||
status = GroupStatusGet(cntrl->pollsocket, cntrl->groupname,
|
||||
&cntrl->groupstatus);
|
||||
if (status != 0) {
|
||||
printf(" Error performing GroupStatusGet\n");
|
||||
}
|
||||
Debug(1, "XPSC8_build_trans:****** Perform GroupInitialize\n");
|
||||
|
||||
status = GroupHomeSearch(cntrl->socket,cntrl->groupname);
|
||||
if (status != 0) {
|
||||
printf(" Error performing GroupHomeSearch\n");
|
||||
}
|
||||
Debug(1, "XPSC8_build_trans:******* Perform GroupHomeSearch\n");
|
||||
Debug(2, "XPSC8_build_trans:******* Perform GroupHomeSearch\n");
|
||||
Debug(2, "XPSC8_build_trans:groupsize=%i\n",groupsize);
|
||||
|
||||
/*}*/
|
||||
|
||||
/* if (cntrl->groupstatus == NOTREF ){ */
|
||||
/* you must kill a group before homing*/
|
||||
/*}*/
|
||||
|
||||
home_rev_end: /* Used for goto statment above */
|
||||
|
||||
/* When a group is homed the drive cue is emptied */
|
||||
|
||||
groupcntrl->cuesize = 0; /* Reset cue */
|
||||
groupcntrl->cueflag = 0;
|
||||
|
||||
break;
|
||||
|
||||
case LOAD_POS:
|
||||
/* command 4 I assume it means just update the position value? */
|
||||
/*status = GroupPositionCurrentGet(cntrl->socket,
|
||||
cntrl->positionername,
|
||||
positioner,
|
||||
&cntrl->currentposition[1]);
|
||||
if (status != 0)
|
||||
printf(" Error performing GroupPositionCurrentGet Load Pos\n");*/
|
||||
case LOAD_POS:/* 4*/
|
||||
/* command 4 Not used*/
|
||||
|
||||
break;
|
||||
|
||||
case SET_VEL_BASE:
|
||||
/* The XPS does not have a different Base velocity!!!*/
|
||||
break;
|
||||
case SET_VELOCITY:
|
||||
case SET_VELOCITY: /*6*/
|
||||
/* The XPS does not have a different Base velocity!!!!!
|
||||
So I perform the same operation for VEL_BASE and VEL*/
|
||||
|
||||
status = PositionerSGammaParametersSet(cntrl->pollsocket,
|
||||
status = PositionerSGammaParametersSet(cntrl->devpollsocket,
|
||||
cntrl->positionername, steps,
|
||||
cntrl->accel,
|
||||
cntrl->minjerktime,
|
||||
cntrl->maxjerktime);
|
||||
if (status != 0)
|
||||
if (status != 0) {
|
||||
printf(" Error performing PositionerSGammaParameters Set Vel\n");
|
||||
printf(" steps=%f resoulution=%f DVAL=%f\n",steps,resolution,dval);
|
||||
}
|
||||
else cntrl->velocity = steps;
|
||||
break;
|
||||
|
||||
case SET_ACCEL: /* command 7 */
|
||||
status = PositionerSGammaParametersSet(cntrl->pollsocket,
|
||||
status = PositionerSGammaParametersSet(cntrl->devpollsocket,
|
||||
cntrl->positionername,
|
||||
cntrl->velocity,
|
||||
steps, cntrl->minjerktime,
|
||||
cntrl->maxjerktime);
|
||||
if (status != 0)
|
||||
printf(" Error performing PositionerSGammaParameters Set Accel\n");
|
||||
if (status != 0) {
|
||||
printf(" Error performing PositionerSGammaParameters Set Accel %i\n",
|
||||
status);
|
||||
printf(" steps=%f resoulution=%f DVAL=%f\n",steps,resolution,dval);
|
||||
if (status == -17)
|
||||
printf("devXPSC8 BuildTrans: One of the parameters was out of range!");
|
||||
}
|
||||
else cntrl->accel = steps;
|
||||
break;
|
||||
|
||||
case GO:
|
||||
case GO: /* 8 */
|
||||
if (groupstatus == 20) { /* If disabled then enable */
|
||||
status = GroupMotionEnable(cntrl->devpollsocket,cntrl->groupname);
|
||||
if (status != 0)
|
||||
printf(" Error performing GroupMotionEnable %i\n",status);
|
||||
}
|
||||
break;
|
||||
|
||||
case SET_ENC_RATIO: /* These must be set in the Stages.ini file */
|
||||
break;
|
||||
|
||||
case GET_INFO: /* Again I don't know what this is intended to do? */
|
||||
case GET_INFO: /* 10 * This is run when you press Go from stop!*/
|
||||
break;
|
||||
|
||||
case STOP_AXIS:
|
||||
case STOP_AXIS: /* 11 */
|
||||
/* The whole group must stop, not just 1 axis */
|
||||
if (cntrl->groupstatus > 42) {
|
||||
/* Update status to see if the group is moving */
|
||||
|
||||
if (cntrl->groupstatus > 42) {
|
||||
/* Then the group is moving! */
|
||||
status = GroupMoveAbort(cntrl->pollsocket,cntrl->groupname);
|
||||
if (status != 0) printf(" Error performing GroupMoveAbort(\n");
|
||||
}
|
||||
status = GroupMoveAbort(cntrl->devpollsocket,cntrl->groupname);
|
||||
if (status != 0) {
|
||||
printf(" Error performing GroupMoveAbort = %i %s(\n",\
|
||||
status,cntrl->groupname);
|
||||
|
||||
}
|
||||
/* When a group is stopped the drive cue is emptied and reset*/
|
||||
|
||||
status = GroupPositionCurrentGet(cntrl->devpollsocket,
|
||||
cntrl->groupname,
|
||||
groupsize,
|
||||
groupcntrl->positionarray);
|
||||
if (status != 0) {
|
||||
printf(" Error performing GroupPositionCurrentGet\n");
|
||||
}
|
||||
}
|
||||
groupcntrl->cuesize = 0; /* Reset cue */
|
||||
groupcntrl->cueflag = 0;
|
||||
break;
|
||||
|
||||
case JOG:
|
||||
/* I need more commandds to impliment this i.e. enable/disable
|
||||
/* I need more commandds to impliment this i.e. enable/disable jog
|
||||
set velocity and acceleration */
|
||||
break;
|
||||
|
||||
case SET_PGAIN:
|
||||
case SET_PGAIN: /* 13 */
|
||||
case SET_IGAIN:
|
||||
case SET_DGAIN:
|
||||
/* These can be implimented but there are so many variables */
|
||||
@@ -405,12 +457,12 @@ STATIC RTN_STATUS XPSC8_build_trans(motor_cmnd command, double *parms, struct mo
|
||||
/* The XPSC8 does not support gain or torque commands */
|
||||
break;
|
||||
|
||||
case SET_HIGH_LIMIT:
|
||||
Debug(1, "XPSC8_build_trans highlimit: socket=%d, posname=%s, "\
|
||||
case SET_HIGH_LIMIT: /*18 */
|
||||
Debug(10, "XPSC8_build_trans highlimit: socket=%d, posname=%s, "\
|
||||
"minlim=%f, steps=%f\n",\
|
||||
cntrl->socket, cntrl->positionername, cntrl->minlimit, steps);
|
||||
|
||||
status = PositionerUserTravelLimitsSet(cntrl->pollsocket,
|
||||
status = PositionerUserTravelLimitsSet(cntrl->devpollsocket,
|
||||
cntrl->positionername,
|
||||
cntrl->minlimit, steps);
|
||||
if (status != 0)
|
||||
@@ -420,7 +472,7 @@ STATIC RTN_STATUS XPSC8_build_trans(motor_cmnd command, double *parms, struct mo
|
||||
break;
|
||||
|
||||
case SET_LOW_LIMIT:
|
||||
status = PositionerUserTravelLimitsSet(cntrl->pollsocket,
|
||||
status = PositionerUserTravelLimitsSet(cntrl->devpollsocket,
|
||||
cntrl->positionername,
|
||||
steps, cntrl->maxlimit);
|
||||
if (status != 0)
|
||||
@@ -432,9 +484,8 @@ STATIC RTN_STATUS XPSC8_build_trans(motor_cmnd command, double *parms, struct mo
|
||||
rtnval = ERROR;
|
||||
}
|
||||
|
||||
done:
|
||||
/* Free the lock */
|
||||
epicsMutexUnlock(control->XPSC8Lock);
|
||||
Debug(1, "End Of Build_trans after Switch\n");
|
||||
Debug(10, "End Of Build_trans after Switch\n");
|
||||
return (rtnval);
|
||||
}
|
||||
|
||||
+323
-119
@@ -2,12 +2,21 @@
|
||||
* drvXPSC8.cc
|
||||
* Motor record driver level support for Newport XPSC8 motor controller.
|
||||
*
|
||||
* Original Author: Mark Rivers
|
||||
* Date: 10-May-2000
|
||||
* By Jon Kelly
|
||||
* 2005
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
|
||||
* 13th May 2005
|
||||
* The driver waits for a time specified in drvXPSC8.h: XPSC8_QUE_PAUSE when
|
||||
* a command is issued. It then performs all the motions specified in the lasped
|
||||
* time as a single syncronised motion. The pause is performed in drvXPSC8.cc:
|
||||
* send_mess.
|
||||
*
|
||||
* 30th June 2005
|
||||
* The driver is converted to asyn. The XPS some times returns an accel=zero in
|
||||
* readStatus so I have added a do loop to repeat the command until a non zero
|
||||
* value is returned
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -18,35 +27,31 @@
|
||||
#include <epicsString.h>
|
||||
#include <drvSup.h>
|
||||
#include "motor.h"
|
||||
#include "drvXPSC8.h"
|
||||
|
||||
#include "drvXPSC8.h"
|
||||
#include "xps_c8_driver.h"
|
||||
|
||||
#define STATIC static
|
||||
|
||||
/*----------------debugging-----------------*/
|
||||
#define DEBUG
|
||||
|
||||
#ifdef __GNUG__
|
||||
#ifdef DEBUG
|
||||
volatile int drvXPSC8Debug = 0;
|
||||
#define Debug(L, FMT, V...) { if(L <= drvXPSC8Debug) \
|
||||
{ printf("%s(%d):",__FILE__,__LINE__); \
|
||||
printf(FMT,##V); } }
|
||||
epicsExportAddress(int, drvXPSC8Debug);
|
||||
#define Debug(l, f, args...) { if(l<=drvXPSC8Debug) printf(f,## args); }
|
||||
#else
|
||||
#define Debug(l, f, args...)
|
||||
#endif
|
||||
#else
|
||||
#define Debug()
|
||||
#endif
|
||||
|
||||
|
||||
/* --- Local data. --- */
|
||||
volatile int drvXPSC8Debug = 6;
|
||||
/* --- Local data. --- */
|
||||
int XPSC8_num_cards = 0;
|
||||
|
||||
/* Local data required for every driver; see "motordrvComCode.h" */
|
||||
#include "motordrvComCode.h"
|
||||
|
||||
/* Why are not all the functions declared here? */
|
||||
|
||||
/*----------------functions-----------------*/
|
||||
STATIC int recv_mess(int, char *, int);
|
||||
@@ -136,7 +141,8 @@ static long init()
|
||||
{
|
||||
if (XPSC8_num_cards <= 0)
|
||||
{
|
||||
Debug(1, "init(): XPSC8 driver disabled. XPSC8etup() missing from startup script.\n");
|
||||
Debug(10, "init() XPSC8etup() missing from startup script.%i\n",
|
||||
XPSC8_num_cards);
|
||||
}
|
||||
return ((long) 0);
|
||||
}
|
||||
@@ -155,7 +161,7 @@ STATIC void start_status(int card)
|
||||
{
|
||||
int itera;
|
||||
|
||||
Debug(2, "start_status: card=%d total_cards=%d\n", card,total_cards);
|
||||
Debug(10, "start_status: card=%d total_cards=%d\n", card,total_cards);
|
||||
if (card >= 0) {
|
||||
readXPSC8Status(card);
|
||||
} else {
|
||||
@@ -173,63 +179,97 @@ STATIC void readXPSC8Status(int card)
|
||||
{
|
||||
struct XPSC8controller *control =
|
||||
(struct XPSC8controller *) motor_state[card]->DevicePrivate;
|
||||
struct XPSC8axis *cntrl;
|
||||
struct XPSC8axis *cntrl;
|
||||
int status,statuserror;
|
||||
int XPSC8_num_axes;
|
||||
int positioner,i; /* this = 1 because we are talking to 1 axis at a time */
|
||||
|
||||
int i;
|
||||
struct mess_node *nodeptr; /* These are to print the DONE flag */
|
||||
register struct mess_info *motor_info;
|
||||
msta_field statusflags;
|
||||
|
||||
positioner = 1;
|
||||
int groupsize, groupnumber; /* To be read in from struct */
|
||||
struct XPSC8group *groupcntrl; /*XPS group specific data */
|
||||
double position[XPSC8_NUM_CHANNELS]; /* To temp store position array */
|
||||
int axisingroup;
|
||||
int loop; /* Variables used when the XPS returns accel=zero */
|
||||
int max_loop = 10; /* This creates an error when we set the vel/accel */
|
||||
|
||||
msta_field statusflags;
|
||||
status = 0;
|
||||
statuserror = 0; /* this = 1 if an error occurs */
|
||||
XPSC8_num_axes = motor_state[card]->total_axis;
|
||||
|
||||
Debug(2, "XPSC8:readXPSC8Status card=%d num_axes=%d\n",card,XPSC8_num_axes);
|
||||
Debug(10, "XPSC8:readXPSC8Status card=%d num_axes=%d\n",card,XPSC8_num_axes);
|
||||
|
||||
/* Take a lock so that only 1 thread can be talking to the Neport XPSC8
|
||||
*/
|
||||
epicsMutexLock(control->XPSC8Lock);
|
||||
|
||||
for (i=0; i<XPSC8_num_axes;i++) {
|
||||
/*epicsThreadSleep(10);*/
|
||||
|
||||
for (i=0; i<XPSC8_num_axes;i++) {
|
||||
|
||||
motor_info = &(motor_state[card]->motor_info[i]); /*To print DONE flag*/
|
||||
nodeptr = motor_info->motor_motion;
|
||||
statusflags.All = motor_info->status.All;
|
||||
|
||||
Debug(9, "XPSC8:readXPSC8Status RA_DONE=%d, RA_MOVING=%d, "\
|
||||
"RA_PROBLEM=%d\n",\
|
||||
statusflags.Bits.RA_DONE, statusflags.Bits.RA_MOVING,\
|
||||
Debug(10, "XPSC8:readXPSC8Status RA_DONE=%d, RA_MOVING=%d, "
|
||||
"RA_PROBLEM=%d\n",
|
||||
statusflags.Bits.RA_DONE, statusflags.Bits.RA_MOVING,
|
||||
statusflags.Bits.RA_PROBLEM);
|
||||
|
||||
control = (struct XPSC8controller *) motor_state[card]->DevicePrivate;
|
||||
cntrl = (struct XPSC8axis *)&control->axis[i];
|
||||
|
||||
Debug(2, "XPSC8:readXPSC8Status card=%d axis=%d sock=%d gp=%s\n",card,i,\
|
||||
cntrl->socket,cntrl->groupname);
|
||||
|
||||
/* Where I have used "&" the func requires an pointer */
|
||||
status = GroupStatusGet(cntrl->pollsocket, cntrl->groupname,
|
||||
&cntrl->groupstatus);
|
||||
if (status != 0) {
|
||||
printf(" Error performing GroupStatusGet status=%d\n", status);
|
||||
axisingroup = cntrl->axisingroup;
|
||||
if ((axisingroup < 0) || (axisingroup > 7) ) {
|
||||
printf(" Error Axis In Group Out Of Range status=%d\n", status);
|
||||
statuserror =1;
|
||||
}
|
||||
|
||||
status = PositionerSGammaParametersGet(cntrl->pollsocket,
|
||||
groupnumber = cntrl->groupnumber;
|
||||
if ((groupnumber < 0) || (groupnumber > 7) ) {
|
||||
printf(" Error Group Number Out Of Range status=%d\n", status);
|
||||
statuserror =1;
|
||||
}
|
||||
groupcntrl = (struct XPSC8group *)&control->group[groupnumber];
|
||||
|
||||
groupsize = groupcntrl->groupsize;
|
||||
if ((groupsize < 1) || (groupsize > 8) ) {
|
||||
printf(" Error Group Size Out Of Range status=%d\n", status);
|
||||
statuserror =1;
|
||||
}
|
||||
Debug(10, "XPSC8:readXPSC8Status groupsize=%i groupnumber=%i\n",
|
||||
groupsize,groupnumber);
|
||||
Debug(10, "XPSC8:readXPSC8Status card=%d axis=%d sock=%d gp=%s\n",card,i,
|
||||
cntrl->socket,cntrl->groupname);
|
||||
|
||||
status = GroupStatusGet(cntrl->pollsocket, cntrl->groupname,
|
||||
&cntrl->groupstatus);
|
||||
if (status != 0) {
|
||||
printf(" ReadStatus Error performing GroupStatusGet status=%d\n", status);
|
||||
statuserror =1;
|
||||
}
|
||||
|
||||
/* This do loop is required because some times the XPS returns accel=zero*/
|
||||
loop = 0;
|
||||
do {
|
||||
status = PositionerSGammaParametersGet(cntrl->pollsocket,
|
||||
cntrl->positionername,
|
||||
&cntrl->velocity,
|
||||
&cntrl->accel,
|
||||
&cntrl->minjerktime,
|
||||
&cntrl->maxjerktime);
|
||||
if (status != 0) {
|
||||
loop++;
|
||||
}
|
||||
while ((cntrl->accel < 0.00001) && (loop < max_loop));
|
||||
|
||||
if (status != 0) {
|
||||
printf(" Error performing PositionerSGammaParametersGet\n");
|
||||
statuserror =1;
|
||||
}
|
||||
/* Is the XPS sending the wrong accel and vel data? */
|
||||
if (cntrl->accel <= 0.00001 )
|
||||
printf("drvXPSC8 Error PositionerSGammaParametersGet accel=%f vel=%f loop=%i\n",
|
||||
cntrl->accel,cntrl->velocity,loop);
|
||||
|
||||
/* The jog function is not enabled*/
|
||||
/*
|
||||
/* Not implimented due to lack of epics motor commands
|
||||
status = GroupJogParametersGet(cntrl->pollsocket,
|
||||
cntrl->groupname,
|
||||
positioner,
|
||||
@@ -241,35 +281,40 @@ STATIC void readXPSC8Status(int card)
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
status = GroupPositionCurrentGet(cntrl->pollsocket,
|
||||
cntrl->positionername,
|
||||
positioner,
|
||||
&cntrl->currentposition[1]);
|
||||
cntrl->groupname,
|
||||
groupsize,
|
||||
position); /* Array! */
|
||||
if (status != 0) {
|
||||
printf(" Error performing GroupPositionCurrentGet\n");
|
||||
statuserror =1;
|
||||
}
|
||||
} else {
|
||||
/* Place the position data into the axis structure */
|
||||
cntrl->currentposition = position[axisingroup];}
|
||||
|
||||
|
||||
status = GroupPositionTargetGet(cntrl->pollsocket,
|
||||
cntrl->positionername,
|
||||
positioner,
|
||||
&cntrl->targetposition[1]);
|
||||
cntrl->groupname,
|
||||
groupsize,
|
||||
position); /* Re use Array! */
|
||||
if (status != 0) {
|
||||
printf(" Error performing GroupPositionTargetGet\n");
|
||||
statuserror =1;
|
||||
}
|
||||
} else {
|
||||
/* Place the position data into the axis structure */
|
||||
cntrl->targetposition = position[axisingroup];}
|
||||
|
||||
|
||||
status = GroupPositionSetpointGet(cntrl->pollsocket,
|
||||
cntrl->positionername,
|
||||
positioner,
|
||||
&cntrl->setpointposition[1]);
|
||||
cntrl->groupname,
|
||||
groupsize,
|
||||
position); /* Re-re use Array! */
|
||||
if (status != 0) {
|
||||
printf(" Error performing GroupPositionSetpointGet\n");
|
||||
statuserror =1;
|
||||
}
|
||||
} else {
|
||||
/* Place the position data into the axis structure */
|
||||
cntrl->setpointposition = position[axisingroup];}
|
||||
|
||||
status = PositionerErrorGet(cntrl->pollsocket,
|
||||
cntrl->positionername,
|
||||
@@ -291,7 +336,7 @@ STATIC void readXPSC8Status(int card)
|
||||
statuserror =1;
|
||||
}
|
||||
|
||||
Debug(11, "readXPSC8Status, socket=%d, groupname=%s, minlim=%f\n",\
|
||||
Debug(10, "readXPSC8Status, socket=%d, groupname=%s, minlim=%f\n",
|
||||
cntrl->socket,cntrl->groupname,cntrl->minlimit);
|
||||
|
||||
if (status == 1)
|
||||
@@ -318,7 +363,7 @@ STATIC int set_status(int card, int signal)
|
||||
|
||||
int positionererror;
|
||||
int rtn_state, groupstatus;
|
||||
double motorData, pos,resolution;
|
||||
double motorData,pos,target,resolution;
|
||||
bool ls_active = false;
|
||||
msta_field status;
|
||||
|
||||
@@ -332,32 +377,28 @@ STATIC int set_status(int card, int signal)
|
||||
|
||||
/* Lock access to global data structure */
|
||||
epicsMutexLock(control->XPSC8Lock);
|
||||
|
||||
Debug(2, "XPSC8:set_status entry: card=%d, signal=%d\n", card, signal);
|
||||
|
||||
Debug(10, "XPSC8:set_status entry: card=%d, signal=%d\n", card, signal);
|
||||
|
||||
/* Parse the error and position values read within the readXPSC8Status
|
||||
function */
|
||||
positionererror = cntrl->positionererror;
|
||||
pos = cntrl->currentposition[1];
|
||||
pos = cntrl->currentposition;
|
||||
target = cntrl->targetposition;
|
||||
groupstatus = cntrl->groupstatus;
|
||||
Debug(2, "XPSC8:set_status entry: positionererror=%d, pos=%f,"\
|
||||
" resolution=%f\n",\
|
||||
positionererror, pos, resolution);
|
||||
Debug(11, "XPSC8:set_status entry: pos0=%f, pos1=%f\n",\
|
||||
cntrl->currentposition[0], cntrl->currentposition[1]);
|
||||
|
||||
if (cntrl->velocity >= 0)
|
||||
/*if (cntrl->velocity >= 0)
|
||||
status.Bits.RA_DIRECTION = 1;
|
||||
else
|
||||
status.Bits.RA_DIRECTION=0;
|
||||
status.Bits.RA_DIRECTION=0;*/
|
||||
|
||||
if (groupstatus > 9 && groupstatus < 20) {
|
||||
/* These states mean ready from move/home/jog etc*/
|
||||
status.Bits.RA_DONE=1; /* 1 means cd ready */
|
||||
Debug(2, "Set_status: Done -->groupstatus=%d\n", groupstatus);
|
||||
Debug(10, "Set_status: Done -->groupstatus=%d\n", groupstatus);
|
||||
} else {
|
||||
status.Bits.RA_DONE=0;
|
||||
Debug(2, "Set_status: Not Done -->groupstatus=%d\n", groupstatus);
|
||||
Debug(10, "Set_status: Not Done -->groupstatus=%d\n", groupstatus);
|
||||
}
|
||||
status.Bits.RA_PLUS_LS=0;
|
||||
status.Bits.RA_MINUS_LS=0;
|
||||
@@ -367,11 +408,20 @@ STATIC int set_status(int card, int signal)
|
||||
if (groupstatus > 42 && groupstatus < 49) {
|
||||
/* These states mean it is moving/homeing/jogging etc*/
|
||||
cntrl->moving = 1;
|
||||
|
||||
if (target >= pos) {
|
||||
status.Bits.RA_DIRECTION = 1;
|
||||
Debug(2, "Set_status: Positive Direction\n");
|
||||
} else {
|
||||
status.Bits.RA_DIRECTION = 0;
|
||||
Debug(2, "Set_status: Negative Direction\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* These are hard limits */
|
||||
if (positionererror & XPSC8_END_OF_RUN_MINUS ) {
|
||||
/* I am unsure of the use of & !!*/
|
||||
|
||||
status.Bits.RA_MINUS_LS=1; /* defined in drvXPSC8.h */
|
||||
ls_active = true;
|
||||
}
|
||||
@@ -410,10 +460,13 @@ STATIC int set_status(int card, int signal)
|
||||
|
||||
status.Bits.RA_PROBLEM=0;
|
||||
|
||||
Debug(11, "--------above inisialisation test \n");
|
||||
if (groupstatus < 9 || (groupstatus > 19 && groupstatus < 43)) {
|
||||
/* not initialized or disabled*/
|
||||
/* Set the Hard limits To show that it is unable to move */
|
||||
/* not initialized, homed or disabled */
|
||||
if ((groupstatus >= 0 && groupstatus < 10) || (groupstatus >= 20 && groupstatus < 43)) {
|
||||
|
||||
/* Set the Hard limits To show that it is unable to move. This means when you
|
||||
home the motor record will only let you home away from the current shown
|
||||
limit */
|
||||
|
||||
status.Bits.RA_MINUS_LS=1;
|
||||
status.Bits.RA_PLUS_LS=1;
|
||||
status.Bits.RA_PROBLEM=1; /*This variable is to do with polling*/
|
||||
@@ -422,16 +475,10 @@ STATIC int set_status(int card, int signal)
|
||||
}
|
||||
|
||||
motor_info->velocity = (int)cntrl->velocity;
|
||||
/* I don't know what this is used for */
|
||||
|
||||
/* if (status.Bits.RA_DIRECTION==0)
|
||||
motor_info->velocity *= -1;*/
|
||||
|
||||
rtn_state = (!motor_info->no_motion_count || ls_active == true ||
|
||||
(status.Bits.RA_DONE | status.Bits.RA_PROBLEM)) ? 1 : 0;
|
||||
|
||||
Debug(1, "--------set_status rtn_state=%d \n",rtn_state);
|
||||
|
||||
|
||||
if (cntrl->status == XPSC8_COMM_ERR)
|
||||
/* I defined this to be -1! */
|
||||
@@ -442,6 +489,10 @@ STATIC int set_status(int card, int signal)
|
||||
/* Free the lock */
|
||||
epicsMutexUnlock(control->XPSC8Lock);
|
||||
motor_info->status.All = status.All;
|
||||
|
||||
Debug(12, "status.Bits.RA_PROBLEM: %i status.Bits.RA_DONE: %i",
|
||||
status.Bits.RA_PROBLEM,status.Bits.RA_DONE);
|
||||
|
||||
return(rtn_state);
|
||||
}
|
||||
|
||||
@@ -450,9 +501,135 @@ STATIC int set_status(int card, int signal)
|
||||
/* send a message to the XPS board */
|
||||
/* send_mess() */
|
||||
/*****************************************************/
|
||||
STATIC RTN_STATUS send_mess(int card, char const *com, char *name)
|
||||
STATIC RTN_STATUS send_mess(int card, char const *com, char *c)
|
||||
{
|
||||
/* This is a no-op for the XPS, but must be present */
|
||||
struct XPSC8controller *control;
|
||||
struct XPSC8axis *cntrl;
|
||||
struct XPSC8group *groupcntrl; /*XPS group specific data */
|
||||
int groupnumber, groupsize;
|
||||
int axisingroup, groupstatus;
|
||||
int status;
|
||||
int waitcount;
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
if (motor_state[0] == NULL)
|
||||
return(ERROR);
|
||||
|
||||
int signal = -1; /* This is incremented up to 0 further down */
|
||||
|
||||
control = (struct XPSC8controller *) motor_state[card]->DevicePrivate;
|
||||
epicsMutexLock(control->XPSC8Lock);
|
||||
/*control = (struct XPSC8controller *) brdptr->DevicePrivate;*/
|
||||
|
||||
/* Loop until you find the axis/group with a move cued up! */
|
||||
do
|
||||
{
|
||||
++signal;
|
||||
cntrl = (struct XPSC8axis *)&control->axis[signal];
|
||||
groupstatus = cntrl->groupstatus; /* From XPS controller */
|
||||
axisingroup = cntrl->axisingroup; /* Pull in group info */
|
||||
groupnumber = cntrl->groupnumber;
|
||||
groupcntrl = (struct XPSC8group *)&control->group[groupnumber];
|
||||
groupsize = groupcntrl->groupsize; /* Number of motors in group */
|
||||
}
|
||||
while ((groupcntrl->cuesize == 0) && (signal < (XPSC8_NUM_CHANNELS-1)));
|
||||
|
||||
Debug(5,"Send_mess After do loop axisingp=%d, groupstatus=%i socket=%i cue=%i flag=%i \n",
|
||||
axisingroup,groupstatus,cntrl->socket,groupcntrl->cuesize,groupcntrl->cueflag);
|
||||
|
||||
if((signal == (XPSC8_NUM_CHANNELS-1)) && (groupcntrl->cuesize == 0))
|
||||
goto send_mess_end; /*No moves to perform */
|
||||
|
||||
status = GroupStatusGet(cntrl->pollsocket, cntrl->groupname,
|
||||
&cntrl->groupstatus); /* Update Status */
|
||||
groupstatus = cntrl->groupstatus;
|
||||
|
||||
if (status != 0)
|
||||
printf(" SendMess Error performing GroupStatusGet status=%d\n", status);
|
||||
|
||||
if (groupstatus > 9 && groupstatus < 20){ /* Ready from move */
|
||||
|
||||
if (groupcntrl->cueflag == 1) /* First motor called */
|
||||
{
|
||||
|
||||
epicsMutexUnlock(control->XPSC8Lock);/* Free up for the other motors*/
|
||||
epicsThreadSleep(XPSC8_QUE_PAUSE_READY); /* Wait for other motors */
|
||||
epicsMutexLock(control->XPSC8Lock);
|
||||
groupcntrl->cuesize = 0; /* Reset cue */
|
||||
groupcntrl->cueflag = 0;
|
||||
|
||||
status = GroupMoveAbsolute(cntrl->socket,
|
||||
cntrl->groupname,
|
||||
groupsize,
|
||||
groupcntrl->positionarray); /*Pointer to array*/
|
||||
|
||||
if (status != 0 && status != -27)
|
||||
printf(" Error performing GroupMoveAbsolute %i\n",status);
|
||||
/* Error -27 is caused when the motor record changes dir i.e.
|
||||
when it aborts a move!*/
|
||||
|
||||
Debug(5,"Send_mess After move in Send_mess axisingp=%d, groupstatus=%i socket=%i psocket=%i\n",
|
||||
cntrl->axisingroup,groupstatus,cntrl->socket,cntrl->pollsocket);
|
||||
goto send_mess_end;
|
||||
}
|
||||
}
|
||||
|
||||
if (groupstatus > 42 && groupstatus < 47){ /* Moveing/Homing*/
|
||||
if (groupcntrl->cuesize > 1)
|
||||
Debug(1,"Send_mess**Added move to the cue group busy ie xps moving***\n");
|
||||
if (groupcntrl->cueflag == 1){ /* First motor called */
|
||||
groupcntrl->cueflag = 0;
|
||||
waitcount = 0;
|
||||
while((groupstatus > 42 && groupstatus < 49) &&
|
||||
(waitcount <= XPSC8_MAX_WAIT)){
|
||||
epicsMutexUnlock(control->XPSC8Lock);/* Free up for the others*/
|
||||
epicsThreadSleep(XPSC8_QUE_PAUSE_MOVING); /* Wait for end of motion */
|
||||
epicsMutexLock(control->XPSC8Lock);
|
||||
++waitcount;
|
||||
status = GroupStatusGet(cntrl->pollsocket, cntrl->groupname,
|
||||
&cntrl->groupstatus);
|
||||
if (status != 0)
|
||||
printf("Error performing GroupStatusGet Bottom Send_mess status=%d\n", status);
|
||||
|
||||
groupstatus = cntrl->groupstatus; /* Update groupstatus */
|
||||
|
||||
}
|
||||
|
||||
if (waitcount >= XPSC8_MAX_WAIT){
|
||||
printf(" Error Motor Cue timed out \n");
|
||||
groupcntrl->cuesize = 0; /* Reset cue */
|
||||
groupcntrl->cueflag = 0;
|
||||
/* Re set the cue array to current positions */
|
||||
status = GroupPositionCurrentGet(cntrl->pollsocket,
|
||||
cntrl->groupname,
|
||||
groupsize,
|
||||
groupcntrl->positionarray);
|
||||
if (status != 0)
|
||||
printf(" Error performing GroupPositionCurrentGet\n");
|
||||
goto send_mess_end;
|
||||
}
|
||||
|
||||
if (groupstatus > 9 && groupstatus < 20){ /* Ready from move */
|
||||
groupcntrl->cuesize = 0; /* Reset cue */
|
||||
groupcntrl->cueflag = 0;
|
||||
status = GroupMoveAbsolute(cntrl->socket,
|
||||
cntrl->groupname,
|
||||
groupsize,
|
||||
groupcntrl->positionarray); /*Pointer to array*/
|
||||
|
||||
/* Error -27 is caused when the motor record changes dir i.e.
|
||||
when it aborts a move!*/
|
||||
if (status != 0 && status != -27 )
|
||||
printf(" Error performing GroupMoveAbsolute %i\n",status);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
send_mess_end:
|
||||
epicsMutexUnlock(control->XPSC8Lock);
|
||||
return (OK);
|
||||
}
|
||||
|
||||
@@ -476,19 +653,19 @@ STATIC int recv_mess(int card, char *com, int flag)
|
||||
/* XPSC8Setup() */
|
||||
/*****************************************************/
|
||||
RTN_STATUS XPSC8Setup(int num_cards, /* number of controllers in system. */
|
||||
int scan_rate) /* I think this is for the epicsthread */
|
||||
int scan_rate) /* Poll rate */
|
||||
{
|
||||
Debug(1, "XPSC8Setup: Controllers=%d Scan Rate=%d\n",num_cards,scan_rate);
|
||||
Debug(10, "XPSC8Setup: Controllers=%d Scan Rate=%d\n",num_cards,scan_rate);
|
||||
int itera;
|
||||
if (num_cards > XPSC8_NUM_CHANNELS)
|
||||
printf(" Error in setup too many channels\n");
|
||||
if (num_cards > XPSC8_MAX_CONTROLLERS)
|
||||
printf(" Error in setup too many controllers\n");
|
||||
|
||||
if (num_cards < 1)
|
||||
XPSC8_num_cards = 1;
|
||||
else
|
||||
XPSC8_num_cards = num_cards;
|
||||
|
||||
/* Set motor polling task rate */
|
||||
/* Set motor polling task rate */
|
||||
if (scan_rate >= 1 && scan_rate <= 60)
|
||||
targs.motor_scan_rate = scan_rate;
|
||||
else
|
||||
@@ -511,23 +688,23 @@ RTN_STATUS XPSC8Setup(int num_cards, /* number of controllers in system. */
|
||||
/* XPSC8Config() */
|
||||
/*****************************************************/
|
||||
RTN_STATUS XPSC8Config(int card, /* Controller number */
|
||||
const char *ip, /* XPS IP address*/
|
||||
int port, /* This may be 5001 */
|
||||
int totalaxes) /* Number of axis/positioners used*/
|
||||
const char *ip, /* XPS IP address*/
|
||||
int port, /* This may be 5001 */
|
||||
int totalaxes) /* Number of axis/positioners used*/
|
||||
|
||||
{
|
||||
struct XPSC8controller *control;
|
||||
struct XPSC8axis *cntrl;
|
||||
int statuserror, status, socket, pollsocket, axis;
|
||||
int statuserror, status, socket, pollsocket, devpollsocket, axis;
|
||||
char *ipchar, List[1000];
|
||||
statuserror = 0;
|
||||
status = 0;
|
||||
ipchar = (char *)ip;
|
||||
socket = 0;
|
||||
pollsocket = 0;
|
||||
devpollsocket = 0;
|
||||
|
||||
|
||||
Debug(1, "XPSC8Config: IP=%s, Port=%d, Card=%d, totalaxes=%d\n",\
|
||||
Debug(10, "XPSC8Config: IP=%s, Port=%d, Card=%d, totalaxes=%d\n",
|
||||
ipchar, port, card, totalaxes);
|
||||
|
||||
if (totalaxes < 0 || totalaxes > XPSC8_NUM_CHANNELS) {return (ERROR);}
|
||||
@@ -539,9 +716,22 @@ RTN_STATUS XPSC8Config(int card, /* Controller number */
|
||||
control = (struct XPSC8controller *) motor_state[card]->DevicePrivate;
|
||||
|
||||
motor_state[card]->total_axis = totalaxes;
|
||||
|
||||
pollsocket = TCP_ConnectToServer(ipchar,port,TIMEOUT);
|
||||
|
||||
if (pollsocket < 0) {
|
||||
printf(" Error TCP_ConnectToServer for pollsocket\n");
|
||||
statuserror =1;
|
||||
}
|
||||
|
||||
devpollsocket = TCP_ConnectToServer(ipchar,port,TIMEOUT);
|
||||
|
||||
|
||||
if (devpollsocket < 0) {
|
||||
printf(" Error TCP_ConnectToServer for pollsocket\n");
|
||||
statuserror =1;
|
||||
}
|
||||
|
||||
|
||||
for (axis=0; axis<totalaxes; axis++) {
|
||||
socket = TCP_ConnectToServer(ipchar,port,TIMEOUT);
|
||||
/* Find a socket number */
|
||||
@@ -549,24 +739,18 @@ RTN_STATUS XPSC8Config(int card, /* Controller number */
|
||||
printf(" Error TCP_ConnectToServer for move-socket\n");
|
||||
statuserror =1;
|
||||
}
|
||||
|
||||
pollsocket = TCP_ConnectToServer(ipchar,port,TIMEOUT);
|
||||
/* Find a socket number */
|
||||
if (pollsocket < 0) {
|
||||
printf(" Error TCP_ConnectToServer for pollsocket\n");
|
||||
statuserror =1;
|
||||
}
|
||||
|
||||
cntrl = (struct XPSC8axis *)&control->axis[axis];
|
||||
Debug(11, "XPSC8Config: axis=%d, cntrl=%p\n", axis, cntrl);
|
||||
|
||||
cntrl->pollsocket = pollsocket;
|
||||
cntrl->devpollsocket = devpollsocket;
|
||||
cntrl->socket = socket;
|
||||
cntrl->ip = epicsStrDup(ip);
|
||||
|
||||
|
||||
Debug(1, "XPSC8Config: Socket=%d, PollSock=%d, ip=%s, port=%d,"\
|
||||
" axis=%d controller=%d\n",\
|
||||
Debug(10, "XPSC8Config: Socket=%d, PollSock=%d, ip=%s, port=%d,"
|
||||
" axis=%d controller=%d\n",
|
||||
cntrl->socket,cntrl->pollsocket,ip,port,axis,card);
|
||||
}
|
||||
Debug(11, "XPSC8Config: Above OjectsListGet\n");
|
||||
@@ -587,21 +771,29 @@ RTN_STATUS XPSC8Config(int card, /* Controller number */
|
||||
/*********************************************************/
|
||||
RTN_STATUS XPSC8NameConfig(int card, /*specify which controller 0-up*/
|
||||
int axis, /*axis number 0-7*/
|
||||
int groupnumber, /* 0-7*/
|
||||
int groupsize, /* 1-8*/
|
||||
int axisingroup, /* eg 4th axis in group 2 */
|
||||
const char *gpname, /*group name e.g. Diffractometer */
|
||||
const char *posname) /*positioner name e.g. Diffractometer.Phi*/
|
||||
|
||||
{
|
||||
struct XPSC8controller *control;
|
||||
struct XPSC8axis *cntrl;
|
||||
struct XPSC8group *groupcntrl; /*XPS group specific data */
|
||||
|
||||
Debug(1, "XPSC8NameConfig: card=%d axis=%d, group=%s, positioner=%s\n",\
|
||||
Debug(10, "XPSC8NameConfig: card=%d axis=%d, group=%s, positioner=%s\n",
|
||||
card, axis, gpname, posname);
|
||||
|
||||
control = (struct XPSC8controller *) motor_state[card]->DevicePrivate;
|
||||
cntrl = (struct XPSC8axis *)&control->axis[axis];
|
||||
|
||||
groupcntrl = (struct XPSC8group *)&control->group[groupnumber];
|
||||
|
||||
cntrl->groupname = epicsStrDup(gpname);
|
||||
cntrl->positionername = epicsStrDup(posname);
|
||||
cntrl->groupnumber = groupnumber;
|
||||
cntrl->axisingroup = axisingroup;
|
||||
groupcntrl->groupsize = groupsize;
|
||||
|
||||
return (OK);
|
||||
}
|
||||
@@ -617,25 +809,26 @@ STATIC int motor_init()
|
||||
struct controller *brdptr;
|
||||
struct XPSC8controller *control;
|
||||
struct XPSC8axis *cntrl;
|
||||
struct XPSC8group *groupcntrl; /*XPS group specific data */
|
||||
int card_index, motor_index;
|
||||
int status, totalaxes;
|
||||
|
||||
int status = 0, totalaxes;
|
||||
int i,counter; /* Used in for loops */
|
||||
bool errind;
|
||||
|
||||
initialized = true; /* Indicate that driver is initialized. */
|
||||
|
||||
/* Check for setup */
|
||||
Debug(1, "XPSC8:motor_init: num_cards=%d\n", XPSC8_num_cards);
|
||||
Debug(10, "XPSC8:motor_init: num_cards=%d\n", XPSC8_num_cards);
|
||||
if (XPSC8_num_cards <= 0){
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
for (card_index = 0; card_index < XPSC8_num_cards; card_index++) {
|
||||
totalaxes = motor_state[card_index]->total_axis;
|
||||
Debug(5, "XPSC8:motor_init: Card init loop card_index=%d\n",card_index);
|
||||
Debug(10, "XPSC8:motor_init: Card init loop card_index=%d\n",card_index);
|
||||
brdptr = motor_state[card_index];
|
||||
total_cards = card_index + 1;
|
||||
Debug(5, "XPSC8:motor_init: Above control def card_index=%d\n",\
|
||||
Debug(10, "XPSC8:motor_init: Above control def card_index=%d\n",
|
||||
card_index);
|
||||
control = (struct XPSC8controller *) brdptr->DevicePrivate;
|
||||
|
||||
@@ -645,12 +838,30 @@ STATIC int motor_init()
|
||||
control->XPSC8Lock = epicsMutexCreate();
|
||||
errind = false;
|
||||
|
||||
/* just to test status, 0 means the call worked*/
|
||||
status = GroupStatusGet(cntrl->socket,cntrl->groupname,
|
||||
&cntrl->groupstatus);
|
||||
/* Just to test status, 0 means the call worked */
|
||||
counter = 0;
|
||||
/* wait incase the socket is busy */
|
||||
while (status < 0 && counter < (TIMEOUT*10)) {
|
||||
status = GroupStatusGet(cntrl->pollsocket,cntrl->groupname,
|
||||
&cntrl->groupstatus);
|
||||
counter++;
|
||||
epicsThreadSleep(0.1);
|
||||
}
|
||||
|
||||
if (status !=0) errind = true;
|
||||
Debug(5, "XPSC8:motor_init: card_index=%d, errind=%d\n",\
|
||||
Debug(10, "XPSC8:motor_init: card_index=%d, errind=%d\n",
|
||||
card_index, errind);
|
||||
Debug(10, "XPSC8:motor_init: psocket %i, gpname %s, gpstatus %i status %i\n",
|
||||
cntrl->pollsocket,cntrl->groupname,cntrl->groupstatus,status);
|
||||
|
||||
/* Set the XPSC8group struct variables to zero */
|
||||
|
||||
for(i=0 ; i< XPSC8_NUM_CHANNELS ; ++i){
|
||||
groupcntrl = (struct XPSC8group *)&control->group[i];
|
||||
groupcntrl->cuesize = 0;
|
||||
groupcntrl->cueflag = 0;
|
||||
}
|
||||
|
||||
|
||||
if (errind == false) {
|
||||
brdptr->localaddr = (char *) NULL;
|
||||
@@ -668,7 +879,6 @@ STATIC int motor_init()
|
||||
start_status(card_index);
|
||||
/*Read in all the parameters vel/accel ect */
|
||||
|
||||
Debug(5, "XPSC8:motor_init: called start_status OK\n");
|
||||
for (motor_index = 0; motor_index < totalaxes; motor_index++) {
|
||||
struct mess_info *motor_info = &brdptr->motor_info[motor_index];
|
||||
motor_info->status.All = 0;
|
||||
@@ -676,15 +886,11 @@ STATIC int motor_init()
|
||||
motor_info->encoder_position = 0;
|
||||
motor_info->position = 0;
|
||||
/* Read status of each motor */
|
||||
Debug(5, " XPSC8:motor_init: calling set_status for motor %d\n",\
|
||||
motor_index);
|
||||
set_status(card_index, motor_index);
|
||||
}
|
||||
}
|
||||
else
|
||||
motor_state[card_index] = (struct controller *) NULL;
|
||||
}
|
||||
Debug(5, "XPSC8:motor_init: done with start_status and set_status\n");
|
||||
|
||||
any_motor_in_motion = 0;
|
||||
|
||||
@@ -693,8 +899,6 @@ STATIC int motor_init()
|
||||
|
||||
free_list.head = (struct mess_node *) NULL;
|
||||
free_list.tail = (struct mess_node *) NULL;
|
||||
|
||||
Debug(5, "XPSC8:motor_init: spawning XPSC8_motor task\n");
|
||||
|
||||
epicsThreadCreate((char *) "XPSC8_motor", epicsThreadPriorityMedium,
|
||||
epicsThreadGetStackSize(epicsThreadStackMedium),
|
||||
|
||||
@@ -13,19 +13,29 @@
|
||||
|
||||
#define XPSC8_END_OF_RUN_MINUS 0x80000100
|
||||
#define XPSC8_END_OF_RUN_PLUS 0x80000200
|
||||
#define XPSC8_NUM_CHANNELS 8
|
||||
#define XPSC8_NUM_CHANNELS 8 /* Number of axes in one XPS */
|
||||
#define XPSC8_MAX_CONTROLLERS 2 /* Set to diffractometer number*/
|
||||
#define XPSC8_COMM_ERR -1
|
||||
#define TIMEOUT 1
|
||||
#define XPSC8_MAX_WAIT 120 /* Cue timeout limit 1min 120*0.5 sec*/
|
||||
#define XPSC8_QUE_PAUSE_READY 0.2 /* Time the driver waits for further
|
||||
comands to group together before
|
||||
performing a move from stationary*/
|
||||
#define XPSC8_QUE_PAUSE_MOVING 0.1 /* Poll time the driver waits to check if
|
||||
the motor is still moving after a
|
||||
cue has been started*/
|
||||
|
||||
#define TIMEOUT 0.5 /* TCP/IP timeout */
|
||||
#define NOTREF 42
|
||||
|
||||
/*------ This defines the XPSC8 specific property structure */
|
||||
struct XPSC8axis
|
||||
{
|
||||
int socket;
|
||||
int pollsocket; /* This is the same for all motors to poll!*/
|
||||
double currentposition[1]; /* the XPS commands want an array */
|
||||
double setpointposition[1];
|
||||
double targetposition[1];
|
||||
int socket; /* Each Axis has its own drive socket */
|
||||
int pollsocket; /*socket for drvXPSC8 thread polling */
|
||||
int devpollsocket; /*socket for devXPSC8 thread polling */
|
||||
double currentposition; /* the XPS commands want an array */
|
||||
double setpointposition; /* but the values are then assigned */
|
||||
double targetposition; /* to these variables. */
|
||||
double velocity;
|
||||
double accel;
|
||||
double minjerktime; /* for the SGamma function */
|
||||
@@ -35,7 +45,6 @@ struct XPSC8axis
|
||||
double maxlimit;
|
||||
double minlimit;
|
||||
double resolution;
|
||||
|
||||
char *ip;
|
||||
char *positionername; /* read in using NameConfig*/
|
||||
char *groupname;
|
||||
@@ -45,11 +54,21 @@ struct XPSC8axis
|
||||
int status; /* Included to fit in with the camac driver template
|
||||
Not a value from the XPS controller!*/
|
||||
|
||||
int groupnumber; /* (0-7) This axis is a member of which group?*/
|
||||
int axisingroup; /* (0-7) eg the 4th axis in the 2nd group */
|
||||
};
|
||||
|
||||
struct XPSC8group{ /* This structure is for each group not axis */
|
||||
double positionarray[XPSC8_NUM_CHANNELS]; /* Used to store cued moves */
|
||||
int groupsize; /* (1-8) Number of members of a group */
|
||||
int cuesize; /* Number of axes in the cue */
|
||||
int cueflag; /* 1 = move/wait loop needs to be started */
|
||||
};
|
||||
|
||||
struct XPSC8controller{
|
||||
epicsMutexId XPSC8Lock;
|
||||
struct XPSC8axis axis[XPSC8_NUM_CHANNELS];
|
||||
struct XPSC8axis axis[XPSC8_NUM_CHANNELS]; /* maximum of 8 axes */
|
||||
struct XPSC8group group[XPSC8_NUM_CHANNELS]; /* maximum of 8 groups */
|
||||
};
|
||||
|
||||
/* Global function, used by both driver and device support */
|
||||
|
||||
Reference in New Issue
Block a user