Removed OrielSrc; Added motorOriel submodule

This commit is contained in:
kpetersn
2019-04-05 16:48:22 -05:00
parent cca5f63a8d
commit 1e2695a461
12 changed files with 5 additions and 1535 deletions
+3
View File
@@ -31,3 +31,6 @@
[submodule "motorNPoint"]
path = motorNPoint
url = https://github.com/epics-motor/motorNPoint.git
[submodule "modules/motorOriel"]
path = modules/motorOriel
url = https://github.com/epics-motor/motorOriel.git
+1
View File
@@ -16,6 +16,7 @@ SUBMODULES += motorKohzu
SUBMODULES += motorMclennan
SUBMODULES += motorMicroMo
SUBMODULES += motorNPoint
SUBMODULES += motorOriel
# Allow sites to add extra submodules
-include Makefile.local
Submodule modules/motorOriel added at fb513f30b8
-3
View File
@@ -42,9 +42,6 @@ PC6KSrc_DEPEND_DIRS = MotorSrc
DIRS += NewFocusSrc
NewFocusSrc_DEPEND_DIRS = MotorSrc
DIRS += OrielSrc
OrielSrc_DEPEND_DIRS = MotorSrc
DIRS += ThorLabsSrc
ThorLabsSrc_DEPEND_DIRS = MotorSrc
-22
View File
@@ -1,22 +0,0 @@
# Makefile
TOP = ../..
include $(TOP)/configure/CONFIG
# The following are used for debugging messages.
USR_CXXFLAGS += -DDEBUG
OPT_CXXFLAGS = -g -O0
DBD += devOriel.dbd
LIBRARY_IOC = Oriel
# Intelligent Motion Systems driver support.
SRCS += OrielRegister.cc
SRCS += devEMC18011.cc drvEMC18011.cc
Oriel_LIBS += motor asyn
Oriel_LIBS += $(EPICS_BASE_IOC_LIBS)
include $(TOP)/configure/RULES
-65
View File
@@ -1,65 +0,0 @@
/*
FILENAME... OrielRegister.cc
USAGE... Register Oriel Encoder/Motor Mike motor device driver shell commands.
*/
/*****************************************************************
COPYRIGHT NOTIFICATION
*****************************************************************
(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO
This software was developed under a United States Government license
described on the COPYRIGHT_UniversityOfChicago file included as part
of this distribution.
**********************************************************************/
#include <iocsh.h>
#include "OrielRegister.h"
#include "epicsExport.h"
extern "C"
{
// Oriel Setup arguments
static const iocshArg setupArg0 = {"Max. controller count", iocshArgInt};
static const iocshArg setupArg1 = {"Polling rate", iocshArgInt};
// Oriel Config arguments
static const iocshArg configArg0 = {"Card being configured", iocshArgInt};
static const iocshArg configArg1 = {"asyn port name", iocshArgString};
static const iocshArg * const OrielSetupArgs[2] = {&setupArg0, &setupArg1};
static const iocshArg * const OrielConfigArgs[2] = {&configArg0, &configArg1};
static const iocshFuncDef setupEMC18011 = {"EMC18011Setup",2, OrielSetupArgs};
static const iocshFuncDef configEMC18011 = {"EMC18011Config", 2, OrielConfigArgs};
static void setupEMC18011CallFunc(const iocshArgBuf *args)
{
EMC18011Setup(args[0].ival, args[1].ival);
}
static void configEMC18011CallFunc(const iocshArgBuf *args)
{
EMC18011Config(args[0].ival, args[1].sval);
}
static void OrielRegister(void)
{
iocshRegister(&setupEMC18011, setupEMC18011CallFunc);
iocshRegister(&configEMC18011, configEMC18011CallFunc);
}
epicsExportRegistrar(OrielRegister);
} // extern "C"
-47
View File
@@ -1,47 +0,0 @@
/*
FILENAME... OrielRegister.h
USAGE... This file contains function prototypes for Oriel IOC shell commands.
Version: 1.4
Modified By: rivers
Last Modified: 2004/07/28 18:45:16
*/
/*
* Original Author: Ron Sluiter
* Date: 05/19/03
*
* 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:
* -----------------
*/
#include "motor.h"
#include "motordrvCom.h"
/* Function prototypes. */
extern RTN_STATUS EMC18011Setup(int, int);
extern RTN_STATUS EMC18011Config(int, const char *);
extern RTN_STATUS EMC18011UpLoad(int, const char *, const char *);
-136
View File
@@ -1,136 +0,0 @@
Spectra-Physics Oriel Encoder Mike Motor Controllers
==============================================================================
Model: 18011 (Three motor controller/driver)
RS232 Configuration
----------------------------------
Default: 4800, 8, 1, N (DB25) - Internal Jumper Setting to 19200
Software Setup: REMOTE/LOCAL switching ("R", "L")
Controller Specifications
------------------------------------------
No Software configuration available
Position Units: Microns (format %.1f)
Precision: 0.1 microns
Limits: 0.1 to 999999 (maximum string length = 7char)
Velocity Units: um/s (format %.1f)
From To Precision
0.5 4.99 %.2f
5.0 49.9 %.1f
50 200 %.0f
Single Character Commands
------------------------------------------
Command Successful Response Failure Response
Local
"L" "\r\n\rOFF LINE\r\n" "" (Already in local)
Remote
"R" "\rON LINE\r\n" "" (Already in remote)
Jog +
">" "\r\n" "" (Already moving)
Jog -
"<" "\r\n" "" (Already moving)
Stop
"S" "STOP\r\n" "" (Already stopped)
Multi Character Commands
------------------------------------------
Command Successful Response Failure Response
Zero Abs
Position "CA\r" "CA\r\n" "" or (Motor in motion)
"xxxx.x\r\n" (position info???)
Zero Rel
Position "CR\r" "CR\r\n" "" (when motor in motion)
Goto Abs
Position "Gxxx.x\r" "Gxxx.x\r\r\n" "" (when motor in motion)
Rel Position "Txxx.x\r" "Txxx.x\r\r\n" "" (when motor in motion)
Set Velocity
"Vx.x\r" "Vx.x\r\r\n" "" (when motor in motion)
"Vx.x\r\r\n" (Echos command even if invalid)
Select Axis
"Mx\r" "Mx\r\r\n" "" (when motor in motion)
Inquiries Commands
------------------------------------------
Command Successful Response Failure Response
Abs Pos "A\r" "xxxx.x\r\n" none
Abs Pos "Z" "<char>" none
a,b,c,d,e
============== Build Info ======================
xxxApp/src
Makefile
--------
xxx_Common_LIBS += Parker
xxCommonInclude.dbd
-------------------
include "devEMC18011.dbd"
============= IOC Boot info ======================
iocBoot/iocLinux
serial.cmd
----------
# serial 1 is a RS232 link to a Oriel Encoder Mike Controller
drvAsynSerialPortConfigure("serial1", "/dev/ttyS0", 0, 0, 0)
asynSetOption(serial1,0,baud,4800)
asynOctetSetOutputEos("serial1",0,"\r")
asynOctetSetInputEos("serial1",0,"\n")
.
.
# Oriel Encoder Mike - driver setup parameters:
# (1) maximum number of controllers in system
# (2) motor task polling rate (min=1Hz, max=60Hz)
EMC18011Setup(2, 60)
# Oriel Encoder Mike driver configuration parameters:
# (1) controller being configured
# (2) asyn port name (string)
EMC18011Config(0, "serial1")
EMC18011Config(1, "serial3")
motor.substitutions
-------------------
Set the DTYPE column to "EMC18011"
=================== Motor Record Setup ================================
EGU = microns
VELO = [0.5 to 200] Maximum and Base velocity not used
BDST = 0 Controller does its own backlash
MRES = .010 (set to velocity resolution, position resolution is .10 microns)
RDBD = .05 (position resolution is only 0.1 - will be rounded up)
-418
View File
@@ -1,418 +0,0 @@
/*
FILENAME... devEMC18011.cc
USAGE... Motor record device level support for Parker Compumotor drivers
*/
/*
* Original Author: Mark Rivers
* Date: 10/20/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:
* -----------------
* .01 04-07-05 jps initialized from devMM4000.cc
*/
#include <string.h>
#include <math.h>
#include <errlog.h>
#include "motorRecord.h"
#include "motor.h"
#include "motordevCom.h"
#include "drvEMC18011.h"
#include "epicsExport.h"
#define STATIC static
extern struct driver_table EMC18011_access;
/* ----------------Create the dsets for devEMC18011----------------- */
STATIC struct driver_table *drvtabptr;
STATIC long EMC18011_init(int);
STATIC long EMC18011_init_record(void *);
STATIC long EMC18011_start_trans(struct motorRecord *);
STATIC RTN_STATUS EMC18011_build_trans(motor_cmnd, double *, struct motorRecord *);
STATIC RTN_STATUS EMC18011_end_trans(struct motorRecord *);
struct motor_dset devEMC18011 =
{
{8, NULL, (DEVSUPFUN) EMC18011_init, (DEVSUPFUN) EMC18011_init_record, NULL},
motor_update_values,
EMC18011_start_trans,
EMC18011_build_trans,
EMC18011_end_trans
};
extern "C" {epicsExportAddress(dset,devEMC18011);}
/* --------------------------- program data --------------------- */
/* This table is used to define the command types */
/* WARNING! this must match "motor_cmnd" in motor.h */
static msg_types EMC18011_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 */
};
static struct board_stat **EMC18011_cards;
/* --------------------------- program data --------------------- */
/* initialize device support for EMC18011 stepper motor */
STATIC long EMC18011_init(int after)
{
long rtnval;
if (!after)
{
drvtabptr = &EMC18011_access;
(drvtabptr->init)();
}
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &EMC18011_cards);
return(rtnval);
}
/* initialize a record instance */
STATIC long EMC18011_init_record(void *arg)
{
struct motorRecord *mr = (struct motorRecord *) arg;
/* Disable change of direction testing in record support */
/* This device does it's own backlash correction */
mr->ntm = menuYesNoNO;
return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr, drvtabptr, EMC18011_cards));
}
/* start building a transaction */
STATIC long EMC18011_start_trans(struct motorRecord *mr)
{
return(motor_start_trans_com(mr, EMC18011_cards));
}
/* end building a transaction */
STATIC RTN_STATUS EMC18011_end_trans(struct motorRecord *mr)
{
return(motor_end_trans_com(mr, drvtabptr));
}
/* add a part to the transaction */
STATIC RTN_STATUS EMC18011_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 mess_info *motor_info;
struct EMC18011Controller *cntrl;
char buff[110];
int signal, axis, card, intval;
double dval, cntrl_units;
unsigned int size;
bool sendMsg;
bool switchMotor;
RTN_STATUS rtnval;
rtnval = OK;
buff[0] = '\0';
sendMsg = true;
switchMotor = false;
/* Protect against NULL pointer with WRTITE_MSG(GO/STOP_AXIS/GET_INFO, NULL). */
intval = (parms == NULL) ? 0 : NINT(parms[0]);
dval = (parms == NULL) ? 0 : *parms;
motor_start_trans_com(mr, EMC18011_cards);
motor_call = &(trans->motor_call);
card = motor_call->card;
signal = motor_call->signal;
axis = signal+1; /* Motors start at 1 */
motor_call->type = EMC18011_table[command];
brdptr = (*trans->tabptr->card_array)[card];
if (brdptr == NULL)
return(rtnval = ERROR);
cntrl = (struct EMC18011Controller *) brdptr->DevicePrivate;
/* 6K Controllers expect Velocity and Acceleration settings in Revs/sec/sec */
cntrl_units = dval * cntrl->drive_resolution;
if (EMC18011_table[command] > motor_call->type)
motor_call->type = EMC18011_table[command];
if (trans->state != BUILD_STATE)
return(rtnval = ERROR);
/* SPECIAL: This controller can only address one motor at a time
* Other motion requests have to wait until the current motion
* is complete. Depend on motorRecord retries to complete pending
* requests. Allow record to stop current motion.
* Switch message type to INFO to get done flag
*/
switch (command)
{
case JOG:
case LOAD_POS:
case SET_VELOCITY:
case GET_INFO:
/* Try to get motorLock then switch active motor */
if (cntrl->motorLock->tryWait())
{
if (cntrl->motorSelect != signal)
{
cntrl->motorSelect = signal;
sprintf(buff, "M%d", axis);
strcat(motor_call->message, buff);
motor_call->type = IMMEDIATE; /* Assure message gets sent */
rtnval = motor_end_trans_com(mr, drvtabptr);
rtnval = (RTN_STATUS) motor_start_trans_com(mr, EMC18011_cards);
motor_call->type = EMC18011_table[command];
}
}
break;
default:
break;
}
/* Only communicate to selected motor */
if (cntrl->motorSelect != signal)
{
/* Assure continuous retries until other motion complete */
motor_call->type = INFO;
if (mr->rcnt > 0)
mr->rcnt--;
return(rtnval = OK);
}
if (command == PRIMITIVE && mr->init != NULL && strlen(mr->init) != 0)
{
strcat(motor_call->message, mr->init);
rtnval = motor_end_trans_com(mr, drvtabptr);
rtnval = (RTN_STATUS) motor_start_trans_com(mr, EMC18011_cards);
motor_call->type = EMC18011_table[command];
}
switch (command)
{
case MOVE_ABS:
case MOVE_REL:
case JOG:
if (strlen(mr->prem) != 0)
{
strcat(motor_call->message, mr->prem);
rtnval = motor_end_trans_com(mr, drvtabptr);
rtnval = (RTN_STATUS) motor_start_trans_com(mr, EMC18011_cards);
motor_call->type = EMC18011_table[command];
}
if (strlen(mr->post) != 0)
motor_call->postmsgptr = (char *) &mr->post;
break;
default:
break;
}
/* Parker 6K controllers do not support multiple commands per line */
switch (command)
{
case MOVE_ABS:
case MOVE_REL:
{
char *xstart = &buff[1];
buff[0] = (command == MOVE_ABS) ? 'G' : 'T';
/* Maximum length for distance is 7 characters. */
sprintf(xstart, "%.1f", cntrl_units);
if (strlen(xstart) > 7)
/* Sacrifice precision for quantity */
sprintf(xstart, "%.0f", cntrl_units);
if (strlen(xstart) > 7)
{
/* Put out maximum distance string */
if (cntrl_units < 0)
strcpy(xstart, "-999999");
else
strcpy(xstart, "9999999");
}
}
break;
case HOME_FOR:
case HOME_REV:
rtnval = ERROR;
sendMsg = false;
break;
case LOAD_POS:
/* Only Zero setting is allowed */
if (intval == 0)
strcpy(buff, "CA");
else
sendMsg = false;
break;
case SET_VEL_BASE:
sendMsg = false;
break; /* EMC18011 does not use base velocity */
case SET_VELOCITY:
/* Velocity resolution decrease at greater speeds. */
if (cntrl_units < 5.0)
sprintf(buff, "V%.2f", cntrl_units);
else if (cntrl_units < 50.0)
sprintf(buff, "V%.1f", cntrl_units);
else if (cntrl_units < 200.0)
sprintf(buff, "V%.0f", cntrl_units);
else
/* Set speed to maximum */
strcpy(buff, "V200");
break;
case SET_ACCEL:
sendMsg = false;
break;
case GO:
/* Send command because generic device support will expect a
* a response */
strcpy(buff, "A");
break;
case SET_ENC_RATIO:
rtnval = ERROR;
sendMsg = 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 */
sendMsg = false;
break;
case STOP_AXIS:
strcpy(buff, "S");
break;
case JOG:
/* Velocity resolution decrease at greater speeds. */
if (cntrl_units < 5.0)
sprintf(buff, "V%.2f", cntrl_units);
else if (cntrl_units < 50.0)
sprintf(buff, "V%.1f", cntrl_units);
else if (cntrl_units < 200.0)
sprintf(buff, "V%.0f", cntrl_units);
else
/* Set speed to maximum */
strcpy(buff, "V200");
strcat(motor_call->message, buff);
rtnval = motor_end_trans_com(mr, drvtabptr);
rtnval = (RTN_STATUS) motor_start_trans_com(mr, EMC18011_cards);
motor_call->type = EMC18011_table[command];
if (intval >= 0)
strcpy(buff, ">");
else
strcpy(buff, "<");
break;
case SET_PGAIN:
case SET_IGAIN:
case SET_DGAIN:
rtnval = ERROR;
sendMsg = false;
break;
case ENABLE_TORQUE:
case DISABL_TORQUE:
rtnval = ERROR;
sendMsg = false;
break;
case SET_HIGH_LIMIT:
case SET_LOW_LIMIT:
rtnval = ERROR;
sendMsg = false;
break;
default:
sendMsg = false;
rtnval = ERROR;
}
if (sendMsg == true)
{
size = strlen(buff);
if (size > sizeof(buff) || (strlen(motor_call->message) + size) > MAX_MSG_SIZE)
errlogMessage("EMC18011_build_trans(): buffer overflow.\n");
else
{
strcat(motor_call->message, buff);
motor_end_trans_com(mr, drvtabptr);
}
}
return(rtnval);
}
-6
View File
@@ -1,6 +0,0 @@
# Oriel Encoder/Motor Mike Device Driver support.
device(motor,VME_IO,devEMC18011,"EMC18011")
driver(drvEMC18011)
registrar(OrielRegister)
variable(drvEMC18011debug)
-754
View File
@@ -1,754 +0,0 @@
/*
FILENAME... drvEMC18011.cc
USAGE... Motor record driver level support for Spectra-Physics
Encoder Mike Controller (Model: 18011)
*/
/*
* Original Author: Mark Rivers
* Date: 10/20/97
* Current Author: J. Sullivan
*
* 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-08-05 jps initialized from drvMM4000.cc
*/
#include <string.h>
#include <ctype.h> /* isascii functions */
#include <math.h>
#include <stdio.h>
#include <epicsThread.h>
#include <drvSup.h>
#include <errlog.h>
#include <stdlib.h>
#include "motor.h"
#include "OrielRegister.h"
#include "drvEMC18011.h"
#include "asynOctetSyncIO.h"
#include "epicsExport.h"
#define CMD_STATUS "Z"
#define CMD_POS "A"
#define CMD_STOP "S"
#define CMD_LOCAL "L"
#define CMD_REMOTE "R"
#define CMD_SELECT "M"
#define RTN_REMOTE "ON LINE"
#define RTN_READY "RE" // READY
#define RTN_OVERLOAD "OV" // OVERLOAD
#define EMC18011_NUM_CARDS 16
#define BUFF_SIZE 120 /* Maximum length of string to/from EMC18011 */
#define TIMEOUT 1.0 /* Command timeout in sec. */
/* Delay after START_MOTION before a status update is possible */
#define MOTION_DELAY 0.1
/*----------------debugging-----------------*/
volatile int drvEMC18011debug = 0;
extern "C" {epicsExportAddress(int, drvEMC18011debug);}
static inline void Debug(int level, const char *format, ...) {
#ifdef DEBUG
if (level < drvEMC18011debug) {
va_list pVar;
va_start(pVar, format);
vprintf(format, pVar);
va_end(pVar);
}
#endif
}
/* --- Local data. --- */
int EMC18011_num_cards = 0;
/* Local data required for every driver; see "motordrvComCode.h" */
#include "motordrvComCode.h"
/* This is a temporary fix to introduce a delayed reading of the motor
* position after a move completes
*/
volatile double drvEMC18011ReadbackDelay = 0.;
/*----------------functions-----------------*/
static int recv_mess(int card, char *com, int flag);
static int recv_mess(int card, char *com, int flag, int recv_len);
static RTN_STATUS send_mess(int card, char const *, char *name);
static int send_recv_mess(int card, char const *send_com, char *recv_com);
static int send_recv_mess(int card, char const *send_com, char *recv_com,
int recv_len);
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 EMC18011_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 drvEMC18011_drvet
{
long number;
long (*report) (int);
long (*init) (void);
} drvEMC18011 = {2, report, init};
extern "C" {epicsExportAddress(drvet, drvEMC18011);}
static struct thread_args targs = {SCAN_RATE, &EMC18011_access, MOTION_DELAY};
/*********************************************************
* Print out driver status report
*********************************************************/
static long report(int level)
{
int card;
if (EMC18011_num_cards <=0)
printf(" No EMC18011 controllers configured.\n");
else
{
for (card = 0; card < EMC18011_num_cards; card++)
{
struct controller *brdptr = motor_state[card];
if (brdptr == NULL)
printf(" EMC18011 controller %d connection failed.\n", card);
else
{
struct EMC18011Controller *cntrl;
cntrl = (struct EMC18011Controller *) brdptr->DevicePrivate;
printf(" EMC18011 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 (EMC18011_num_cards <= 0)
{
Debug(1, "init(): EMC18011 driver disabled. EMC18011Setup() missing from startup script.\n");
}
return((long) 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 EMC18011Controller *cntrl;
struct mess_node *nodeptr;
register struct mess_info *motor_info;
char send_buff[80];
char Zstatus;
char *recvStr;
char *brkptr, *endptr;
int rtn_state;
int recvCnt;
int motorData;
int motor;
double datad;
bool recvRetry;
bool plusdir, ls_active = false;
msta_field status;
cntrl = (struct EMC18011Controller *) motor_state[card]->DevicePrivate;
motor_info = &(motor_state[card]->motor_info[signal]);
status.All = motor_info->status.All;
motor = signal+1;
recvRetry = true;
/* Initialize motorData in-order to detect motor not moving */
motorData = motor_info->position;
/* Status updates only available on selected motor */
if (signal == cntrl->motorSelect)
{
recvStr = cntrl->recv_string[0];
/* Get Zstatus (one character motion indicator) */
recvCnt = send_recv_mess(card, CMD_STATUS, recvStr, 1);
if (recvCnt == 1)
{
/* Test for valid reply */
Zstatus = *recvStr;
if (Zstatus >= Z_STOPPED && Zstatus <= Z_LSUP)
recvRetry = false;
else
Zstatus = Z_RUNUP;
/* Update position after motion has stopped */
/* NOTE: This controller does not provide reliable position
* feedback during motion (BUG?) */
if (Zstatus != Z_RUNUP && Zstatus != Z_RUNDOWN)
{
recvCnt = send_recv_mess(card, CMD_POS, recvStr);
if (recvCnt > 0)
{
datad = strtod(recvStr, &endptr);
if (brkptr != endptr)
{
motorData = NINT(datad / cntrl->drive_resolution);
/* Release motor */
cntrl->motorSelect = -1;
cntrl->motorLock->signal();
recvRetry = false;
}
else
/* Don't indicate done until we get a valid position */
Zstatus = Z_RUNUP;
}
}
}
}
else
{
/* Not the selected motor - no new information */
recvRetry = false;
Zstatus = Z_STOPPED;
epicsThreadSleep(0.1); /* Pretend we did something - in-case of record retry loop */
}
/* Check for normal look termination - all queries successful */
if (recvRetry == false)
cntrl->status = NORMAL;
else
{
if (cntrl->status == NORMAL)
{
epicsThreadSleep(MOTION_DELAY);
cntrl->status = RETRY;
}
else
cntrl->status = COMM_ERR;
}
if (cntrl->status != NORMAL)
{
if (cntrl->status == COMM_ERR)
{
status.Bits.CNTRL_COMM_ERR = 1;
status.Bits.RA_PROBLEM = 1;
rtn_state = 1;
goto exit;
}
else
{
rtn_state = 0;
goto exit;
}
}
else
status.Bits.CNTRL_COMM_ERR = 0;
nodeptr = motor_info->motor_motion;
/*
* Parse the status/fault string
*/
Debug(5, "set_status(): status = %c\n", Zstatus);
plusdir = (Zstatus == Z_STOPPED || Zstatus == Z_RUNUP || Zstatus == Z_LSUP) ? true : false;
status.Bits.RA_DIRECTION = plusdir ? 1 : 0;
status.Bits.RA_HOME = 0;
status.Bits.RA_DONE = (Zstatus == Z_STOPPED) ? 1 : 0;
/* Set Travel limit switch status bits. */
status.Bits.RA_PLUS_LS = (Zstatus == Z_LSUP) ? 1 : 0;
status.Bits.RA_MINUS_LS = (Zstatus == Z_LSDOWN) ? 1 : 0;
ls_active = (status.Bits.RA_PLUS_LS || status.Bits.RA_MINUS_LS) ? true : false;
/* encoder status */
status.Bits.EA_POSITION = 0;
status.Bits.EA_SLIP = 0;
status.Bits.EA_SLIP_STALL = 0;
status.Bits.EA_HOME = 0;
/* Disable no motion test - this driver does not update position */
// if (motorData == motor_info->position)
if (false)
{
if (nodeptr != 0) /* Increment counter only if motor is moving. */
motor_info->no_motion_count++;
}
else
{
motor_info->position = motorData;
motor_info->encoder_position = 0;
motor_info->no_motion_count = 0;
}
status.Bits.RA_PROBLEM = 0;
/* Parse motor velocity? */
/* NEEDS WORK */
motor_info->velocity = 0;
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)
{
strncpy(send_buff, nodeptr->postmsgptr, 80);
send_mess(card, send_buff, (char*) NULL);
nodeptr->postmsgptr = NULL;
}
exit:
motor_info->status.All = status.All;
return(rtn_state);
}
/*****************************************************/
/* send_receive a message to the EMC18011 board */
/* send_recv_mess() */
/*****************************************************/
static int send_recv_mess(int card, char const *send_com, char *recv_com)
{
return(send_recv_mess(card, send_com, recv_com, 0));
}
static int send_recv_mess(int card, char const *send_com, char *recv_com,
int recv_len)
{
struct EMC18011Controller *cntrl;
int sendLen, recvLen;
size_t nwrite;
size_t nread = 0;
double timeout = 0.;
asynStatus status;
int eomReason;
sendLen = strlen(send_com);
/* recv_len argument used to request specific number of response characters */
recvLen = recv_len ? recv_len : EMC18011_MSG_SIZE;
recv_com[0] = '\0';
if (sendLen > MAX_MSG_SIZE)
{
errlogMessage("drvEMC18011.c:send_recv_mess(); message size violation.\n");
return(ERROR);
}
else if (sendLen == 0) /* Normal exit on empty input message. */
return(OK);
if (!motor_state[card])
{
errlogPrintf("drvEMC18011.c:send_recv_mess() - invalid card #%d\n", card);
return(ERROR);
}
Debug(2, "send_recv_mess(): message = %s\n", send_com);
cntrl = (struct EMC18011Controller *) motor_state[card]->DevicePrivate;
timeout = TIMEOUT;
/* flush any junk at input port - should not be any data available */
// pasynOctetSyncIO->flush(cntrl->pasynUser);
/* Perform atomic write/read operation */
status = pasynOctetSyncIO->writeRead(cntrl->pasynUser, send_com, sendLen,
recv_com, recvLen ,
TIMEOUT, &nwrite, &nread, &eomReason);
if ((status != asynSuccess) || (nread <= 0))
{
recv_com[0] = '\0';
nread = 0;
Debug(1, "send_recv_mess(): TIMEOUT sending = '%s'\n", send_com);
}
Debug(2, "send_recv_mess(): recv message = '%s'\n", recv_com);
return(nread);
}
/*****************************************************/
/* send a message to the EMC18011 board */
/* send_mess() */
/*****************************************************/
static RTN_STATUS send_mess(int card, char const *com, char *name)
{
struct EMC18011Controller *cntrl;
int size;
size_t nwrite;
size = strlen(com);
if (size > MAX_MSG_SIZE)
{
errlogMessage("drvEMC18011.c:send_mess(); message size violation.\n");
return(ERROR);
}
else if (size == 0) /* Normal exit on empty input message. */
return(OK);
if (!motor_state[card])
{
errlogPrintf("drvEMC18011.c:send_mess() - invalid card #%d\n", card);
return(ERROR);
}
if (name != NULL)
{
errlogPrintf("drvEMC18011.c:send_mess() - invalid argument = %s\n", name);
return(ERROR);
}
Debug(2, "send_mess(): message = %s\n", com);
cntrl = (struct EMC18011Controller *) motor_state[card]->DevicePrivate;
/* flush any junk at input port - should not be any data available */
pasynOctetSyncIO->flush(cntrl->pasynUser);
pasynOctetSyncIO->write(cntrl->pasynUser, com, strlen(com),
TIMEOUT, &nwrite);
return(OK);
}
/*
* FUNCTION... recv_mess(int card, char *com, int flag)
* recv_mess(int card, char *com, int flag, int recv_len)
*
* INPUT ARGUMENTS...
* card - controller card # (0,1,...).
* *com - caller's response buffer.
* flag | FLUSH = this flag is ignored - the receive buffer is flushed
* on every write (see write_mess())
* recvLen - receive length (optional)
* LOGIC...
* IF controller card does not exist.
* ERROR RETURN.
* ENDIF
* NORMAL RETURN.
*/
static int recv_mess(int card, char *com, int flag)
{
return(recv_mess(card, com, flag, 0));
}
static int recv_mess(int card, char *com, int flag, int recv_len)
{
struct EMC18011Controller *cntrl;
double timeout = 0.;
size_t nread = 0;
asynStatus status;
int eomReason;
int recvLen;
/* Check that card exists */
if (!motor_state[card])
return(ERROR);
cntrl = (struct EMC18011Controller *) motor_state[card]->DevicePrivate;
timeout = TIMEOUT;
/* Check if specific number of input characters requested */
recvLen = (recv_len ? recv_len : BUFF_SIZE);
status = pasynOctetSyncIO->read(cntrl->pasynUser, com, recvLen,
timeout, &nread, &eomReason);
if (nread > 0)
Debug(2, "recv_mess(): message = '%s'\n", com);
if ((status != asynSuccess) || (nread <= 0))
{
com[0] = '\0';
nread = 0;
Debug(1, "recv_mess(): TIMEOUT \n");
}
return(nread);
}
/*****************************************************/
/* Setup system configuration */
/* EMC18011Setup() */
/*****************************************************/
RTN_STATUS
EMC18011Setup(int num_cards, /* maximum number of controllers in system. */
int scan_rate) /* polling rate - 1/60 sec units. */
{
int itera;
if (num_cards < 1 || num_cards > EMC18011_NUM_CARDS)
EMC18011_num_cards = EMC18011_NUM_CARDS;
else
EMC18011_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 EMC18011Config 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(EMC18011_num_cards *
sizeof(struct controller *));
for (itera = 0; itera < EMC18011_num_cards; itera++)
motor_state[itera] = (struct controller *) NULL;
return(OK);
}
/*****************************************************/
/* Configure a controller */
/* EMC18011Config() */
/*****************************************************/
RTN_STATUS
EMC18011Config(int card, /* card being configured */
const char *name) /* asyn port name */
{
struct EMC18011Controller *cntrl;
if (card < 0 || card >= EMC18011_num_cards)
return(ERROR);
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
motor_state[card]->DevicePrivate = malloc(sizeof(struct EMC18011Controller));
cntrl = (struct EMC18011Controller *) motor_state[card]->DevicePrivate;
strcpy(cntrl->asyn_port, name);
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 EMC18011Controller *cntrl;
int card_index, motor_index;
char buff[BUFF_SIZE];
char send_buff[20];
int total_axis = 0;
int recvCnt, retryCnt;
bool cardFound = false;
asynStatus success_rtn;
initialized = true; /* Indicate that driver is initialized. */
/* Check for setup */
if (EMC18011_num_cards <= 0)
return(ERROR);
for (card_index = 0; card_index < EMC18011_num_cards; card_index++)
{
if (!motor_state[card_index])
continue;
brdptr = motor_state[card_index];
brdptr->cmnd_response = true;
total_cards = card_index + 1;
cntrl = (struct EMC18011Controller *) brdptr->DevicePrivate;
cntrl->motorLock = new epicsEvent;
/* Initialize communications channel */
success_rtn = pasynOctetSyncIO->connect(cntrl->asyn_port,
cntrl->asyn_address, &cntrl->pasynUser, NULL);
if (success_rtn == asynSuccess)
{
/* Set command End-of-string */
pasynOctetSyncIO->setInputEos(cntrl->pasynUser,
EMC18011_IN_EOS,strlen(EMC18011_IN_EOS));
pasynOctetSyncIO->setOutputEos(cntrl->pasynUser,
EMC18011_OUT_EOS,strlen(EMC18011_OUT_EOS));
/* Send a message to the board, see if it exists */
retryCnt = 0;
do
{
/* Switch to remote - test response */
recvCnt = send_recv_mess(card_index, CMD_LOCAL, buff);
recvCnt = recv_mess(card_index, buff, 0); // Could be a second message - get it
recvCnt = send_recv_mess(card_index, CMD_REMOTE, buff);
/* Check for valid response -- if not retry */
if ((recvCnt > 0) && strstr(buff, RTN_REMOTE))
cardFound = true;
} while(!cardFound && ++retryCnt < 3);
}
if (cardFound)
{
strcpy(brdptr->ident, "Oriel Encoder Mike 18011"); /* Save Controller ID */
brdptr->localaddr = (char *) NULL;
brdptr->motor_in_motion = 0;
/* Make sure that motion is stopped - cannot change motor selection */
recvCnt = send_recv_mess(card_index, CMD_STOP, buff);
/* The find how many axes this controller has - fixed number*/
total_axis = EMC18011_MAX_MOTORS;
brdptr->total_axis = total_axis;
cntrl->drive_resolution = EMC18011_RESOLUTION;
for (motor_index = 0; motor_index < total_axis; motor_index++)
{
struct mess_info *motor_info = &brdptr->motor_info[motor_index];
brdptr->motor_info[motor_index].motor_motion = NULL;
motor_info->status.All = 0;
motor_info->no_motion_count = 0;
motor_info->encoder_position = 0;
motor_info->position = 0;
/* NO Encoder support - internal closed loop controller */
motor_info->encoder_present = NO;
motor_info->status.Bits.EA_PRESENT = 0;
motor_info->pid_present = NO;
motor_info->status.Bits.GAIN_SUPPORT = 0;
/* Select motor - for status update */
sprintf(send_buff, "%s%d", CMD_SELECT, motor_index+1);
recvCnt = send_recv_mess(card_index, send_buff, buff);
cntrl->motorSelect = motor_index;
set_status(card_index, motor_index); /* Read status of each motor */
}
}
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 *) "EMC18011_motor", 64, 5000, (EPICSTHREADFUNC) motor_task, (void *) &targs);
epicsThreadCreate((char *) "EMC18011_motor",
epicsThreadPriorityMedium,
epicsThreadGetStackSize(epicsThreadStackMedium),
(EPICSTHREADFUNC) motor_task, (void *) &targs);
return(OK);
}
-84
View File
@@ -1,84 +0,0 @@
/*
FILENAME... drvEMC18011.h
USAGE... This file contains Parker Compumotor driver "include"
information that is specific to the 6K series serial controller
*/
/*
* Original Author: Mark Rivers
* Current Author: J. Sullivan
* 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:
* -----------------
* .01 09-01-06 jps initialized from drvPC6K.h
*/
#ifndef INCdrvEMC18011h
#define INCdrvEMC18011h 1
#include "motor.h"
#include "motordrvCom.h"
#include "asynDriver.h"
#include "asynOctetSyncIO.h"
#include "epicsEvent.h"
#define EMC18011_MAX_MOTORS 3
#define EMC18011_MSG_SIZE 120
#define EMC18011_STATUS_RETRY 10
/* End-of-string defines */
#define EMC18011_OUT_EOS "\r" /* Command */
#define EMC18011_IN_EOS "\n" /* Reply */
/* Although the positition resolution is fixed at 0.1um the
* velocity resolution is 0.01um/s if programmed less then 5.0 um/s */
#define EMC18011_RESOLUTION 0.01
/* Responses to 'Z' report status command - used by set_status() */
#define Z_STOPPED 'a'
#define Z_RUNDOWN 'b' /* Pos motion */
#define Z_RUNUP 'c' /* Neg. motion */
#define Z_LSDOWN 'd' /* Neg. limit switch (hard stop) */
#define Z_LSUP 'e' /* Pos limit switch (hard stop) */
/* Motion Master specific data is stored in this structure. */
struct EMC18011Controller
{
asynUser *pasynUser; /* For RS-232 */
int asyn_address; /* Use for GPIB or other address with asyn */
char asyn_port[80]; /* asyn port name */
char recv_string[2][EMC18011_MSG_SIZE]; /* Position Query result strings */
int motorSelect; /* Keep track of currently selected motor - this */
/* is the only one that can get status information */
double drive_resolution; /* This controller has a fixed drive resolution */
epicsEvent *motorLock; /* Only one axis can move at a time */
CommStatus status; /* Controller communication status. */
};
#endif /* INCdrvEMC18011h */