forked from epics_driver_modules/motorBase
- Flexible MDrive I/O configuration.
- Change Echo mode to 2; eliminate eat_garbage().
This commit is contained in:
+108
-103
@@ -3,9 +3,9 @@ FILENAME... drvMDrive.cc
|
||||
USAGE... Motor record driver level support for Intelligent Motion
|
||||
Systems, Inc. MDrive series; M17, M23, M34.
|
||||
|
||||
Version: $Revision: 1.14 $
|
||||
Version: $Revision: 1.15 $
|
||||
Modified By: $Author: sluiter $
|
||||
Last Modified: $Date: 2004-12-21 17:19:34 $
|
||||
Last Modified: $Date: 2005-03-18 22:32:59 $
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -47,6 +47,8 @@ Last Modified: $Date: 2004-12-21 17:19:34 $
|
||||
* - make debug variables always available.
|
||||
* - MS Visual C compatibility; make all epicsExportAddress
|
||||
* extern "C" linkage.
|
||||
* .07 03/18/05 rls - Flexible MDrive I/O configuration.
|
||||
* - Change Echo mode to 2; eliminate eat_garbage().
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -91,7 +93,6 @@ static char *MDrive_axis[] = {"1", "2", "3", "4", "5", "6", "7", "8"};
|
||||
#include "motordrvComCode.h"
|
||||
|
||||
/*----------------functions-----------------*/
|
||||
static int eat_garbage(int, char *, int);
|
||||
static int recv_mess(int, char *, int);
|
||||
static RTN_STATUS send_mess(int, char const *, char *);
|
||||
static int set_status(int, int);
|
||||
@@ -118,7 +119,7 @@ struct driver_table MDrive_access =
|
||||
&total_cards,
|
||||
&any_motor_in_motion,
|
||||
send_mess,
|
||||
eat_garbage,
|
||||
recv_mess,
|
||||
set_status,
|
||||
query_done,
|
||||
NULL,
|
||||
@@ -138,34 +139,6 @@ extern "C" {epicsExportAddress(drvet, drvMDrive);}
|
||||
static struct thread_args targs = {SCAN_RATE, &MDrive_access};
|
||||
|
||||
|
||||
/* Single Inputs - response from PR IN command */
|
||||
typedef union
|
||||
{
|
||||
epicsUInt8 All;
|
||||
struct
|
||||
{
|
||||
#ifdef MSB_First
|
||||
unsigned int na7:1;
|
||||
unsigned int na6:1;
|
||||
unsigned int na5:1;
|
||||
unsigned int na4:1;
|
||||
unsigned int na3:1;
|
||||
unsigned int homels:1; /* Home limit switch. */
|
||||
unsigned int ls_plus:1; /* Plus limit switch. */
|
||||
unsigned int ls_minus:1; /* Minus limit switch. */
|
||||
#else
|
||||
unsigned int ls_minus:1; /* Minus limit switch. */
|
||||
unsigned int ls_plus:1; /* Plus limit switch. */
|
||||
unsigned int homels:1; /* Home limit switch. */
|
||||
unsigned int na3:1;
|
||||
unsigned int na4:1;
|
||||
unsigned int na5:1;
|
||||
unsigned int na6:1;
|
||||
unsigned int na7:1;
|
||||
#endif
|
||||
} Bits;
|
||||
} SINPUTS;
|
||||
|
||||
/*********************************************************
|
||||
* Print out driver status report
|
||||
*********************************************************/
|
||||
@@ -257,17 +230,17 @@ static int set_status(int card, int signal)
|
||||
char buff[BUFF_SIZE];
|
||||
int rtnval, rtn_state;
|
||||
double motorData;
|
||||
SINPUTS inputs;
|
||||
epicsUInt8 Lswitch;
|
||||
bool plusdir, ls_active = false;
|
||||
msta_field status;
|
||||
|
||||
cntrl = (struct IM483controller *) motor_state[card]->DevicePrivate;
|
||||
input_config *confptr = cntrl->inconfig;
|
||||
motor_info = &(motor_state[card]->motor_info[signal]);
|
||||
nodeptr = motor_info->motor_motion;
|
||||
status.All = motor_info->status.All;
|
||||
|
||||
send_mess(card, "PR MV", MDrive_axis[signal]);
|
||||
eat_garbage(card, buff, 1);
|
||||
rtn_state = recv_mess(card, buff, 1);
|
||||
if (rtn_state > 0)
|
||||
{
|
||||
@@ -303,7 +276,6 @@ static int set_status(int card, int signal)
|
||||
*/
|
||||
|
||||
send_mess(card, "PR P", MDrive_axis[signal]);
|
||||
eat_garbage(card, buff, 1);
|
||||
recv_mess(card, buff, 1);
|
||||
|
||||
motorData = atof(buff);
|
||||
@@ -325,31 +297,53 @@ static int set_status(int card, int signal)
|
||||
|
||||
plusdir = (status.Bits.RA_DIRECTION) ? true : false;
|
||||
|
||||
send_mess(card, "PR IN", MDrive_axis[signal]);
|
||||
eat_garbage(card, buff, 1);
|
||||
recv_mess(card, buff, 1);
|
||||
inputs.All = atoi(buff);
|
||||
|
||||
/* Set limit switch error indicators. */
|
||||
if (inputs.Bits.ls_plus == 0)
|
||||
if (confptr->plusLS == 0 || confptr->minusLS == 0)
|
||||
{
|
||||
status.Bits.RA_PLUS_LS = 1;
|
||||
if (plusdir == true)
|
||||
ls_active = true;
|
||||
}
|
||||
else
|
||||
status.Bits.RA_PLUS_LS = 0;
|
||||
|
||||
if (inputs.Bits.ls_minus == 0)
|
||||
{
|
||||
status.Bits.RA_MINUS_LS = 1;
|
||||
if (plusdir == false)
|
||||
ls_active = true;
|
||||
}
|
||||
else
|
||||
status.Bits.RA_PLUS_LS = 0;
|
||||
status.Bits.RA_MINUS_LS = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buff, "PR I%d", confptr->plusLS);
|
||||
send_mess(card, buff, MDrive_axis[signal]);
|
||||
recv_mess(card, buff, 1);
|
||||
Lswitch = atoi(buff);
|
||||
|
||||
status.Bits.RA_HOME = (inputs.Bits.homels) ? 1 : 0;
|
||||
/* Set limit Lswitch error indicators. */
|
||||
if (Lswitch != 0)
|
||||
{
|
||||
status.Bits.RA_PLUS_LS = 1;
|
||||
if (plusdir == true)
|
||||
ls_active = true;
|
||||
}
|
||||
else
|
||||
status.Bits.RA_PLUS_LS = 0;
|
||||
|
||||
sprintf(buff, "PR I%d", confptr->minusLS);
|
||||
send_mess(card, buff, MDrive_axis[signal]);
|
||||
recv_mess(card, buff, 1);
|
||||
Lswitch = atoi(buff);
|
||||
|
||||
if (Lswitch != 0)
|
||||
{
|
||||
status.Bits.RA_MINUS_LS = 1;
|
||||
if (plusdir == false)
|
||||
ls_active = true;
|
||||
}
|
||||
else
|
||||
status.Bits.RA_MINUS_LS = 0;
|
||||
}
|
||||
|
||||
if (confptr->homeLS == 0)
|
||||
status.Bits.RA_HOME = 0;
|
||||
else
|
||||
{
|
||||
sprintf(buff, "PR I%d", confptr->homeLS);
|
||||
send_mess(card, buff, MDrive_axis[signal]);
|
||||
recv_mess(card, buff, 1);
|
||||
Lswitch = atoi(buff);
|
||||
status.Bits.RA_HOME = (Lswitch) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* !!! Assume no closed-looped control!!!*/
|
||||
status.Bits.EA_POSITION = 0;
|
||||
@@ -364,7 +358,6 @@ static int set_status(int card, int signal)
|
||||
else
|
||||
{
|
||||
send_mess(card, "PR C2", MDrive_axis[signal]);
|
||||
eat_garbage(card, buff, 1);
|
||||
recv_mess(card, buff, 1);
|
||||
motorData = atof(buff);
|
||||
motor_info->encoder_position = (int32_t) motorData;
|
||||
@@ -445,44 +438,6 @@ static RTN_STATUS send_mess(int card, char const *com, char *name)
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************/
|
||||
/* eat garbage characters from the MDrive board */
|
||||
/* eat_garbage() */
|
||||
/*****************************************************/
|
||||
static int eat_garbage(int card, char *com, int flag)
|
||||
{
|
||||
struct IM483controller *cntrl;
|
||||
int timeout = 0;
|
||||
int nread = 0;
|
||||
asynStatus status = asynError;
|
||||
int eomReason;
|
||||
|
||||
/* Check that card exists */
|
||||
if (!motor_state[card])
|
||||
return(ERROR);
|
||||
|
||||
cntrl = (struct IM483controller *) motor_state[card]->DevicePrivate;
|
||||
|
||||
if (flag == FLUSH)
|
||||
pasynOctetSyncIO->flush(cntrl->pasynUser);
|
||||
else
|
||||
status = pasynOctetSyncIO->read(cntrl->pasynUser, com, BUFF_SIZE,
|
||||
timeout, &nread, &eomReason);
|
||||
|
||||
Debug(2, "eat_garbage(): nread = %i\n", nread);
|
||||
|
||||
if ((status != asynSuccess) || (nread <= 0))
|
||||
{
|
||||
Debug(2, "eat_garbage(): com = \"%s\"\n", com);
|
||||
com[0] = '\0';
|
||||
nread = 0;
|
||||
}
|
||||
|
||||
/*Debug(2, "eat_garbage(): message = \"%s\"\n", com);*/
|
||||
return (nread);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************/
|
||||
/* receive a message from the MDrive board */
|
||||
/* recv_mess() */
|
||||
@@ -490,7 +445,7 @@ static int eat_garbage(int card, char *com, int flag)
|
||||
static int recv_mess(int card, char *com, int flag)
|
||||
{
|
||||
struct IM483controller *cntrl;
|
||||
int timeout = 0;
|
||||
const double timeout = 1.0;
|
||||
int nread = 0;
|
||||
asynStatus status = asynError;
|
||||
int eomReason;
|
||||
@@ -523,7 +478,7 @@ static int recv_mess(int card, char *com, int flag)
|
||||
/* MDriveSetup() */
|
||||
/*****************************************************/
|
||||
RTN_STATUS
|
||||
MDriveSetup(int num_cards, /* maximum number of controllers in system. */
|
||||
MDriveSetup(int num_cards, /* maximum number of chains in system. */
|
||||
int scan_rate) /* polling rate - 1/60 sec units. */
|
||||
{
|
||||
int itera;
|
||||
@@ -560,8 +515,8 @@ MDriveSetup(int num_cards, /* maximum number of controllers in system. */
|
||||
/* MDriveConfig() */
|
||||
/*****************************************************/
|
||||
RTN_STATUS
|
||||
MDriveConfig(int card, /* card being configured */
|
||||
const char *name) /* MPF server task name */
|
||||
MDriveConfig(int card, /* chain being configured */
|
||||
const char *name) /* ASYN port name */
|
||||
{
|
||||
struct IM483controller *cntrl;
|
||||
|
||||
@@ -608,7 +563,7 @@ static int motor_init()
|
||||
|
||||
brdptr = motor_state[card_index];
|
||||
brdptr->ident[0] = (char) NULL; /* No controller identification message. */
|
||||
brdptr->cmnd_response = true;
|
||||
brdptr->cmnd_response = false;
|
||||
total_cards = card_index + 1;
|
||||
cntrl = (struct IM483controller *) brdptr->DevicePrivate;
|
||||
|
||||
@@ -634,7 +589,6 @@ static int motor_init()
|
||||
do
|
||||
{
|
||||
send_mess(card_index, "PR VR", MDrive_axis[total_axis]);
|
||||
eat_garbage(card_index, buff, 1);
|
||||
status = recv_mess(card_index, buff, 1);
|
||||
retry++;
|
||||
} while (status == 0 && retry < 3);
|
||||
@@ -645,15 +599,20 @@ static int motor_init()
|
||||
strcpy(brdptr->ident, buff);
|
||||
}
|
||||
brdptr->total_axis = total_axis;
|
||||
cntrl->inconfig = (input_config *) malloc(
|
||||
sizeof(struct IM483controller) * total_axis);
|
||||
}
|
||||
|
||||
if (success_rtn == asynSuccess && total_axis > 0)
|
||||
{
|
||||
input_config *confptr = cntrl->inconfig;
|
||||
|
||||
brdptr->localaddr = (char *) NULL;
|
||||
brdptr->motor_in_motion = 0;
|
||||
|
||||
for (motor_index = 0; motor_index < total_axis; motor_index++)
|
||||
{
|
||||
int itera;
|
||||
struct mess_info *motor_info = &brdptr->motor_info[motor_index];
|
||||
|
||||
motor_info->status.All = 0;
|
||||
@@ -673,6 +632,50 @@ static int motor_init()
|
||||
motor_info->status.Bits.EA_PRESENT = 1;
|
||||
}
|
||||
|
||||
/* Determine input configuration. */
|
||||
confptr->homeLS = confptr->minusLS = confptr->plusLS = 0;
|
||||
|
||||
for (itera = 1; itera <= 4; itera++)
|
||||
{
|
||||
int type, active;
|
||||
|
||||
sprintf(buff, "PR S%d", itera);
|
||||
send_mess(card_index, buff, MDrive_axis[motor_index]);
|
||||
status = recv_mess(card_index, buff, 1);
|
||||
if (status == 0)
|
||||
{
|
||||
errlogPrintf("Error reading I/O configuration.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
status = sscanf(buff, "%d,%d", &type, &active);
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1: // Home switch.
|
||||
confptr->homeLS = itera;
|
||||
break;
|
||||
case 2: // Plus limit switch.
|
||||
confptr->plusLS = itera;
|
||||
break;
|
||||
case 3: // Minus limit switch.
|
||||
confptr->minusLS = itera;
|
||||
break;
|
||||
default:
|
||||
errlogPrintf("Invalid I/O type: %d.\n", type);
|
||||
|
||||
}
|
||||
}
|
||||
// Test for missing configuration.
|
||||
if (confptr->minusLS == 0 || confptr->plusLS == 0)
|
||||
{
|
||||
const char p_label[6] = "Plus", m_label[6] = "Minus";
|
||||
errlogPrintf("MDrive chain #%d, motor #%d %s LS not configured.\n",
|
||||
card_index, motor_index,
|
||||
(confptr->minusLS == 0) ? m_label : p_label);
|
||||
}
|
||||
|
||||
set_status(card_index, motor_index); /* Read status of each motor */
|
||||
}
|
||||
}
|
||||
@@ -688,7 +691,9 @@ static int motor_init()
|
||||
free_list.head = (struct mess_node *) NULL;
|
||||
free_list.tail = (struct mess_node *) NULL;
|
||||
|
||||
epicsThreadCreate((char *) "MDrive_motor", 64, 5000, (EPICSTHREADFUNC) motor_task, (void *) &targs);
|
||||
epicsThreadCreate((char *) "MDrive_motor", 64,
|
||||
epicsThreadGetStackSize(epicsThreadStackMedium),
|
||||
(EPICSTHREADFUNC) motor_task, (void *) &targs);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user