Deleted old Ensemble device driver

This commit is contained in:
Ron Sluiter
2011-01-07 16:06:01 +00:00
parent 2ceabc5693
commit 2ec4e3b57a
6 changed files with 0 additions and 1217 deletions
-1
View File
@@ -43,7 +43,6 @@ HeadURL: $URL$
#include "motor.h"
#include "motordrvCom.h"
#include "drvEnsembleAsyn.h"
#include "drvEnsemble.h"
#include "drvSoloist.h"
-1
View File
@@ -11,7 +11,6 @@ LIBRARY_IOC = Aerotech
# Aerotech driver support.
SRCS += AerotechRegister.cc
SRCS += devEnsemble.cc drvEnsemble.cc
SRCS += devSoloist.cc drvSoloist.cc
SRCS += drvEnsembleAsyn.cc
-7
View File
@@ -1,13 +1,6 @@
# Aerotech Ensemble Driver support.
device(motor,VME_IO,devEnsemble,"Ensemble")
driver(drvEnsemble)
# Aerotech Soloist Driver support
device(motor,VME_IO,devSoloist,"Soloist")
driver(drvSoloist)
# Aerotech Ensemble asynMotor support
driver(motorEnsemble)
registrar(AerotechRegister)
-376
View File
@@ -1,376 +0,0 @@
/*
* FILENAME... devEnsemble.cc
* USAGE... Motor record device level support for Aerotech Ensemble.
*
* Version: $Revision$
* Modified By: $Author$
* Last Modified: $Date$
* HeadURL: $URL$
*/
/*
* Original Author: Chad Weimer
* Date: 04/04/08
* Current Author: Chad Weimer
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .01 04-01-08 caw initialized from devMM4000.cc (Newport)
* .02 11-20-08 rls - support homing in both directions.
* - disable LOAD_POS until ABORT command fixed.
* - SET_VELOCITY sets both default speed and home feedrate.
* .03 01-22-09 rls - enable LOAD_POS; ABORT command fixed with Ensemble
* firmware 2.5.2.
* .04 05-01-09 rls - Fix for jog velocity not adjusted by
* cntrl->drive_resolution.
* .05 03-02-10 rls - removed setting controller's soft limits; see README
* - Depreciated version; use the asyn motor version.
*/
#include <string.h>
#include <math.h>
#include "motorRecord.h"
#include "motor.h"
#include "motordevCom.h"
#include "drvEnsemble.h"
#include "epicsExport.h"
extern struct driver_table Ensemble_access;
/* ----------------Create the dsets for devEnsemble----------------- */
static struct driver_table *drvtabptr;
static long Ensemble_init (void *);
static long Ensemble_init_record (void *);
static long Ensemble_start_trans (struct motorRecord *);
static RTN_STATUS Ensemble_build_trans (motor_cmnd, double *,
struct motorRecord *);
static RTN_STATUS Ensemble_end_trans (struct motorRecord *);
struct motor_dset devEnsemble =
{
{8, NULL, (DEVSUPFUN) Ensemble_init, (DEVSUPFUN) Ensemble_init_record, NULL},
motor_update_values,
Ensemble_start_trans,
Ensemble_build_trans,
Ensemble_end_trans
};
extern "C" {epicsExportAddress (dset, devEnsemble);}
/* --------------------------- program data --------------------- */
/*
* This table is used to define the command types
* WARNING! this must match "motor_cmnd" in motor.h
*/
static msg_types Ensemble_table[] = {
MOTION, /* MOVE_ABS */
MOTION, /* MOVE_REL */
MOTION, /* HOME_FOR */
MOTION, /* HOME_REV */
IMMEDIATE, /* LOAD_POS */
IMMEDIATE, /* SET_VEL_BASE */
IMMEDIATE, /* SET_VELOCITY */
IMMEDIATE, /* SET_ACCEL */
IMMEDIATE, /* GO */
IMMEDIATE, /* SET_ENC_RATIO */
INFO, /* GET_INFO */
MOVE_TERM, /* STOP_AXIS */
VELOCITY, /* JOG */
IMMEDIATE, /* SET_PGAIN */
IMMEDIATE, /* SET_IGAIN */
IMMEDIATE, /* SET_DGAIN */
IMMEDIATE, /* ENABLE_TORQUE */
IMMEDIATE, /* DISABL_TORQUE */
IMMEDIATE, /* PRIMITIVE */
IMMEDIATE, /* SET_HIGH_LIMIT */
IMMEDIATE, /* SET_LOW_LIMIT */
VELOCITY, /* JOG_VELOCITY */
IMMEDIATE /* SET_RESOLUTION */
};
static struct board_stat **Ensemble_cards;
/* --------------------------- program data --------------------- */
// initialize device support for Ensemble
static long Ensemble_init (void *arg)
{
long rtnval;
int after = (arg == 0) ? 0 : 1;
if (after == 0)
{
drvtabptr = &Ensemble_access;
(drvtabptr->init)();
}
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr,
drvtabptr, &Ensemble_cards);
return(rtnval);
}
// initialize a record instance
static long Ensemble_init_record (void *arg)
{
struct motorRecord *mr = (struct motorRecord *) arg;
return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr,
drvtabptr, Ensemble_cards));
}
// start building a transaction
static long Ensemble_start_trans (struct motorRecord *mr)
{
return(OK);
//return (motor_start_trans_com(mr, Ensemble_cards));
}
// end building a transaction
static RTN_STATUS Ensemble_end_trans (struct motorRecord * mr)
{
return(OK);
//return (motor_end_trans_com(mr, drvtabptr));
}
// add a part to the transaction
static RTN_STATUS Ensemble_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 Ensemblecontroller *cntrl;
char buff[BUFF_SIZE], temp[BUFF_SIZE];
int axis, card, maxdigits;
unsigned int size;
double dval, cntrl_units;
RTN_STATUS rtnval;
bool send = true;
rtnval = OK;
buff[0] = '\0';
// Protect against NULL pointer with WRTITE_MSG(GO/STOP_AXIS/GET_INFO, NULL).
dval = (parms == NULL) ? 0.0 : *parms;
motor_start_trans_com(mr, Ensemble_cards);
motor_call = &(trans->motor_call);
card = motor_call->card;
axis = motor_call->signal;
brdptr = (*trans->tabptr->card_array)[card];
if (brdptr == NULL)
return(rtnval = ERROR);
cntrl = (struct Ensemblecontroller *) brdptr->DevicePrivate;
cntrl_units = dval * cntrl->drive_resolution[axis];
maxdigits = cntrl->res_decpts[axis];
if (Ensemble_table[command] > motor_call->type)
{
motor_call->type = Ensemble_table[command];
}
if (trans->state != BUILD_STATE)
{
return(rtnval = ERROR);
}
switch (command)
{
case MOVE_ABS:
case MOVE_REL:
case HOME_FOR:
case HOME_REV:
case JOG:
if (strlen(mr->prem) != 0)
{
sprintf(temp, "%s%c", mr->prem, ASCII_EOS_CHAR);
strcat(motor_call->message, temp);
}
if (strlen(mr->post) != 0)
{
motor_call->postmsgptr = (char *) &mr->post;
}
break;
default:
break;
}
switch (command)
{
case MOVE_ABS:
sprintf(buff, "MOVEABS @%d %.*f",
axis, maxdigits, cntrl_units);
break;
case MOVE_REL:
sprintf(buff, "MOVEINC @%d %.*f",
axis, maxdigits, cntrl_units);
break;
case HOME_FOR:
case HOME_REV:
{
epicsUInt32 hparam = cntrl->home_dparam[axis];
if (command == HOME_FOR)
hparam |= 0x00000001;
else
hparam &= 0xFFFFFFFE;
cntrl->home_dparam[axis] = hparam;
sprintf(buff, "SETPARM @%d, 106, %d", axis, hparam);
strcpy(motor_call->message, buff);
rtnval = motor_end_trans_com(mr, drvtabptr);
rtnval = (RTN_STATUS) motor_start_trans_com(mr, Ensemble_cards);
sprintf(buff, "HOME @%d", axis);
motor_call->type = Ensemble_table[command];
}
break;
case LOAD_POS:
sprintf(buff, "SETPOSCMD @%d, %.*f", axis, maxdigits, cntrl_units);
break;
case SET_VEL_BASE:
send = false;
break; // Ensemble does not use base velocity
case SET_VELOCITY:
sprintf(buff, "SETPARM @%d, 102, %.*f", //DefaultSpeed
axis, maxdigits, cntrl_units);
strcpy(motor_call->message, buff);
rtnval = motor_end_trans_com(mr, drvtabptr);
rtnval = (RTN_STATUS) motor_start_trans_com(mr, Ensemble_cards);
sprintf(buff, "SETPARM @%d, 107, %.*f", //HomeFeedRate
axis, maxdigits, cntrl_units);
motor_call->type = Ensemble_table[command];
break;
case SET_ACCEL:
sprintf(buff, "SETPARM @%d, 103, %.*f", //DefaultRampRate
axis, maxdigits, cntrl_units);
break;
case GO:
/*
* The Ensemble starts moving immediately on move commands, GO command
* does nothing
*/
send = false;
break;
case SET_ENC_RATIO:
//sprintf(buff, "SETPARM @%d, 3, %.*f", //PosScaleFactor
// axis, maxdigits, cntrl_units);
send = false;
break;
case GET_INFO:
/*
* These commands are not actually done by sending a message, but
* rather they will indirectly cause the driver to read the status
* of all motors
*/
break;
case STOP_AXIS:
sprintf(buff, "ABORT @%d", axis);
break;
case JOG_VELOCITY:
case JOG:
sprintf(buff, "FREERUN @%d %.*f", axis, maxdigits, cntrl_units);
break;
case SET_PGAIN:
sprintf(buff, "SETPARM @%d, 8, %.*f", //GainKp
axis, maxdigits, dval);
break;
case SET_IGAIN:
sprintf(buff, "SETPARM @%d, 7, %.*f", //GainKi
axis, maxdigits, dval);
break;
case SET_DGAIN:
sprintf(buff, "SETPARM @%d, 12, %.*f", //GainKpi
axis, maxdigits, dval); // which gain??
break;
case ENABLE_TORQUE:
sprintf(buff, "ENABLE @%d", axis);
break;
case DISABL_TORQUE:
sprintf(buff, "DISABLE @%d", axis);
break;
case PRIMITIVE:
if (mr->init != NULL && strlen(mr->init) != 0)
{
strcat(motor_call->message, mr->init);
}
break;
case SET_HIGH_LIMIT:
case SET_LOW_LIMIT:
send = false;
break;
case SET_RESOLUTION:
sprintf(buff, "SETPARM @%d, 3, %.*f", //PosScaleFactor
axis, maxdigits, 1 / cntrl_units);
break;
default:
send = false;
rtnval = ERROR;
}
if (send == true)
{
size = strlen (buff);
if (size > sizeof(buff) || (strlen(motor_call->message) + size) > MAX_MSG_SIZE)
{
errlogMessage("Ensemble_build_trans(): buffer overflow.\n");
}
else
{
strcat(motor_call->message, buff);
motor_end_trans_com(mr, drvtabptr);
}
}
return(rtnval);
}
-750
View File
@@ -1,750 +0,0 @@
/*
FILENAME... drvEnsemble.cc
USAGE... Motor record driver level support for Aerotech Ensemble.
Version: $Revision$
Modified By: $Author$
Last Modified: $Date$
HeadURL: $URL$
*/
/*
* Original Author: Chad Weimer
* Date: 04/04/08
* Current Author: Chad Weimer
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* NOTES
* -----
* Verified with firmware:
* - ver: 2.5.2
*
* Modification Log:
* -----------------
* .01 04-04-08 caw initialized from drvMM4000.cc (Newport)
* .02 05-01-09 rls - Using EOT fault indicators rather than LS's to set
* RA_PLUS/MINUS_LS indicators.
* - Fix HOME_LIMIT/MARKER_BIT mask.
* - More extensive comm. error checks in set_status(); handle
* ASCII_ACK_CHAR as error.
* - cntrl->drive_resolution must be initialized with fabs().
* .03 03-02-10 rls - Use sign(drive_resolution) to determine +/- limit switch
* status. Removed reading controller's soft limits; see
* README file. This version is depreciated; use the asyn
* motor version.
*/
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <epicsThread.h>
#include <epicsString.h>
#include <drvSup.h>
#include "motor.h"
#include "drvEnsemble.h"
#include "asynOctetSyncIO.h"
#include "epicsExport.h"
/* Status byte bits */
#define ENABLED_BIT 0x00000001
#define IN_POSITION_BIT 0x00000004
#define IN_MOTION_BIT 0x00000008
#define DIRECTION_BIT 0x00000200
#define HOME_LIMIT_BIT 0x01000000
#define HOME_MARKER_BIT 0x02000000
/* Fault status bits */
#define CW_FAULT_BIT 0x004
#define CCW_FAULT_BIT 0x008
// This can really be any number, because there isn't any theoretical
// restriction on the number of Ensembles that can be on a network.
// However, a relatively low number was picked for practical purposes
#define Ensemble_NUM_CARDS 10
// Due to the way some of the commands are implemented in the Ensemble,
// such as HOME, the command response is not returned until the command
// has actually finished executing. This requires a fairly large timeout
// value. However, even a large value will not guarantee that the response will
// be sent back in the time alloted.
#define TIMEOUT 20.0 /* Command timeout in sec. */
/*----------------debugging-----------------*/
#ifdef __GNUG__
#ifdef DEBUG
#define Debug(l, f, args...) { if(l<=drvEnsembledebug) printf(f,## args); }
#else
#define Debug(l, f, args...)
#endif
#else
#define Debug()
#endif
volatile int drvEnsembledebug = 0;
extern "C" {epicsExportAddress(int, drvEnsembledebug);}
/* --- Local data. --- */
int Ensemble_num_cards = 0;
int num_cmds = 0;
/* Local data required for every driver; see "motordrvComCode.h" */
#include "motordrvComCode.h"
/*----------------functions-----------------*/
static int recv_mess(int, char *, int);
static RTN_STATUS send_mess(int, char const *, char *name);
static int set_status(int card, int signal);
static long report(int level);
static long init();
static int motor_init();
static void query_done(int, int, struct mess_node *);
/*----------------functions-----------------*/
struct driver_table Ensemble_access =
{
motor_init,
motor_send,
motor_free,
motor_card_info,
motor_axis_info,
&mess_queue,
&queue_lock,
&free_list,
&freelist_lock,
&motor_sem,
&motor_state,
&total_cards,
&any_motor_in_motion,
send_mess,
recv_mess,
set_status,
query_done,
NULL,
&initialized,
NULL
};
struct drvEnsemble_drvet
{
long number;
long (*report) (int);
long (*init) (void);
} drvEnsemble = {2, report, init};
extern "C" {epicsExportAddress(drvet, drvEnsemble);}
static struct thread_args targs = {SCAN_RATE, &Ensemble_access, 0.0};
/*********************************************************
* Print out driver status report
*********************************************************/
static long report(int level)
{
int card;
if (Ensemble_num_cards <=0)
printf(" No Ensemble controllers configured.\n");
else
{
for (card = 0; card < Ensemble_num_cards; card++)
{
struct controller *brdptr = motor_state[card];
if (brdptr == NULL)
printf(" Ensemble controller %d connection failed.\n", card);
else
{
struct Ensemblecontroller *cntrl;
cntrl = (struct Ensemblecontroller *) brdptr->DevicePrivate;
printf(" Ensemble controller %d, port=%s, address=%d, id: %s \n",
card, cntrl->asyn_port, cntrl->asyn_address,
brdptr->ident);
}
}
}
return(OK);
}
static long init()
{
/*
* We cannot call motor_init() here, because that function can do GPIB I/O,
* and hence requires that the drvGPIB have already been initialized.
* That cannot be guaranteed, so we need to call motor_init from device
* support
*/
/* Check for setup */
if (Ensemble_num_cards <= 0)
{
Debug(1, "init(): Ensemble driver disabled. EnsembleSetup() missing from startup script.\n");
}
return((long) 0);
}
static void query_done(int card, int axis, struct mess_node *nodeptr)
{
}
/**************************************************************
* Parse status and position strings for a card and signal
* set_status()
************************************************************/
static int set_status(int card, int signal)
{
struct Ensemblecontroller *cntrl;
struct mess_node *nodeptr;
register struct mess_info *motor_info;
double motorData, pfbk;
bool plusdir, ls_active = false;
msta_field status;
int rtn_state, comm_status, axis_status;
char buff[BUFF_SIZE];
cntrl = (struct Ensemblecontroller *) motor_state[card]->DevicePrivate;
motor_info = &(motor_state[card]->motor_info[signal]);
status.All = motor_info->status.All;
// get the axis status
sprintf(buff, "AXISSTATUS(@%d)", signal);
send_mess(card, buff, (char) NULL);
comm_status = recv_mess(card, buff, 1);
if (comm_status > 0 && buff[0] == ASCII_ACK_CHAR)
{
cntrl->status = NORMAL;
status.Bits.CNTRL_COMM_ERR = 0;
}
else if (comm_status <= 0)
{
if (cntrl->status == NORMAL)
{
cntrl->status = RETRY;
rtn_state = OK;
}
else
{
cntrl->status = COMM_ERR;
status.Bits.CNTRL_COMM_ERR = 1;
status.Bits.RA_PROBLEM = 1;
rtn_state = 1;
}
goto exit;
}
else if (buff[0] != ASCII_ACK_CHAR)
{
cntrl->status = COMM_ERR;
status.Bits.CNTRL_COMM_ERR = 1;
status.Bits.RA_PROBLEM = 1;
rtn_state = 1;
goto exit;
}
cntrl->status = NORMAL;
status.Bits.CNTRL_COMM_ERR = 0;
// convert to an integer
axis_status = atoi(&buff[1]);
nodeptr = motor_info->motor_motion;
status.Bits.EA_SLIP = 0;
status.Bits.EA_SLIP_STALL = 0;
// fill in the status
if (cntrl->drive_resolution[signal] > 0.0)
status.Bits.RA_DIRECTION = axis_status & DIRECTION_BIT ? 1 : 0;
else
status.Bits.RA_DIRECTION = axis_status & DIRECTION_BIT ? 0 : 1;
status.Bits.RA_DONE = axis_status & IN_POSITION_BIT ? 1 : 0;
status.Bits.RA_HOME = axis_status & HOME_LIMIT_BIT ? 1 : 0;
status.Bits.EA_POSITION = axis_status & ENABLED_BIT ? 1 : 0;
status.Bits.EA_HOME = axis_status & HOME_MARKER_BIT ? 1 : 0;
status.Bits.RA_MOVING = axis_status & IN_MOTION_BIT ? 1 : 0;
/* get the axis fault status */
sprintf(buff, "AXISFAULT(@%d)", signal);
send_mess(card, buff, (char) NULL);
comm_status = recv_mess(card, buff, 1);
axis_status = atoi(&buff[1]);
if (cntrl->drive_resolution[signal] > 0.0)
{
status.Bits.RA_PLUS_LS = axis_status & CW_FAULT_BIT ? 1 : 0;
status.Bits.RA_MINUS_LS = axis_status & CCW_FAULT_BIT ? 1 : 0;
}
else
{
status.Bits.RA_PLUS_LS = axis_status & CCW_FAULT_BIT ? 1 : 0;
status.Bits.RA_MINUS_LS = axis_status & CW_FAULT_BIT ? 1 : 0;
}
plusdir = status.Bits.RA_DIRECTION ? true : false;
if ((status.Bits.RA_PLUS_LS && plusdir) || (status.Bits.RA_MINUS_LS && !plusdir))
{
ls_active = true;
}
// get the position
sprintf(buff, "PFBKPROG(@%d)", signal);
send_mess(card, buff, (char) NULL);
recv_mess(card, buff, 1);
if (buff[0] == ASCII_ACK_CHAR)
{
// convert to an integer
pfbk = atof(&buff[1]);
}
else
{
pfbk = 0;
}
// fill in the position
motorData = pfbk / fabs(cntrl->drive_resolution[signal]);
if (motorData == motor_info->position)
{
// only increment the counter if the motor is moving
if (nodeptr != 0)
{
motor_info->no_motion_count++;
}
}
else
{
motor_info->position = NINT(motorData);
if (motor_info->encoder_present == YES)
{
motor_info->encoder_position = NINT(motorData);
}
else
{
motor_info->encoder_position = 0;
}
motor_info->no_motion_count = 0;
}
// velocity is not used, so don't bother doing a command down
// to the controller to get it
motor_info->velocity = 0;
// do this "last", so that we know no errors occurred
status.Bits.RA_PROBLEM = 0;
rtn_state = (!motor_info->no_motion_count || ls_active ||
status.Bits.RA_DONE | status.Bits.RA_PROBLEM) ? 1 : 0;
// test for post-move string
if ((status.Bits.RA_DONE || ls_active) && nodeptr != 0 && nodeptr->postmsgptr != 0)
{
strcpy(buff, nodeptr->postmsgptr);
send_mess(card, buff, (char) NULL);
nodeptr->postmsgptr = NULL;
}
exit:
motor_info->status.All = status.All;
return(rtn_state);
}
/*****************************************************/
/* send a message to the Ensemble board */
/* send_mess() */
/*****************************************************/
static RTN_STATUS send_mess(int card, char const *com, char *name)
{
struct Ensemblecontroller *cntrl;
int size;
size_t nwrite;
char *eos_tok, com_cpy[BUFF_SIZE];
asynStatus status;
size = strlen(com);
if (size > MAX_MSG_SIZE)
{
errlogMessage("drvEnsemble.c:send_mess(); message size violation.\n");
return(ERROR);
}
else if (size == 0)
{
return(OK);
}
if (!motor_state[card])
{
errlogMessage("drvEnsemble.c:send_mess() - invalid card #%d\n");
return(ERROR);
}
if (name != NULL)
{
errlogMessage("drvEnsemble.c:send_mess() - invalid argument = %s\n");
return(ERROR);
}
Debug(2, "send_mess(): message = %s\n", com);
// We need to track the number of individual Ensemble commands that are
// being sent, so that we can read back the same number of responses.
// This is necessary, because the Ensemble will send individual responses
// terminated by the EOS char for each command sent, even if those commands
// were all sent as part of one motor record command, such as LOAD_POS
num_cmds = 0;
strcpy(com_cpy, com);
eos_tok = strtok(com_cpy, ASCII_EOS_STR);
while (eos_tok != NULL)
{
num_cmds++;
eos_tok = strtok(NULL, ASCII_EOS_STR);
}
cntrl = (struct Ensemblecontroller *) motor_state[card]->DevicePrivate;
status = pasynOctetSyncIO->write(cntrl->pasynUser, com, size, TIMEOUT, &nwrite);
if (status != asynSuccess || nwrite <= 0)
{
errlogMessage(cntrl->pasynUser->errorMessage);
return(ERROR);
}
return(OK);
}
/*
* FUNCTION... recv_mess(int card, char *com, int flag)
*
* INPUT ARGUMENTS...
* card - controller card # (0,1,...).
* *com - caller's response buffer.
* flag | FLUSH = flush controller's output buffer; set timeout = 0.
* | !FLUSH = retrieve response into caller's buffer; set timeout.
*
* LOGIC...
* IF controller card does not exist.
* ERROR RETURN.
* ENDIF
* NORMAL RETURN.
*/
static int recv_mess(int card, char *com, int flag)
{
struct Ensemblecontroller *cntrl;
double timeout = 0;
size_t nread = 0;
asynStatus status;
int eomReason, i;
char buff[BUFF_SIZE];
if (!motor_state[card])
{
return(ERROR);
}
cntrl = (struct Ensemblecontroller *) motor_state[card]->DevicePrivate;
timeout = TIMEOUT;
com[0] = '\0';
for (i = 0; i < num_cmds; i++)
{
status = pasynOctetSyncIO->read(cntrl->pasynUser, buff, BUFF_SIZE, timeout, &nread, &eomReason);
if (status == asynSuccess && nread > 0)
{
strcat(com, buff);
}
else
{
com[0] = '\0';
nread = 0;
break;
}
}
Debug(2, "recv_mess(): message = \"%s\"\n", com);
return(nread);
}
/*****************************************************/
/* Setup system configuration */
/* EnsembleSetup() */
/*****************************************************/
RTN_STATUS EnsembleSetup(int num_cards, /* maximum number of controllers in system. */
int scan_rate) /* polling rate - 1/60 sec units. */
{
int i;
if (num_cards < 1 || num_cards > Ensemble_NUM_CARDS)
{
Ensemble_num_cards = Ensemble_NUM_CARDS;
}
else
{
Ensemble_num_cards = num_cards;
}
// Set motor polling task rate
if (scan_rate >= 1 && scan_rate <= 60)
{
targs.motor_scan_rate = scan_rate;
}
else
{
targs.motor_scan_rate = SCAN_RATE;
}
/*
* Allocate space for motor_state structures. Note this must be done
* before EnsembleConfig is called, so it cannot be done in motor_init()
* This means that we must allocate space for a card without knowing
* if it really exists, which is not a serious problem
*/
motor_state = (struct controller **) malloc(Ensemble_num_cards * sizeof(struct controller *));
for (i = 0; i < Ensemble_num_cards; i++)
{
motor_state[i] = (struct controller *) NULL;
}
return(OK);
}
/*****************************************************/
/* Configure a controller */
/* EnsembleConfig() */
/*****************************************************/
RTN_STATUS EnsembleConfig(int card, /* card being configured */
const char *name, /* asyn port name */
int addr) /* asyn address (GPIB) */
{
struct Ensemblecontroller *cntrl;
if (card < 0 || card >= Ensemble_num_cards)
{
return(ERROR);
}
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
motor_state[card]->DevicePrivate = malloc(sizeof(struct Ensemblecontroller));
cntrl = (struct Ensemblecontroller *) motor_state[card]->DevicePrivate;
strcpy(cntrl->asyn_port, name);
cntrl->asyn_address = addr;
return(OK);
}
/*****************************************************/
/* initialize all software and hardware */
/* This is called from the initialization routine in */
/* device support. */
/* motor_init() */
/*****************************************************/
static int motor_init()
{
struct controller *brdptr;
struct Ensemblecontroller *cntrl;
int card_index, motor_index, status, digits;
char buff[BUFF_SIZE];
asynStatus success_rtn;
// Indicates that the driver is initialized
initialized = true;
if (Ensemble_num_cards <= 0)
return(ERROR);
for (card_index = 0; card_index < Ensemble_num_cards; card_index++)
{
int retry = 0;
if (!motor_state[card_index])
continue;
brdptr = motor_state[card_index];
brdptr->cmnd_response = true;
total_cards = card_index + 1;
cntrl = (struct Ensemblecontroller *)brdptr->DevicePrivate;
// Initialize communications channel
success_rtn = pasynOctetSyncIO->connect(cntrl->asyn_port, cntrl->asyn_address, &cntrl->pasynUser, NULL);
if (success_rtn != asynSuccess)
continue;
// Send a message to the baord, see if it exists
// flush any junk at input port - should not be any data available
pasynOctetSyncIO->flush(cntrl->pasynUser);
do
{
// we only care if we get a response
// so we don't need to send a valid command
strcpy(buff, "NONE");
send_mess(card_index, buff, (char) NULL);
status = recv_mess(card_index, buff, 1);
retry++;
} while (!status && retry < 3);
if (status > 0)
{
brdptr->localaddr = (char *) NULL;
brdptr->motor_in_motion = 0;
// Read controller ID string
strcpy(buff, "GETPARM(CONTROL, 265)"); //UserString1
send_mess(card_index, buff, (char) NULL);
recv_mess(card_index, buff, 1);
if (buff[0] == ASCII_ACK_CHAR)
strcpy(brdptr->ident, &buff[1]);
else
sprintf(brdptr->ident, "Ensemble%d", card_index);
// Get the number of axes
brdptr->total_axis = 0;
for (motor_index = 0; motor_index < 10; motor_index++)
{
// Does this axis actually exist?
sprintf(buff, "GETPARM(@%d, 257)", motor_index); //AxisName
send_mess(card_index, buff, (char) NULL);
recv_mess(card_index, buff, 1);
// We know the axis exists if we got an ACK response
if (buff[0] == ASCII_ACK_CHAR)
{
cntrl->axes[motor_index] = 1;
brdptr->total_axis++;
}
}
for (motor_index = 0; motor_index < 10; motor_index++)
{
if (cntrl->axes[motor_index])
{
struct mess_info *motor_info = &brdptr->motor_info[motor_index];
motor_info->status.All = 0;
motor_info->no_motion_count = 0;
motor_info->encoder_position = 0;
motor_info->position = 0;
brdptr->motor_info[motor_index].motor_motion = NULL;
// Determine if encoder present based on open/closed loop mode.
sprintf(buff, "GETPARM(@%d, 58)", motor_index); //CfgFbkPosType
send_mess(card_index, buff, (char) NULL);
recv_mess(card_index, buff, 1);
if (buff[0] == ASCII_ACK_CHAR)
{
if (atoi(&buff[1]) > 0)
{
motor_info->encoder_present = YES;
motor_info->status.Bits.EA_PRESENT = 1;
}
}
// Determine if gains are supported based on the motor type.
sprintf(buff, "GETPARM(@%d, 33)", motor_index); //CfgMotType
send_mess(card_index, buff, (char) NULL);
recv_mess(card_index, buff, 1);
if (buff[0] == ASCII_ACK_CHAR)
{
if (atoi(&buff[1]) != 3)
{
motor_info->pid_present = YES;
motor_info->status.Bits.GAIN_SUPPORT = 1;
}
}
// Stop all motors
sprintf(buff, "ABORT @%d", motor_index);
send_mess(card_index, buff, (char) NULL);
recv_mess(card_index, buff, 1);
// Determive drive resolution
sprintf(buff, "GETPARM(@%d, 3)", motor_index); //PosScaleFactor
send_mess(card_index, buff, (char) NULL);
recv_mess(card_index, buff, 1);
if (buff[0] == ASCII_ACK_CHAR)
cntrl->drive_resolution[motor_index] = 1 / atof(&buff[1]);
else
cntrl->drive_resolution[motor_index] = 1;
digits = (int) -log10(fabs(cntrl->drive_resolution[motor_index])) + 2;
if (digits < 1)
digits = 1;
cntrl->res_decpts[motor_index] = digits;
// Save home preset position
sprintf(buff, "GETPARM(@%d, 108)", motor_index); //HomeOffset
send_mess(card_index, buff, (char) NULL);
recv_mess(card_index, buff, 1);
if (buff[0] == ASCII_ACK_CHAR)
cntrl->home_preset[motor_index] = atof(&buff[1]);
// Save the HomeDirection parameter
sprintf(buff, "GETPARM(@%d, 106)", motor_index); //HomeDirection
send_mess(card_index, buff, (char) NULL);
recv_mess(card_index, buff, 1);
if (buff[0] == ASCII_ACK_CHAR)
cntrl->home_dparam[motor_index] = atoi(&buff[1]);
// Read status of each motor
set_status(card_index, motor_index);
}
}
}
else
motor_state[card_index] = (struct controller *) NULL;
}
any_motor_in_motion = 0;
mess_queue.head = (struct mess_node *) NULL;
mess_queue.tail = (struct mess_node *) NULL;
free_list.head = (struct mess_node *) NULL;
free_list.tail = (struct mess_node *) NULL;
epicsThreadCreate((char *) "Ensemble_motor",
epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC) motor_task, (void *) &targs);
return(OK);
}
-82
View File
@@ -1,82 +0,0 @@
/*
FILENAME... drvEnsemble.h
USAGE... This file contains Aerotech Ensemble driver "include" information.
Version: $Revision$
Modified By: $Author$
Last Modified: $Date$
HeadURL: $URL$
*/
/*
* Original Author: Chad Weimer
* Date: 10/16/97
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .00 04-01-08 caw initialized from drvMM4000.h (Newport)
*/
#ifndef INCdrvEnsembleh
#define INCdrvEnsembleh 1
#include "motor.h"
#include "motordrvCom.h"
#include "asynDriver.h"
#include "asynOctetSyncIO.h"
// The following should be defined to have the same value as
// the Ensemble parameters specified
#define ASCII_EOS_CHAR '\n' // AsciiCmdEOSChar
#define ASCII_EOS_STR "\n"
#define ASCII_ACK_CHAR '%' // AsciiCmdAckChar
#define ASCII_NAK_CHAR '!' // AsciiCmdNakChar
#define ASCII_FAULT_CHAR '#' // AsciiCmdFaultChar
#define ASCII_TIMEOUT_CHAR '$' // AsciiCmdTimeoutChar
#define BUFF_SIZE 100 /* Maximum length of string to/from Ensemble */
/* Ensemble specific data is stored in this structure. */
struct Ensemblecontroller
{
asynUser *pasynUser; /* For RS-232/Ethernet */
int asyn_address; /* Use for GPIB or other address with asyn */
char asyn_port[80]; /* asyn port name */
int axes[MAX_AXIS];
double drive_resolution[MAX_AXIS];
int res_decpts[MAX_AXIS]; /* Drive resolution significant dec. pts. */
double home_preset[MAX_AXIS]; /* Controller's home preset position (XF command). */
epicsUInt32 home_dparam[MAX_AXIS]; /* Controller's HomeDirection parameter. */
CommStatus status; /* Controller communication status. */
};
/* Function prototypes. */
extern RTN_STATUS EnsembleSetup(int, int);
extern RTN_STATUS EnsembleConfig(int, const char *, int);
#endif /* INCdrvEnsembleh */