OMS PC68/78 support.

This commit is contained in:
Ron Sluiter
2006-04-24 18:12:49 +00:00
parent b45e24de8a
commit 1defd6dc3d
6 changed files with 1142 additions and 3 deletions
+12
View File
@@ -227,6 +227,18 @@ dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=IOC:")
#!asynOctetSetInputEos("tcp2",0,"")
#!asynOctetSetOutputEos("tcp2",0,"")
# OMS PC68/78 stand-alone serial driver setup parameters:
# (1) maximum number of controllers in system
# (2) motor task polling rate (min=1Hz,max=60Hz)
#!OmsPC68Setup(1, 10)
# OMS PC68/78 stand-alone serial driver configuration parameters:
# (1) Card# being configured
# (2) asyn port name
#!OmsPC68Config(0, "L0")
#!var drvOmsPC68debug 4
iocInit
# motorUtil (allstop & alldone)
+12
View File
@@ -227,6 +227,18 @@ dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=IOC:")
#!asynOctetSetInputEos("tcp2",0,"")
#!asynOctetSetOutputEos("tcp2",0,"")
# OMS PC68/78 stand-alone serial driver setup parameters:
# (1) maximum number of controllers in system
# (2) motor task polling rate (min=1Hz,max=60Hz)
#!OmsPC68Setup(1, 10)
# OMS PC68/78 stand-alone serial driver configuration parameters:
# (1) Card# being configured
# (2) asyn port name
#!OmsPC68Config(0, "L0")
#!var drvOmsPC68debug 4
iocInit
# motorUtil (allstop & alldone)
+14 -3
View File
@@ -1,8 +1,19 @@
# Oregon Micro Systems VME8/44 and VME58 Driver support.
# Oregon Micro Systems VME8/44 driver support.
device(motor,VME_IO,devOMS,"OMS VME8/44")
device(motor,VME_IO,devOms58,"OMS VME58")
device(motor,VME_IO,devMAXv,"OMS MAXv")
driver(drvOms)
# Oregon Micro Systems VME58 driver support.
device(motor,VME_IO,devOms58,"OMS VME58")
driver(drvOms58)
# Oregon Micro Systems MAXv driver support.
device(motor,VME_IO,devMAXv,"OMS MAXv")
driver(drvMAXv)
# Oregon Micro Systems PC68/78 RS-232 serial driver support.
device(motor,VME_IO,devOmsPC68,"OMS PC68/78")
driver(drvOmsPC68)
registrar(OmsPC68Register)
variable(drvOmsPC68debug)
+142
View File
@@ -0,0 +1,142 @@
/*
FILENAME... devOmsPC68.c
USAGE... Motor record device level support for OMS VME58.
Version: 1.5
Modified By: sluiter
Last Modified: 2004/12/20 21:11:53
*/
/*
* Original Author: Jim Kowalkowski
* Current Author: Joe Sullivan
* Date: 11/14/94
*
* 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 01-18-93 jbk initialized
* .02 11-14-94 jps copy devOMS.c and modify to point to vme58 driver
* .03 03-19-96 tmm v1.10: modified encoder-ratio calculation
* .04 06-20-96 jps allow for bumpless-reboot on position
* .04a 02-19-97 tmm fixed for EPICS 3.13
* .05 06-16-03 rls Converted to R3.14.x.
*/
#include <alarm.h>
#include <callback.h>
#include <dbDefs.h>
#include <dbAccess.h>
#include <dbCommon.h>
#include <devSup.h>
#include <drvSup.h>
#include <recSup.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "drvOmsPC68Com.h"
#include "devOmsCom.h"
#include "epicsExport.h"
#define STATIC static
extern int OmsPC68_num_cards;
extern struct driver_table OmsPC68_access;
/* ----------------Create the dsets for devOMS----------------- */
STATIC long oms_init(void *);
STATIC long oms_init_record(void *);
STATIC long oms_start_trans(struct motorRecord *);
STATIC RTN_STATUS oms_end_trans(struct motorRecord *);
struct motor_dset devOmsPC68 =
{
{8, NULL, oms_init, oms_init_record, NULL},
motor_update_values,
oms_start_trans,
oms_build_trans,
oms_end_trans
};
extern "C" {
epicsExportAddress(dset,devOmsPC68);
}
STATIC struct board_stat **oms_cards;
STATIC const char errmsg[] = {"\n\n!!!ERROR!!! - OmsPC68 driver uninitialized.\n"};
//__________________________________________________________________________________________
STATIC long oms_init(void *arg)
{
int after = (int) arg;
if (*(OmsPC68_access.init_indicator) == NO)
{
errlogSevPrintf(errlogMinor, "%s", errmsg);
return(ERROR);
}
else
return (motor_init_com (after, OmsPC68_num_cards, &OmsPC68_access, &oms_cards));
}
//__________________________________________________________________________________________
STATIC long oms_init_record(void *arg)
{
struct motorRecord *mr = (struct motorRecord *) arg;
return (motor_init_record_com(mr, OmsPC68_num_cards, &OmsPC68_access, oms_cards));
}
//__________________________________________________________________________________________
STATIC long oms_start_trans(struct motorRecord *mr)
{
struct motor_trans *trans;
long rtnval;
rtnval = motor_start_trans_com(mr, oms_cards);
/* Initialize a STOP_AXIS command termination string pointer. */
trans = (struct motor_trans *) mr->dpvt;
trans->motor_call.termstring = " ID";
return(rtnval);
}
//__________________________________________________________________________________________
STATIC RTN_STATUS oms_end_trans(struct motorRecord *mr)
{
if (*(OmsPC68_access.init_indicator) == NO)
{
errlogSevPrintf(errlogMinor, "%s", errmsg);
return(ERROR);
}
else
return(motor_end_trans_com(mr, &OmsPC68_access));
}
//__________________________________________________________________________________________
+877
View File
@@ -0,0 +1,877 @@
/*
FILENAME... drvOmsPC68.cc
USAGE... Motor record driver level support for OMS PC68 serial device.
Version: $Revision: 1.1 $
Modified By: $Author: sluiter $
Last Modified: $Date: 2006-04-24 18:12:00 $
*/
/*
* Original Author: Brian Tieman
* Current Author: Ron Sluiter
*
* 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:
* - PC78 ver 1.14-46
* - PC68 ver 6.51-2008
*
* Modification Log:
* -----------------
* .01 02/07/06 dmk - modified motor_init() to skip the encoder query if the
* controller has been configured for no encoder.
* .02 04/24/06 rls - support for both PC68 and PC78.
* - test for encoder support.
* - test for servo support.
*/
#include <string.h>
#include <math.h>
#include <epicsThread.h>
#include <dbAccess.h>
#include <drvSup.h>
#include <iocsh.h>
#include "motor.h"
#include "drvOmsPC68Com.h"
#include "epicsExport.h"
#define PC68_MAX_NUM_CARDS 10 /* Maximum # of cards. */
#define BUFF_SIZE 100 /* Maximum length of string to/from OmsPC68 */
#define TIMEOUT 2.0 /* Command timeout in sec. */
/*----------------debugging-----------------*/
#ifdef __GNUG__
#ifdef DEBUG
#define Debug(l, f, args...) {if(l<=drvOmsPC68debug) printf(f,## args);}
#else
#define Debug(l, f, args...)
#endif
#else
#define Debug()
#endif
volatile int drvOmsPC68debug = 0;
extern "C" {epicsExportAddress(int, drvOmsPC68debug);}
/* --- Global data. --- */
int OmsPC68_num_cards = 0;
/* Local data required for every driver; see "motordrvComCode.h" */
#include "motordrvComCode.h"
static volatile int motionTO = 10;
//OmsPC68 generic controller commands
static char *oms_axis[] = {"X", "Y", "Z", "T", "U", "V", "R", "S"};
/*----------------functions-----------------*/
static int recv_mess(int, char *, int);
static RTN_STATUS send_mess(int, char const *, char *name);
static void start_status(int card);
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-----------------*/
static int omsGet(int card, char *pcom);
struct driver_table OmsPC68_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,
start_status,
&initialized,
oms_axis
};
struct
{
long number;
long (*report) (int);
long (*init) (void);
} drvOmsPC68 = {2, report, init};
extern "C" {epicsExportAddress(drvet, drvOmsPC68);}
static struct thread_args targs = {SCAN_RATE, &OmsPC68_access, 0.0};
//_____________________________________________________________________________
/*********************************************************
* Print out driver status report
*********************************************************/
static long report(int level)
{
int card;
if (OmsPC68_num_cards <= 0)
printf(" No MDrive controllers configured.\n");
else
{
for (card = 0; card < OmsPC68_num_cards; card++)
{
struct controller *brdptr = motor_state[card];
if (brdptr == NULL)
printf(" PC68 controller %d connection failed.\n", card);
else
{
struct OmsPC68controller *cntrl;
cntrl = (struct OmsPC68controller *) brdptr->DevicePrivate;
printf(" PC68 controller #%d, port=%s, id: %s \n", card,
cntrl->asyn_port, brdptr->ident);
}
}
}
return(OK);
}
//_____________________________________________________________________________
static long init()
{
/* Check for setup */
if (OmsPC68_num_cards <= 0)
{
Debug(1, "init(): OmsPC68 driver disabled.\n");
Debug(1, "init(): OmsPC68Setup() missing from startup script.\n");
}
motor_init ();
initialized = true;
return(0);
}
//_____________________________________________________________________________
static void query_done(int card, int axis, struct mess_node *nodeptr)
{
}
/*********************************************************
* Read the status and position of all motors on a card
* start_status(int card)
* if card == -1 then start all cards
*********************************************************/
static void start_status(int card)
{
}
//_____________________________________________________________________________
/**************************************************************
* Parse status and position strings for a card and signal
* set_status()
************************************************************/
static int set_status(int card, int signal)
{
struct OmsPC68controller *cntrl;
struct mess_info *motor_info;
struct mess_node *nodeptr;
char *p, *tok_save;
struct axis_status *ax_stat;
struct encoder_status *en_stat;
char q_buf[50], outbuf[50];
int index, motorData, rtn_state;
bool ls_active = false;
msta_field status;
cntrl = (struct OmsPC68controller *) motor_state[card]->DevicePrivate;
motor_info = &(motor_state[card]->motor_info[signal]);
nodeptr = motor_info->motor_motion;
status.All = motor_info->status.All;
if (cntrl->status != NORMAL)
recv_mess(card, q_buf, FLUSH);
if (motor_state[card]->motor_info[signal].encoder_present == YES)
{
/* get 4 peices of info from axis */
send_mess(card, ALL_INFO, oms_axis[signal]);
rtn_state = recv_mess(card, q_buf, 4);
}
else
{
send_mess(card, AXIS_INFO, oms_axis[signal]);
rtn_state = recv_mess(card, q_buf, 2);
}
if (rtn_state > 0)
{
cntrl->status = NORMAL;
status.Bits.CNTRL_COMM_ERR = 0;
}
else
{
if (cntrl->status == NORMAL)
{
cntrl->status = RETRY;
rtn_state = OK;
goto exit;
}
else
{
cntrl->status = COMM_ERR;
status.Bits.CNTRL_COMM_ERR = 1;
status.Bits.RA_PROBLEM = 1;
rtn_state = 1;
goto exit;
}
}
Debug(5, "info = (%s)\n", q_buf);
for (index = 0, p = strtok_r(q_buf, ",", &tok_save); p;
p = strtok_r(NULL, ",", &tok_save), index++)
{
switch (index)
{
case 0:
/* axis status */
ax_stat = (struct axis_status *) p;
status.Bits.RA_DIRECTION = (ax_stat->direction == 'P') ? 1 : 0;
status.Bits.RA_DONE = (ax_stat->done == 'D') ? 1 : 0;
status.Bits.RA_HOME = (ax_stat->home == 'H') ? 1 : 0;
if (ax_stat->overtravel == 'L')
{
ls_active = true;
if (status.Bits.RA_DIRECTION)
status.Bits.RA_PLUS_LS = 1;
else
status.Bits.RA_MINUS_LS = 1;
}
else
{
ls_active = false;
status.Bits.RA_PLUS_LS = 0;
status.Bits.RA_MINUS_LS = 0;
}
break;
case 1:
/* motor pulse count (position) */
sscanf(p, "%index", &motorData);
if (motorData == motor_info->position)
{
/* Increment counter only if motor is moving. */
if (nodeptr != 0)
motor_info->no_motion_count++;
}
else
{
motor_info->no_motion_count = 0;
motor_info->position = motorData;
}
if (motor_info->no_motion_count > motionTO)
{
status.Bits.RA_PROBLEM = 1;
send_mess(card, AXIS_STOP, oms_axis[signal]);
motor_info->no_motion_count = 0;
errlogSevPrintf(errlogMinor,
"Motor motion timeout ERROR on card: %d, signal: %d\n", card,
signal);
}
else
status.Bits.RA_PROBLEM = 0;
break;
case 2:
{
/* encoder pulse count (position) */
int temp;
sscanf(p, "%index", &temp);
motor_info->encoder_position = (epicsInt32) temp;
}
break;
case 3:
/* encoder status */
en_stat = (struct encoder_status *) p;
status.Bits.EA_SLIP = (en_stat->slip_enable == 'E') ? 1 : 0;
status.Bits.EA_POSITION = (en_stat->pos_enable == 'E') ? 1 : 0;
status.Bits.EA_SLIP_STALL = (en_stat->slip_detect == 'S') ? 1 : 0;
status.Bits.EA_HOME = (en_stat->axis_home == 'H') ? 1 : 0;
break;
default:
break;
}
}
/*
* jps: Velocity should be set based on the actual velocity returned from
* the 'RV' command (See drvOms58.c). But the polling task does not have
* time to request additional information so the velocity is set to
* indicate moving or not-moving.
*/
if (status.Bits.RA_DONE)
motor_info->velocity = 0;
else
motor_info->velocity = 1;
if (!(status.Bits.RA_DIRECTION))
motor_info->velocity *= -1;
rtn_state = (!motor_info->no_motion_count || ls_active == true ||
status.Bits.RA_DONE | status.Bits.RA_PROBLEM) ? 1 : 0;
/* Test for post-move string. */
if ((status.Bits.RA_DONE || ls_active == true) && (nodeptr != 0) &&
(nodeptr->postmsgptr != 0))
{
char buffer[40];
/* Test for a "device directive" in the POST string. */
if (nodeptr->postmsgptr[0] == '@')
{
bool errind = false;
char *end = strchr(&nodeptr->postmsgptr[1], '@');
if (end == NULL)
errind = true;
else
{
DBADDR addr;
char *start, *tail;
int size = (end - &nodeptr->postmsgptr[0]) + 1;
/* Copy device directive to buffer. */
strncpy(buffer, nodeptr->postmsgptr, size);
buffer[size] = '\0';
if (strncmp(buffer, "@PUT(", 5) != 0)
goto errorexit;
/* Point "start" to PV name argument. */
tail = NULL;
start = strtok_r(&buffer[5], ",", &tail);
if (tail == NULL)
goto errorexit;
if (dbNameToAddr(start, &addr)) /* Get address of PV. */
{
errPrintf(-1, __FILE__, __LINE__, "Invalid PV name: %s",
start);
goto errorexit;
}
/* Point "start" to PV value argument. */
start = strtok_r(NULL, ")", &tail);
if (dbPutField(&addr, DBR_STRING, start, 1L))
{
errPrintf(-1, __FILE__, __LINE__, "invalid value: %s",
start);
goto errorexit;
}
}
if (errind == true)
errorexit: errMessage(-1, "Invalid device directive");
end++;
strcpy(buffer, end);
}
else
strcpy(buffer, nodeptr->postmsgptr);
strcpy(outbuf, buffer);
send_mess(card, outbuf, oms_axis[signal]);
nodeptr->postmsgptr = NULL;
}
exit:
motor_info->status.All = status.All; /* Update status from local copy. */
return(rtn_state);
}
//_____________________________________________________________________________
/*****************************************************/
/* send a message to the OmsPC68 board */
/* send_mess() */
/*****************************************************/
static RTN_STATUS send_mess(int card, char const *com, char *name)
{
struct OmsPC68controller *cntrl;
size_t size,
nwrite;
int error_code;
char outbuf[MAX_MSG_SIZE];
if (!motor_state[card])
{
errlogPrintf("drvOmsPC68.c:send_mess() - invalid card #%d\n", card);
return(ERROR);
}
if (name == NULL)
strcpy(outbuf, com);
else
{
strcpy(outbuf, "A");
strcat(outbuf, name);
strcat(outbuf, " ");
strcat(outbuf, com);
}
size = strlen (outbuf);
if (size > MAX_MSG_SIZE)
{
errlogMessage("drvOmsPC68.c:send_mess(); message size violation.\n");
return(ERROR);
}
else
if (size == 0) /* Normal exit on empty input message. */
return(OK);
Debug(2, "send_mess(): message = %s\n", com);
cntrl = (struct OmsPC68controller *) motor_state[card]->DevicePrivate;
error_code = pasynOctetSyncIO->write(cntrl->pasynUser, outbuf, size,
TIMEOUT, &nwrite);
if (error_code == OK)
{
Debug(4, "sent message: (%s)\n", outbuf);
}
else
{
Debug(4, "unable to send message (%s)\n", outbuf);
}
return(OK);
}
/*
* FUNCTION... recv_mess(int card, char *com, int amount)
*
* INPUT ARGUMENTS...
* card - controller card # (0,1,...).
* *com - caller's response buffer.
* amount | -1 = flush controller's output buffer.
* | >= 1 = the # of command responses to retrieve into caller's
* response buffer.
*
* LOGIC...
* IF controller card does not exist.
* ERROR RETURN.
* ENDIF
* IF "amount" indicates buffer flush.
* WHILE characters left in input buffer.
* Call omsGet().
* ENDWHILE
* ENDIF
*
* FOR each message requested (i.e. "amount").
* Initialize head and tail pointers.
* Initialize retry counter and state indicator.
* WHILE retry count not exhausted, AND, state indicator is NOT at END.
* IF characters left in controller's input buffer.
* Process input character.
* ELSE IF command error occured - call omsError().
* ERROR RETURN.
* ENDIF
* ENDWHILE
* IF retry count exhausted.
* Terminate receive buffer.
* ERROR RETURN.
* ENDIF
* Terminate command response.
* ENDFOR
*
* IF commands processed.
* Terminate response buffer.
* ELSE
* Clear response buffer.
* ENDIF
* NORMAL RETURN.
*/
static int recv_mess(int card, char *com, int amount)
{
struct OmsPC68controller *cntrl;
int itera, trys, piece, head_size, tail_size;
char inchar;
inchar = '\0';
/* Check that card exists */
if (card >= total_cards)
{
Debug(1, "recv_mess - invalid card #%d\n", card);
return(-1);
}
if (amount == -1)
{
/* Process request to flush receive queue */
Debug(7, "recv flush -------------");
cntrl = (struct OmsPC68controller *) motor_state[card]->DevicePrivate;
pasynOctetSyncIO->flush(cntrl->pasynUser);
return(0);
}
for (itera = 0; amount > 0; amount--)
{
Debug(7, "-------------");
head_size = 0;
tail_size = 0;
for (piece = 0, trys = 0; piece < 3 && trys < 3; trys++)
{
if (omsGet(card, &inchar))
{
Debug(7, "%02x", inchar);
switch (piece)
{
case 0: /* header */
if (inchar == '\n' || inchar == '\r')
head_size++;
else if ((inchar == '#') || //command error
(inchar == '$') || //motor slip
(inchar == '@') || //over travel
(inchar == '!')) //done
{
if (inchar == '#')
{
Debug(4, "command error: card %d\n", card);
return(-1);
}
head_size++;
}
else
{
piece++;
com[itera++] = inchar;
}
break;
case 1: /* body */
if (inchar == '\n' || inchar == '\r')
{
piece++;
tail_size++;
}
else
com[itera++] = inchar;
break;
case 2: /* trailer */
tail_size++;
if (tail_size >= head_size)
piece++;
break;
}
trys = 0;
}
}
Debug(7, "-------------\n");
if (trys >= 3)
{
Debug(1, "Timeout occurred in recv_mess\n");
com[itera] = '\0';
return(0);
}
com[itera++] = ',';
}
if (itera > 0)
com[itera - 1] = '\0';
else
com[itera] = '\0';
Debug(4, "recv_mess: card %d, msg: (%s)\n", card, com);
return(itera);
}
/*****************************************************/
/* Get next character from OMS input buffer */
/* omsGet() */
/*****************************************************/
static int omsGet(int card, char *pchar)
{
int eomReason;
size_t nread;
asynStatus status;
struct OmsPC68controller *cntrl;
cntrl = (struct OmsPC68controller *) motor_state[card]->DevicePrivate;
status = pasynOctetSyncIO->read(cntrl->pasynUser, pchar, 1, TIMEOUT, &nread, &eomReason);
return(nread);
}
//_____________________________________________________________________________
/*****************************************************/
/* initialize all software and hardware */
/* This is called from the initialization routine in */
/* device support. */
/* motor_init() */
/*****************************************************/
static int motor_init()
{
volatile struct controller* pmotorState;
struct OmsPC68controller* cntrl;
int card_index, status, success_rtn, total_axis, motor_index;
char axis_pos[50], encoder_pos[50], *tok_save, *pos_ptr;
/* Check for setup */
if (OmsPC68_num_cards <= 0)
{
Debug(1, "motor_init: OmsPC68 driver disabled* \n");
Debug(1, "motor_init: OmsPC68Setup() is missing from startup script.\n");
return(ERROR);
}
total_cards = OmsPC68_num_cards;
for (card_index=0;card_index<OmsPC68_num_cards;card_index++)
{
if (!motor_state[card_index])
continue;
pmotorState = motor_state[card_index];
/* Initialize communications channel */
cntrl = (struct OmsPC68controller *) pmotorState->DevicePrivate;
success_rtn = pasynOctetSyncIO->connect(cntrl->asyn_port, 0,
&cntrl->pasynUser, NULL);
if (success_rtn == asynSuccess)
{
int retry = 0;
/* Send a message to the board, see if it exists */
/* flush any junk at input port - should be no data available */
pasynOctetSyncIO->flush(cntrl->pasynUser);
/* Try 3 times to connect to controller. */
do
{
send_mess (card_index, GET_IDENT, (char) NULL);
status = recv_mess(card_index, (char *) pmotorState->ident, 1);
retry++;
} while (status == 0 && retry < 3);
Debug(3, "Identification = %s\n", pmotorState->ident);
}
if (success_rtn == asynSuccess && status > 0)
{
pmotorState->motor_in_motion = 0;
pmotorState->cmnd_response = false;
send_mess (card_index, ECHO_OFF, (char) NULL);
send_mess (card_index, ERROR_CLEAR, (char) NULL);
send_mess (card_index, STOP_ALL, (char) NULL);
send_mess (card_index, ALL_POS, (char) NULL);
recv_mess (card_index, axis_pos, 1);
for (total_axis = 0, pos_ptr = strtok_r(axis_pos, ",", &tok_save);
pos_ptr; pos_ptr = strtok_r(NULL, ",", &tok_save),
total_axis++)
{
pmotorState->motor_info[total_axis].motor_motion = NULL;
pmotorState->motor_info[total_axis].status.All = 0;
}
Debug(3, "Total axis = %d\n", total_axis);
pmotorState->total_axis = total_axis;
for (motor_index = 0; motor_index < total_axis; motor_index++)
{
send_mess(card_index, ENCODER_QUERY, oms_axis[motor_index]);
if (recv_mess(card_index, encoder_pos, 1) == -1)
pmotorState->motor_info[motor_index].encoder_present = NO;
else
pmotorState->motor_info[motor_index].encoder_present = YES;
/* Test if motor has PID parameters. */
send_mess(card_index, PID_QUERY, oms_axis[motor_index]);
if (recv_mess(card_index, encoder_pos, 1) == -1)
pmotorState->motor_info[motor_index].pid_present = NO;
else
pmotorState->motor_info[motor_index].pid_present = YES;
}
for (motor_index=0;motor_index<total_axis;motor_index++)
{
pmotorState->motor_info[motor_index].status.All = 0;
pmotorState->motor_info[motor_index].no_motion_count = 0;
pmotorState->motor_info[motor_index].encoder_position = 0;
pmotorState->motor_info[motor_index].position = 0;
if (pmotorState->motor_info[motor_index].encoder_present == YES)
pmotorState->motor_info[motor_index].status.Bits.EA_PRESENT = 1;
if (pmotorState->motor_info[motor_index].pid_present == YES)
pmotorState->motor_info[motor_index].status.Bits.GAIN_SUPPORT = 1;
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;
Debug(3, "Motors initialized\n");
epicsThreadCreate((char *) "OmsPC68_motor", epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC) motor_task, (void *) &targs);
Debug(3, "Started motor_task\n");
return(0);
}
//_____________________________________________________________________________
/*****************************************************/
/* Setup system configuration */
/* OmsPC68Setup() */
/*****************************************************/
RTN_STATUS OmsPC68Setup (int num_cards, int scan_rate)
{
int itera;
if (num_cards < 1 || num_cards > PC68_MAX_NUM_CARDS)
OmsPC68_num_cards = PC68_MAX_NUM_CARDS;
else
OmsPC68_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 OmsPC68Config 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(OmsPC68_num_cards * sizeof(struct controller *));
for (itera = 0; itera < OmsPC68_num_cards; itera++)
motor_state[itera] = (struct controller *) NULL;
return(OK);
}
//___________________________________________
/*******************************************/
/* Configure a controller */
/* OmsPC68Config() */
/* */
/* Recieves: */
/* card - card being configured */
/* name - asyn port name */
/*******************************************/
RTN_STATUS OmsPC68Config(int card, const char *name)
{
struct OmsPC68controller *cntrl;
if (card < 0 || card >= OmsPC68_num_cards)
return(ERROR);
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
motor_state[card]->DevicePrivate = malloc(sizeof(struct OmsPC68controller));
cntrl = (struct OmsPC68controller *) motor_state[card]->DevicePrivate;
strcpy(cntrl->asyn_port, name);
return(OK);
}
extern "C"
{
// Setup arguments
static const iocshArg setupArg0 = {"Maximum # of cards", iocshArgInt};
static const iocshArg setupArg1 = {"Polling rate (HZ)", iocshArgInt};
// Config arguments
static const iocshArg configArg0 = {"Card# being configured", iocshArgInt};
static const iocshArg configArg1 = {"asyn port name", iocshArgString};
static const iocshArg *const SetupArgs[2] = {&setupArg0, &setupArg1};
static const iocshArg *const ConfigArgs[2] = {&configArg0, &configArg1};
static const iocshFuncDef setupOmsPC68 = {"OmsPC68Setup", 2, SetupArgs};
static const iocshFuncDef configOmsPC68 = {"OmsPC68Config", 2, ConfigArgs};
static void setupOmsPC68CallFunc(const iocshArgBuf *args)
{
OmsPC68Setup(args[0].ival, args[1].ival);
}
static void configOmsPC68CallFunc (const iocshArgBuf *args)
{
OmsPC68Config(args[0].ival, args[1].sval);
}
static void OmsPC68Register(void)
{
iocshRegister(&setupOmsPC68, setupOmsPC68CallFunc);
iocshRegister(&configOmsPC68, configOmsPC68CallFunc);
}
epicsExportRegistrar(OmsPC68Register);
} // extern "C"
//_____________________________________________________________________________
+85
View File
@@ -0,0 +1,85 @@
/*
FILENAME... drvOmsPC68Com.h
USAGE... This file contains information common to all OMS PC68/78 controllers.
Version: $Revision: 1.1 $
Modified By: $Author: sluiter $
Last Modified: $Date: 2006-04-24 18:11:59 $
*/
/*
* Original Author: Brian Tieman
* Current Author: Ron Sluiter
*
* 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:
* -----------------
*/
#ifndef INCdrvOmsPC68Comh
#define INCdrvOmsPC68Comh 1
#include "motor.h"
#include "motordrvCom.h"
#include "asynDriver.h"
#include "asynOctetSyncIO.h"
/* OmsPC68 specific data is stored in this structure. */
struct OmsPC68controller
{
asynUser *pasynUser; /* For RS-232 */
char asyn_port[80]; /* asyn port name */
CommStatus status; /* Controller communication status. */
};
struct encoder_status
{
char slip_enable;
char pos_enable;
char slip_detect;
char pos_dead;
char axis_home;
char unused;
};
#define ECHO_OFF "EF"
#define AXIS_STOP "ST"
#define GET_IDENT "WY"
#define ERROR_CLEAR "IC"
#define STOP_ALL "AA SA"
#define ALL_POS "AA RP"
#define ALL_INFO "QA RP RE EA"
#define AXIS_INFO "QA RP"
#define ENCODER_QUERY "EA"
#define DONE_QUERY "RA"
#define PID_QUERY "?KP"
/* Function prototypes. */
extern RTN_STATUS OmsPC68Setup(int, int);
extern RTN_STATUS OmsPC68Config(int, const char *);
#endif /* INCdrvOmsPC68Comh */