diff --git a/.gitmodules b/.gitmodules index f0dacc53..470e6d0d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -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 diff --git a/modules/Makefile b/modules/Makefile index 91dce565..7c2b5b77 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -16,6 +16,7 @@ SUBMODULES += motorKohzu SUBMODULES += motorMclennan SUBMODULES += motorMicroMo SUBMODULES += motorNPoint +SUBMODULES += motorOriel # Allow sites to add extra submodules -include Makefile.local diff --git a/modules/motorOriel b/modules/motorOriel new file mode 160000 index 00000000..fb513f30 --- /dev/null +++ b/modules/motorOriel @@ -0,0 +1 @@ +Subproject commit fb513f30b8e94e5434f3c7af42612b7e3cbc3728 diff --git a/motorApp/Makefile b/motorApp/Makefile index c29692d6..df5892b1 100644 --- a/motorApp/Makefile +++ b/motorApp/Makefile @@ -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 diff --git a/motorApp/OrielSrc/Makefile b/motorApp/OrielSrc/Makefile deleted file mode 100644 index e6c7e46b..00000000 --- a/motorApp/OrielSrc/Makefile +++ /dev/null @@ -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 - diff --git a/motorApp/OrielSrc/OrielRegister.cc b/motorApp/OrielSrc/OrielRegister.cc deleted file mode 100644 index ca4cfb0d..00000000 --- a/motorApp/OrielSrc/OrielRegister.cc +++ /dev/null @@ -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 -#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" diff --git a/motorApp/OrielSrc/OrielRegister.h b/motorApp/OrielSrc/OrielRegister.h deleted file mode 100644 index 6f02d417..00000000 --- a/motorApp/OrielSrc/OrielRegister.h +++ /dev/null @@ -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 *); - - diff --git a/motorApp/OrielSrc/README b/motorApp/OrielSrc/README deleted file mode 100644 index 64addeb6..00000000 --- a/motorApp/OrielSrc/README +++ /dev/null @@ -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" "" 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) - - - - - - diff --git a/motorApp/OrielSrc/devEMC18011.cc b/motorApp/OrielSrc/devEMC18011.cc deleted file mode 100644 index 4148f0e1..00000000 --- a/motorApp/OrielSrc/devEMC18011.cc +++ /dev/null @@ -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 -#include -#include -#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); -} diff --git a/motorApp/OrielSrc/devOriel.dbd b/motorApp/OrielSrc/devOriel.dbd deleted file mode 100644 index 4a6b8660..00000000 --- a/motorApp/OrielSrc/devOriel.dbd +++ /dev/null @@ -1,6 +0,0 @@ -# Oriel Encoder/Motor Mike Device Driver support. -device(motor,VME_IO,devEMC18011,"EMC18011") -driver(drvEMC18011) -registrar(OrielRegister) -variable(drvEMC18011debug) - diff --git a/motorApp/OrielSrc/drvEMC18011.cc b/motorApp/OrielSrc/drvEMC18011.cc deleted file mode 100644 index ae1313b7..00000000 --- a/motorApp/OrielSrc/drvEMC18011.cc +++ /dev/null @@ -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 -#include /* isascii functions */ -#include -#include -#include -#include -#include -#include -#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); -} - diff --git a/motorApp/OrielSrc/drvEMC18011.h b/motorApp/OrielSrc/drvEMC18011.h deleted file mode 100644 index 8f0f2054..00000000 --- a/motorApp/OrielSrc/drvEMC18011.h +++ /dev/null @@ -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 */ -