diff --git a/.gitmodules b/.gitmodules index 48720720..429e8422 100644 --- a/.gitmodules +++ b/.gitmodules @@ -55,3 +55,6 @@ [submodule "modules/motorMicos"] path = modules/motorMicos url = https://github.com/epics-motor/motorMicos.git +[submodule "modules/motorNewFocus"] + path = modules/motorNewFocus + url = https://github.com/epics-motor/motorNewFocus.git diff --git a/iocBoot/iocNewFocus874x/Makefile b/iocBoot/iocNewFocus874x/Makefile deleted file mode 100644 index 6512ead1..00000000 --- a/iocBoot/iocNewFocus874x/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -TOP = ../.. -include $(TOP)/configure/CONFIG -ARCH = linux-x86_64 -TARGETS += envPaths -include $(TOP)/configure/RULES.ioc - diff --git a/iocBoot/iocNewFocus874x/newfocus8742.asyn.motor.substitutions b/iocBoot/iocNewFocus874x/newfocus8742.asyn.motor.substitutions deleted file mode 100644 index cbc5b8ab..00000000 --- a/iocBoot/iocNewFocus874x/newfocus8742.asyn.motor.substitutions +++ /dev/null @@ -1,8 +0,0 @@ -file "$(MOTOR)/db/basic_asyn_motor.db" -{ -pattern -{P, N, M, DTYP, PORT, ADDR, C, S, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT} -{IOC:, 1, "X", "asynMotor", M0, 1, 0, 0, "X", counts, Pos, 100, 25, 1, 0, 0, 50, 1, 0, 0, 0, ""} -{IOC:, 2, "Y", "asynMotor", M0, 2, 0, 0, "Y", counts, Pos, 100, 25, 1, 0, 0, 50, 1, 0, 0, 0, ""} -} - diff --git a/iocBoot/iocNewFocus874x/newfocus8742.asyn.st.cmd.linux-x86 b/iocBoot/iocNewFocus874x/newfocus8742.asyn.st.cmd.linux-x86 deleted file mode 100644 index 5aebfe7d..00000000 --- a/iocBoot/iocNewFocus874x/newfocus8742.asyn.st.cmd.linux-x86 +++ /dev/null @@ -1,67 +0,0 @@ -#!../../bin/linux-x86_64/picoctl - -## You may have to change picoctl to something else -## everywhere it appears in this file - -< envPaths - -epicsEnvSet("EPICS_CA_AUTO_ADDR_LIST", "NO") -epicsEnvSet("EPICS_CA_ADDR_LIST", "10.28.0.255") - -epicsEnvSet("Sys", "Sys") -epicsEnvSet("Port", "P0") -epicsEnvSet("ControllerPort", "M0") -epicsEnvSet("MC", "MC:10") -epicsEnvSet("CT", "CT") -epicsEnvSet("IOC_PREFIX", "$(CT){IOC:MC10}") -epicsEnvSet("MC_PREFIX", "$(CT){$(MC)}") - -cd ${TOP} - -## Register all support components -dbLoadDatabase "dbd/picoctl.dbd" -picoctl_registerRecordDeviceDriver pdbbase - -# Setup IP port for 8742 -drvAsynIPPortConfigure("$(Port)", "10.28.2.111:23") -asynOctetSetInputEos("$(Port)",0,"\r\n") -asynOctetSetOutputEos("$(Port)",0,"\r") - -#db asyn debug traces -asynSetTraceMask("$(Port)",-1,0x1) -asynSetTraceIOMask("$(Port)",-1,0x1) - - -# New Focus Picomotor Network Controller (model 87xx) configuration parameters: -# (1) IP asyn port name (string) -# (2) Controller asyn port name (string) -# (3) Number of axes -# (4) Moving poll period (ms) -# (5) Idle poll period (ms) -nf874xCreateController("$(ControllerPort)", "$(Port)", 4, 200, 1000) - -## Load record instances -dbLoadTemplate("iocBoot/iocNewFocus874x/newfocus8742.asyn.motor.substitutions") - -dbLoadRecords("${ASYN}/db/asynRecord.db", "P=$(MC_PREFIX),R=Asyn,PORT=$(Port),ADDR=,OMAX=80,IMAX=80") - -## autosave/restore machinery -save_restoreSet_Debug(0) -save_restoreSet_IncompleteSetsOk(1) -save_restoreSet_DatedBackupFiles(1) - -set_savefile_path("${TOP}/as","/save") -set_requestfile_path("${TOP}/as","/req") - -set_pass0_restoreFile("info_positions.sav") -set_pass0_restoreFile("info_settings.sav") -set_pass1_restoreFile("info_settings.sav") - -iocInit() - -## more autosave/restore machinery -cd ${TOP}/as/req -makeAutosaveFiles() -create_monitor_set("info_positions.req", 5 , "") -create_monitor_set("info_settings.req", 15 , "") - diff --git a/iocBoot/iocWithAsyn/st.cmd.Vx b/iocBoot/iocWithAsyn/st.cmd.Vx index e834b7fc..05a4675e 100644 --- a/iocBoot/iocWithAsyn/st.cmd.Vx +++ b/iocBoot/iocWithAsyn/st.cmd.Vx @@ -44,18 +44,6 @@ dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=IOC:") #!IM483PLConfig(0, "a-Serial[0]") #!drvIM483PLdebug=4 -# New Focus Picomotor Network Controller (model 8750/2) (setup parameters: -# (1) maximum number of controllers in system -# (2) maximum number of drivers per controller (1 - 3) -# (3) motor task polling rate (min=1Hz,max=60Hz) -#!PMNC87xxSetup(1, 2, 10) - -# New Focuc Picomotor Network Controller (model 8750/2) configuration parameters: -# (1) controller# being configured, -# (2) asyn port name (string) -#!PMNC87xxConfig(0, "serial2") -#!drvPMNC87xxdebug=4 - # IMS MDrive driver setup parameters: # (1) maximum number of controllers in system diff --git a/iocsh/Newfocus_PMNC87xx.iocsh b/iocsh/Newfocus_PMNC87xx.iocsh deleted file mode 100644 index f05693ff..00000000 --- a/iocsh/Newfocus_PMNC87xx.iocsh +++ /dev/null @@ -1,37 +0,0 @@ -# ### Newfocus_PMNC87xx.iocsh ### - -#- ################################################### -#- PORT - Serial port for communications -#- CONTROLLER - Optional: Which controller is being configured -#- Default: 0 -#- -#- NUM_AXES - Optional: Number of axes on this controller -#- Default: 1 -#- -#- MAX_CONTROLLERS - Optional: Max number of controllers that will be configured -#- Default: 1 -#- -#- MAX_DRIVES - Optional: Max number of drives per controller -#- Default: 1 -#- -#- POLL_RATE - Optional: Controller poll rate in hertz -#- Default: 10 -#- ################################################### - -#- NewFocus Picomotor driver setup parameters: -#- (1) maximum number of controllers in system -#- (2) maximum drives per controller -#- (3) motor task polling rate (min=1Hz, max=60Hz) -$(PMNC87XX_INIT_COMPLETE="") PMNC87xxSetup($(MAX_CONTROLLERS=1), $(MAX_DRIVES=1), $(POLL_RATE=10)) - -#- Serial port configuration -iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=19200, BITS=8, STOP=1, PARITY=none") -asynOctetSetInputEos( "$(PORT)", -1, "\r") -asynOctetSetOutputEos("$(PORT)", -1, "\r") - -#- NewFocus Picomotor driver configuration parameters: -#- (1) controller being configured -#- (2) asyn port name (string) -PMNC87xxConfig($(CONTROLLER=0), "$(PORT)") - -epicsEnvSet("PMNC87XX_INIT_COMPLETE", "#") diff --git a/modules/Makefile b/modules/Makefile index 5f494341..7d1e1b5b 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -18,6 +18,7 @@ SUBMODULES += motorMclennan SUBMODULES += motorMicos SUBMODULES += motorMicroMo SUBMODULES += motorMicronix +SUBMODULES += motorNewFocus SUBMODULES += motorNPoint SUBMODULES += motorOriel SUBMODULES += motorPiJena diff --git a/modules/motorNewFocus b/modules/motorNewFocus new file mode 160000 index 00000000..eb6d3f59 --- /dev/null +++ b/modules/motorNewFocus @@ -0,0 +1 @@ +Subproject commit eb6d3f59389f151f9f46f1d31a8ae476a5c0e7ed diff --git a/motorApp/Makefile b/motorApp/Makefile index 8f09a601..13eff83e 100644 --- a/motorApp/Makefile +++ b/motorApp/Makefile @@ -30,9 +30,6 @@ PIGCS2Src_DEPEND_DIRS = MotorSrc DIRS += PC6KSrc PC6KSrc_DEPEND_DIRS = MotorSrc -DIRS += NewFocusSrc -NewFocusSrc_DEPEND_DIRS = MotorSrc - DIRS += AerotechSrc AerotechSrc_DEPEND_DIRS = MotorSrc diff --git a/motorApp/NewFocusSrc/874xMotorDriver.cpp b/motorApp/NewFocusSrc/874xMotorDriver.cpp deleted file mode 100644 index c3130d9b..00000000 --- a/motorApp/NewFocusSrc/874xMotorDriver.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* -FILENAME... 874xMotorDriver.cpp -USAGE... Motor driver support for the NewFocus 874x series motor controller - -Based on ACRMotorDriver.cpp by: -Mark Rivers -March 4, 2011 - -== Modifications == -2015-12-01 - Wayne Lewis - Modify for NewFocus 874x series -*/ - -/* - * TODO: Extend for 8743 closed loop functionality - */ - -#include -#include -#include - -#include -#include - -#include - -#include "asynMotorController.h" -#include "asynMotorAxis.h" - -#include -#include "874xMotorDriver.h" - -static const char *driverName = "nf874xMotorDriver"; - -/** Creates a new nf874xController object. - * \param[in] portName The name of the asyn port that will be created for this driver - * \param[in] nf874xPortName The name of the drvAsynIPPPort that was created previously to connect to the nf874x controller - * \param[in] numAxes The number of axes that this controller supports. Create one extra axis to allow for base 1 indexing of NewFocus controllers. - * \param[in] movingPollPeriod The time between polls when any axis is moving - * \param[in] idlePollPeriod The time between polls when no axis is moving - */ -nf874xController::nf874xController(const char *portName, const char *nf874xPortName, int numAxes, - double movingPollPeriod, double idlePollPeriod) - //: asynMotorController(portName, numAxes, NUM_nf874x_PARAMS, - : asynMotorController(portName, numAxes+1, 0, - asynUInt32DigitalMask, - asynUInt32DigitalMask, - ASYN_CANBLOCK | ASYN_MULTIDEVICE, - 1, // autoconnect - 0, 0) // Default priority and stack size -{ - int axis; - asynStatus status; - static const char *functionName = "nf874xController"; - - /* Connect to nf874x controller */ - status = pasynOctetSyncIO->connect(nf874xPortName, 0, &pasynUserController_, NULL); - if (status) { - asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, - "%s:%s: cannot connect to nf874x controller\n", - driverName, functionName); - } - epicsThreadSleep(0.5); - // Create the axis objects - // Axis 0 will remain unused. This allows consistent axis numbering with - // NewFocus convention. - for (axis=1; axis<=numAxes; axis++) { - new nf874xAxis(this, axis); - } - - startPoller(movingPollPeriod, idlePollPeriod, 2); -} - - -/** Creates a new nf874xController object. - * Configuration command, called directly or from iocsh - * \param[in] portName The name of the asyn port that will be created for this driver - * \param[in] nf874xPortName The name of the drvAsynIPPPort that was created previously to connect to the nf874x controller - * \param[in] numAxes The number of axes that this controller supports. - * \param[in] movingPollPeriod The time in ms between polls when any axis is moving - * \param[in] idlePollPeriod The time in ms between polls when no axis is moving - */ -extern "C" int nf874xCreateController(const char *portName, const char *nf874xPortName, int numAxes, - int movingPollPeriod, int idlePollPeriod) -{ - new nf874xController(portName, nf874xPortName, numAxes, movingPollPeriod/1000., idlePollPeriod/1000.); - return(asynSuccess); -} - -/** Reports on status of the driver - * \param[in] fp The file pointer on which report information will be written - * \param[in] level The level of report detail desired - * - * If details > 0 then information is printed about each axis. - * After printing controller-specific information calls asynMotorController::report() - */ -void nf874xController::report(FILE *fp, int level) -{ - fprintf(fp, "nf874x motor driver %s, numAxes=%d, moving poll period=%f, idle poll period=%f\n", - this->portName, numAxes_, movingPollPeriod_, idlePollPeriod_); - - // Call the base class method - asynMotorController::report(fp, level); -} - -/** Returns a pointer to an nf874xMotorAxis object. - * Returns NULL if the axis number encoded in pasynUser is invalid. - * \param[in] pasynUser asynUser structure that encodes the axis index number. */ -nf874xAxis* nf874xController::getAxis(asynUser *pasynUser) -{ - return static_cast(asynMotorController::getAxis(pasynUser)); -} - -/** Returns a pointer to an nf874xMotorAxis object. - * Returns NULL if the axis number encoded in pasynUser is invalid. - * \param[in] axisNo Axis index number. */ -nf874xAxis* nf874xController::getAxis(int axisNo) -{ - return static_cast(asynMotorController::getAxis(axisNo)); -} - - -/** Called when asyn clients call pasynInt32->write(). - * Extracts the function and axis number from pasynUser. - * Sets the value in the parameter library. - * For all other functions it calls asynMotorController::writeInt32. - * Calls any registered callbacks for this pasynUser->reason and address. - * \param[in] pasynUser asynUser structure that encodes the reason and address. - * \param[in] value Value to write. */ -asynStatus nf874xController::writeInt32(asynUser *pasynUser, epicsInt32 value) -{ - int function = pasynUser->reason; - asynStatus status = asynSuccess; - nf874xAxis *pAxis = getAxis(pasynUser); - static const char *functionName = "writeInt32"; - - /* Set the parameter and readback in the parameter library. This may be overwritten when we read back the - * status at the end, but that's OK */ - status = setIntegerParam(pAxis->axisNo_, function, value); - - status = asynMotorController::writeInt32(pasynUser, value); - - /* Do callbacks so higher layers see any changes */ - callParamCallbacks(pAxis->axisNo_); - if (status) - asynPrint(pasynUser, ASYN_TRACE_ERROR, - "%s:%s: error, status=%d function=%d, value=%d\n", - driverName, functionName, status, function, value); - else - asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, - "%s:%s: function=%d, value=%d\n", - driverName, functionName, function, value); - return status; -} - -/** Called when asyn clients call pasynFloat64->write(). - * Extracts the function and axis number from pasynUser. - * Sets the value in the parameter library. - * Calls any registered callbacks for this pasynUser->reason and address. - * For all other functions it calls asynMotorController::writeFloat64. - * \param[in] pasynUser asynUser structure that encodes the reason and address. - * \param[in] value Value to write. */ -asynStatus nf874xController::writeFloat64(asynUser *pasynUser, epicsFloat64 value) -{ - int function = pasynUser->reason; - asynStatus status = asynSuccess; - nf874xAxis *pAxis = getAxis(pasynUser); - static const char *functionName = "writeFloat64"; - - - /* Set the parameter and readback in the parameter library. */ - status = setDoubleParam(pAxis->axisNo_, function, value); - - status = asynMotorController::writeFloat64(pasynUser, value); - - /* Do callbacks so higher layers see any changes */ - pAxis->callParamCallbacks(); - if (status) - asynPrint(pasynUser, ASYN_TRACE_ERROR, - "%s:%s: error, status=%d function=%d, value=%f\n", - driverName, functionName, status, function, value); - else - asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, - "%s:%s: function=%d, value=%f\n", - driverName, functionName, function, value); - return status; -} - -// These are the nf874xAxis methods - -/** Creates a new nf874xAxis object. - * \param[in] pC Pointer to the nf874xController to which this axis belongs. - * \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1. - * - * Initializes register numbers, etc. - */ -nf874xAxis::nf874xAxis(nf874xController *pC, int axisNo) - : asynMotorAxis(pC, axisNo), - pC_(pC) -{ - sprintf(axisName_, "%d", axisNo); -} - -/** Reports on status of the driver - * \param[in] fp The file pointer on which report information will be written - * \param[in] level The level of report detail desired - * - * If details > 0 then information is printed about each axis. - * After printing controller-specific information calls asynMotorController::report() - */ -void nf874xAxis::report(FILE *fp, int level) -{ - if (level > 0) { - fprintf(fp, " axis %d\n", axisNo_ ); - } - - // Call the base class method - asynMotorAxis::report(fp, level); -} - - -asynStatus nf874xAxis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration) -{ - asynStatus status; - - sprintf(pC_->outString_, "%s AC %f", axisName_, acceleration); - status = pC_->writeController(); - sprintf(pC_->outString_, "%s VA %f", axisName_, maxVelocity); - status = pC_->writeController(); - if (relative) { - sprintf(pC_->outString_, "%s PR %f", axisName_, position); - status = pC_->writeController(); - } else { - sprintf(pC_->outString_, "%s PA %f", axisName_, position); - status = pC_->writeController(); - } - return status; -} - -asynStatus nf874xAxis::home(double minVelocity, double maxVelocity, double acceleration, int forwards) -{ - asynStatus status; - - sprintf(pC_->outString_, "%s AC %f", axisName_, acceleration); - status = pC_->writeController(); - sprintf(pC_->outString_, "%s VA %f", axisName_, acceleration); - status = pC_->writeController(); - sprintf(pC_->outString_, "%s DH", axisName_); - status = pC_->writeController(); - return status; -} - -asynStatus nf874xAxis::moveVelocity(double minVelocity, double maxVelocity, double acceleration) -{ - asynStatus status; - double speed=maxVelocity; - int forwards=1; - - if (speed < 0) { - speed = -speed; - forwards = 0; - } - sprintf(pC_->outString_, "%s AC %f", axisName_, acceleration); - status = pC_->writeController(); - sprintf(pC_->outString_, "%s VA %f", axisName_, speed); - status = pC_->writeController(); - sprintf(pC_->outString_, "%s MV %s", axisName_, forwards ? "+" : "-"); - status = pC_->writeController(); - return status; -} - -asynStatus nf874xAxis::stop(double acceleration ) -{ - asynStatus status; - - sprintf(pC_->outString_, "%s ST", axisName_); - status = pC_->writeController(); - return status; -} - -asynStatus nf874xAxis::setPosition(double position) -{ - asynStatus status; - - sprintf(pC_->outString_, "%s DH %f", axisName_, position); - status = pC_->writeController(); - return status; -} - -/** Polls the axis. - * This function reads the controller position, encoder position, the limit status, the moving status, - * and the drive power-on status. It does not current detect following error, etc. but this could be - * added. - * It calls setIntegerParam() and setDoubleParam() for each item that it polls, - * and then calls callParamCallbacks() at the end. - * \param[out] moving A flag that is set indicating that the axis is moving (1) or done (0). */ -asynStatus nf874xAxis::poll(bool *moving) -{ - int done; - asynStatus comStatus; - - // Read the current encoder position - sprintf(pC_->outString_, "%s TP?", axisName_); - comStatus = pC_->writeReadController(); - if (comStatus) goto skip; - encoderPosition_ = atof(pC_->inString_); - setDoubleParam(pC_->motorEncoderPosition_,encoderPosition_); - - // Read the current theoretical position - setDoubleParam(pC_->motorPosition_, encoderPosition_); - - // Read the current moving status - sprintf(pC_->outString_, "%s MD?", axisName_); - comStatus = pC_->writeReadController(); - if (comStatus) goto skip; - done = atoi(pC_->inString_); - setIntegerParam(pC_->motorStatusDone_, done); - *moving = done ? false:true; - - skip: - setIntegerParam(pC_->motorStatusProblem_, comStatus ? 1:0); - callParamCallbacks(); - return comStatus ? asynError : asynSuccess; -} - -/** Code for iocsh registration */ -static const iocshArg nf874xCreateControllerArg0 = {"Port name", iocshArgString}; -static const iocshArg nf874xCreateControllerArg1 = {"nf874x port name", iocshArgString}; -static const iocshArg nf874xCreateControllerArg2 = {"Number of axes", iocshArgInt}; -static const iocshArg nf874xCreateControllerArg3 = {"Moving poll period (ms)", iocshArgInt}; -static const iocshArg nf874xCreateControllerArg4 = {"Idle poll period (ms)", iocshArgInt}; -static const iocshArg * const nf874xCreateControllerArgs[] = {&nf874xCreateControllerArg0, - &nf874xCreateControllerArg1, - &nf874xCreateControllerArg2, - &nf874xCreateControllerArg3, - &nf874xCreateControllerArg4}; -static const iocshFuncDef nf874xCreateControllerDef = {"nf874xCreateController", 5, nf874xCreateControllerArgs}; -static void nf874xCreateContollerCallFunc(const iocshArgBuf *args) -{ - nf874xCreateController(args[0].sval, args[1].sval, args[2].ival, args[3].ival, args[4].ival); -} - -static void nf874xMotorRegister(void) -{ - iocshRegister(&nf874xCreateControllerDef, nf874xCreateContollerCallFunc); -} - -extern "C" { -epicsExportRegistrar(nf874xMotorRegister); -} diff --git a/motorApp/NewFocusSrc/874xMotorDriver.h b/motorApp/NewFocusSrc/874xMotorDriver.h deleted file mode 100644 index 76929258..00000000 --- a/motorApp/NewFocusSrc/874xMotorDriver.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -FILENAME... 874xMotorDriver.h -USAGE... Motor driver support for the NewFocus 874x series of controllers - -Based on ACRMotorDriver.h by: -Mark Rivers -March 28, 2011 - -== Modifications == -2015-12-01 - Wayne Lewis - Modify for NewFocus 874x controllers -*/ - -#include "asynMotorController.h" -#include "asynMotorAxis.h" - -class epicsShareClass nf874xAxis : public asynMotorAxis -{ -public: - /* These are the methods we override from the base class */ - nf874xAxis(class nf874xController *pC, int axis); - void report(FILE *fp, int level); - asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration); - asynStatus moveVelocity(double min_velocity, double max_velocity, double acceleration); - asynStatus home(double min_velocity, double max_velocity, double acceleration, int forwards); - asynStatus stop(double acceleration); - asynStatus poll(bool *moving); - asynStatus setPosition(double position); - -private: - nf874xController *pC_; /**< Pointer to the asynMotorController to which this axis belongs. - * Abbreviated because it is used very frequently */ - char axisName_[10]; /**< Name of each axis, used in commands to nf874x controller */ - double encoderPosition_; /**< Cached copy of the encoder position */ - -friend class nf874xController; -}; - -class epicsShareClass nf874xController : public asynMotorController { -public: - nf874xController(const char *portName, const char *nf874xPortName, int numAxes, double movingPollPeriod, double idlePollPeriod); - - /* These are the methods that we override from asynMotorDriver */ - asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); - asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value); - void report(FILE *fp, int level); - nf874xAxis* getAxis(asynUser *pasynUser); - nf874xAxis* getAxis(int axisNo); - -friend class nf874xAxis; -}; diff --git a/motorApp/NewFocusSrc/Makefile b/motorApp/NewFocusSrc/Makefile deleted file mode 100644 index bc5cf8ee..00000000 --- a/motorApp/NewFocusSrc/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# Makefile -TOP = ../.. -include $(TOP)/configure/CONFIG - -# Both the following line, and a line in the *.dbd file, -# must be uncommented to use diagnostic debugging messages. -# USR_CXXFLAGS += -DDEBUG -# OPT_CXXFLAGS = -g -O0 - -DBD += devNewFocus.dbd - -LIBRARY_IOC = NewFocus - -NewFocus_SRCS += NewFocusRegister.cc - -# PMNC87xx (i.e., PMNC87xx) device driver. -NewFocus_SRCS += devPMNC87xx.cc drvPMNC87xx.cc - -# NewFocus 874x driver -NewFocus_SRCS += 874xMotorDriver.cpp - -NewFocus_LIBS += motor asyn -NewFocus_LIBS += $(EPICS_BASE_IOC_LIBS) - -include $(TOP)/configure/RULES - diff --git a/motorApp/NewFocusSrc/NewFocusRegister.cc b/motorApp/NewFocusSrc/NewFocusRegister.cc deleted file mode 100644 index 7302ad52..00000000 --- a/motorApp/NewFocusSrc/NewFocusRegister.cc +++ /dev/null @@ -1,68 +0,0 @@ -/* -FILENAME... NewFocusRegister.cc -USAGE... Register NewFocus motor device driver shell commands. - -Version: 1.6 -Modified By: rivers -Last Modified: 2004/07/28 20:24:01 -*/ - -/***************************************************************** - 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 "NewFocusRegister.h" -#include "epicsExport.h" - -extern "C" -{ - -// NewFocus Setup arguments -static const iocshArg setupArg0 = {"Max. controller count", iocshArgInt}; -static const iocshArg setupArg1 = {"Max. drivers per controller count", iocshArgInt}; -static const iocshArg setupArg2 = {"Polling rate", iocshArgInt}; -// NewFocus Config arguments -static const iocshArg configArg0 = {"Card being configured", iocshArgInt}; -static const iocshArg configArg1 = {"asyn port name", iocshArgString}; -static const iocshArg configArg2 = {"asyn address (GPIB)", iocshArgInt}; - -static const iocshArg * const NewFocusSetupArgs[3] = {&setupArg0, - &setupArg1, - &setupArg2}; -static const iocshArg * const NewFocusConfigArgs[3] = {&configArg0, - &configArg1, - &configArg2}; - -static const iocshFuncDef setupPMNC87xx = {"PMNC87xxSetup", 3, NewFocusSetupArgs}; - -static const iocshFuncDef configPMNC87xx = {"PMNC87xxConfig", 3, NewFocusConfigArgs}; - - -static void setupPMNC87xxCallFunc(const iocshArgBuf *args) -{ - PMNC87xxSetup(args[0].ival, args[1].ival, args[2].ival); -} - -static void configPMNC87xxCallFunc(const iocshArgBuf *args) -{ - PMNC87xxConfig(args[0].ival, args[1].sval, args[2].ival); -} - -static void NewFocusRegister(void) -{ - iocshRegister(&setupPMNC87xx, setupPMNC87xxCallFunc); - - iocshRegister(&configPMNC87xx, configPMNC87xxCallFunc); -} - -epicsExportRegistrar(NewFocusRegister); - -} // extern "C" diff --git a/motorApp/NewFocusSrc/NewFocusRegister.h b/motorApp/NewFocusSrc/NewFocusRegister.h deleted file mode 100644 index 6392b62c..00000000 --- a/motorApp/NewFocusSrc/NewFocusRegister.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -FILENAME... NewportRegister.h -USAGE... This file contains function prototypes for Newport 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 PMNC87xxSetup(int, int, int); -extern RTN_STATUS PMNC87xxConfig(int, const char *, int); - diff --git a/motorApp/NewFocusSrc/README b/motorApp/NewFocusSrc/README deleted file mode 100644 index 4bcaf1a8..00000000 --- a/motorApp/NewFocusSrc/README +++ /dev/null @@ -1,116 +0,0 @@ -NewFocus PicoMotor Controller (87xx) -=================================== - - -This motorRecord driver supports the NewFocus 8750 and 8752 -PicoMotor Network Controllers. - 8750 - RS232 @ 19200Baud (8data, No Parity, 1stop) - 8752 - RS232 @ 19200Baud or Ethernet (port 23) - -Support Motor Drivers (daisychained) - 8753 - 3 Channel Open-loop - 8751 - 1 Channel Closed-loop - -Motor Resolution: - Standard Picomotor - ~30nm - Tiny Picomotor - ~100nm - - -Serial Port Config -=================== -DB9: Male - Tx - Pin 2 - Rx - Pin 3 - - Null-Modem (swap 2-3) required for IP-Octal breakout module - -Baud: 19200 (eight data bits, one stop bit, and no parity) - - -**** EXAMPLE CONFIGURATION FOR VXWORKS TARGETS **** - -Ethernet Config (8752 Only) -============================ -Commands sent using RS232 port - -EHCO ComA ON Turn echo on RS232 port (Computer) - -IPMODE (STAT, DHCP) - IP Mode (Static IP, Use DHCP Server) -IPADDR IP Setting -NETMASK Network Mask -MACADDR MAC Address -GATEWAY Network Gateway -SAV Save Configuration Settings - -After setting up ethernet parameters and SAV(ing) reset the controller. -The IPMODE and IPADDR do not take effect untill after a reboot. - -Example: ->IPMODE=STAT ->IPADDR=164.54.9.33 ->NETMASK=255.255.252.0 ->GATEWAY=164.54.8.1 ->SAV - - - -Other Info -=================================== -Test Versions: - VER - 8750 - Version 1.0.13 - 8752 - Version 1.5.0, 1.6.0 - 8752 - Version 1.5.4 (NO '>' on STA command - use '/n' for input EOS) - - -Detect driver types - DRT Driver Type (8752 Only) - 1 = 3 channel open loop (8753) - 2 = 1 channel closed loop (8751) - - - -EPICS SETUP -============ - - -xxxApp/src/Makefile -------------------- -xxx_vxWorks_LIBS += NewFocus - -xxxApp/src/xxxCommonInclude.dbd --------------------------------- -include "devNewFocus.dbd" - - -iocBoot/iocxxx/serial.cmd ---------------------------- -tyGSAsynInit("serial1", "UART_0", 1, 19200,'N',1,8,'N',">","\r") /* NewFocus Pico Motor */ - -. -# Setup IP port for 8752 -drvAsynIPPortConfigure("serial3", "164.54.9.33:23", 0, 0, 0) -asynOctetSetInputEos("serial3",0,">") -asynOctetSetOutputEos("serial3",0,"\r") -. -. - -# New Focus Picomotor Network Controller (model 87xx) (setup parameters: -# (1) maximum number of controllers in system -# (2) maximum number of drivers per controller (1 - 3) -# (3) motor task polling rate (min=1Hz,max=60Hz) -#drvPMNC87xxdebug=0 -PMNC87xxSetup(1, 2, 10) - -# New Focuc Picomotor Network Controller (model 87xx) configuration parameters: -# (1) controller# being configured, -# (2) asyn port name (string) -PMNC87xxConfig(0, "serial1") - - -iocBoot/iocxxx/motor.substitutions ----------------------------------- -{xxx:, 1, m$(N), "PMNC87xx", 0, 0, "motor $(N)", degrees, Pos, 10, 0., 1., 0, 1, .2, 1e-3, 3, 100, -100, ""} -{xxx:, 2 m$(N), "PMNC87xx", 0, 1, "motor $(N)", degrees, Pos, 60, 0., 1.5, 0, 1, .2, 1e-3, 3, 100, -100, ""} -{xxx:, 3, m$(N), "PMNC87xx", 0, 2, "motor $(N)", degrees, Pos, 60, 0., 1., 0, 1, .2, 1e-3, 3, 100, -100, ""} - diff --git a/motorApp/NewFocusSrc/devNewFocus.dbd b/motorApp/NewFocusSrc/devNewFocus.dbd deleted file mode 100644 index d9c6e6ea..00000000 --- a/motorApp/NewFocusSrc/devNewFocus.dbd +++ /dev/null @@ -1,9 +0,0 @@ -# NewFocus PicoMotor Network Controller (PMNC) Device Driver support. -device(motor,VME_IO,devPMNC87xx,"PMNC87xx") -driver(drvPMNC87xx) -registrar(NewFocusRegister) -variable(drvPMNC87xxdebug) - -# NewFocus 874x controller support -registrar(nf874xMotorRegister) - diff --git a/motorApp/NewFocusSrc/devPMNC87xx.cc b/motorApp/NewFocusSrc/devPMNC87xx.cc deleted file mode 100644 index b293e8cf..00000000 --- a/motorApp/NewFocusSrc/devPMNC87xx.cc +++ /dev/null @@ -1,427 +0,0 @@ -/* -FILENAME... devPMNC87xx.cc -USAGE... Motor record device level support for NewFocus 8750 and 8752 Controller . - -Version: 1.3 -Modified By: sluiter -Last Modified: 2004/12/20 21:10:53 -*/ - -/* - * Original Author: Mark Rivers - * Date: 10/16/97 - * Current Author: Joe 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: - * ----------------- - * .00 10-16-97 mlr initialized from devOms58 - * .01 07-19-99 rls initialized from drvMM4000 - * .02 04-21-01 rls Added jog velocity motor command. - * .03 05-22-03 rls Converted to R3.14.x. - * .04 06-20-06 jps initialized from drvPMNC8750 - */ - - -#include -#include -#include -#include "motorRecord.h" -#include "motor.h" -#include "motordevCom.h" -#include "drvPMNCCom.h" -#include "epicsExport.h" - -#define STATIC static - -extern struct driver_table PMNC87xx_access; - -/* ----------------Create the dsets for devPMNC87xx----------------- */ -/* static long report(); */ -STATIC struct driver_table *drvtabptr; -STATIC long PMNC87xx_init(int); -STATIC long PMNC87xx_init_record(void *); -STATIC long PMNC87xx_start_trans(struct motorRecord *); -STATIC RTN_STATUS PMNC87xx_build_trans(motor_cmnd, double *, struct motorRecord *); -STATIC RTN_STATUS PMNC87xx_end_trans(struct motorRecord *); - -struct motor_dset devPMNC87xx = -{ - {8, NULL, (DEVSUPFUN) PMNC87xx_init, (DEVSUPFUN) PMNC87xx_init_record, NULL}, - motor_update_values, - PMNC87xx_start_trans, - PMNC87xx_build_trans, - PMNC87xx_end_trans -}; - -extern "C" {epicsExportAddress(dset,devPMNC87xx);} - -/* --------------------------- program data --------------------- */ - -/* This table is used to define the command types */ -/* WARNING! this must match "motor_cmnd" in motor.h */ - -static msg_types PMNC87xx_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 **PMNC87xx_cards; - -/* --------------------------- program data --------------------- */ - - -/* initialize device support for PMNC87xx stepper motor */ -STATIC long PMNC87xx_init(int after) -{ - long rtnval; - - if (!after) - { - drvtabptr = &PMNC87xx_access; - (drvtabptr->init)(); - } - - rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &PMNC87xx_cards); - return(rtnval); -} - - -/* initialize a record instance */ -STATIC long PMNC87xx_init_record(void *arg) -{ - struct motorRecord *mr = (struct motorRecord *) arg; - return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr, drvtabptr, PMNC87xx_cards)); -} - - -/* start building a transaction */ -STATIC long PMNC87xx_start_trans(struct motorRecord *mr) -{ - return(motor_start_trans_com(mr, PMNC87xx_cards)); -} - - -/* end building a transaction */ -STATIC RTN_STATUS PMNC87xx_end_trans(struct motorRecord *mr) -{ - return(motor_end_trans_com(mr, drvtabptr)); -} - - -/* add a part to the transaction */ -STATIC RTN_STATUS PMNC87xx_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 mess_info *motor_info; - struct controller *brdptr; - struct PMNCcontroller *cntrl; - struct PMD_axis *paxisDef; - PMD_model dType; - - char buff[110]; - int axis, card; - int drive, motor; - unsigned int size; - int intval, velval; - RTN_STATUS rtnval; - bool sendMsg; - - rtnval = OK; - buff[0] = '\0'; - sendMsg = true; - - motor_start_trans_com(mr, PMNC87xx_cards); - - motor_call = &(trans->motor_call); - card = motor_call->card; - axis = motor_call->signal; - - motor_call->type = PMNC87xx_table[command]; - brdptr = (*trans->tabptr->card_array)[card]; - if (brdptr == NULL) - return(rtnval = ERROR); - cntrl = (struct PMNCcontroller *) brdptr->DevicePrivate; - - - paxisDef = &cntrl->axisDef[axis]; - drive = paxisDef->driverNum; - motor = paxisDef->motorNum; - dType = paxisDef->driverType; - - if (PMNC87xx_table[command] > motor_call->type) - motor_call->type = PMNC87xx_table[command]; - - if (trans->state != BUILD_STATE) - return(rtnval = ERROR); - - if (command == PRIMITIVE && mr->init != NULL && strlen(mr->init) != 0) - strcat(motor_call->message, mr->init); - - switch (command) - { - case MOVE_ABS: - case MOVE_REL: - case HOME_FOR: - case HOME_REV: - 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, PMNC87xx_cards); - motor_call->type = PMNC87xx_table[command]; - - } - if (strlen(mr->post) != 0) - motor_call->postmsgptr = (char *) &mr->post; - default: - /* Protect against NULL pointer with WRTITE_MSG(GO/STOP_AXIS/GET_INFO, NULL). */ - intval = (parms == NULL) ? 0 : NINT(parms[0]); - break; - } - - motor_info = &((*drvtabptr->card_array)[card]->motor_info[axis]); - - switch (command) - { - case MOVE_ABS: - if (dType == PMD8753) - sprintf(buff, "REL A%d=%d", drive, intval-motor_info->position); - else - sprintf(buff, "ABS A%d=%d", drive, intval); - break; - case MOVE_REL: - sprintf(buff, "REL A%d=%d", drive, intval); - break; - case HOME_FOR: - // if (dType == PMD8751) - // sprintf(buff, "FIN A%d", drive); - // else - // trans->state = IDLE_STATE; /* No command sent to the controller. */ - sendMsg = false; - break; - case HOME_REV: - // if (dType == PMD8751) - // sprintf(buff, "RIN A%d", drive); - // else - // trans->state = IDLE_STATE; /* No command sent to the controller. */ - sendMsg = false; - break; - case LOAD_POS: - - if (dType == PMD8753) - { - /* Setting local driver position because the controller cannot be set */ - sprintf(buff, "CHL A%d=%d", drive, motor); - motor_info->position = intval; - motor_info->encoder_position = intval; - cntrl->last_position[axis] = 0; // Used to accumulate position history - } - else if (dType == PMD8751) - { - /* Closed loop driver - able to set position */ - sprintf(buff, "POS %d=%d", drive, intval); - } - else - { - trans->state = IDLE_STATE; /* No command sent to the controller. */ - sendMsg = false; - } - - break; - case SET_VEL_BASE: - if (dType == PMD8753) - { - if (abs(intval) >= MAX_VELOCITY) - intval = MAX_VELOCITY-1; - /* Set VEL to maximum to eliminate MPV out-of-range error */ - sprintf(buff, "VEL A%d %d=%d", drive, motor, MAX_VELOCITY); - strcpy(motor_call->message, buff); - - rtnval = motor_end_trans_com(mr, drvtabptr); - rtnval = (RTN_STATUS) motor_start_trans_com(mr, PMNC87xx_cards); - motor_call->type = PMNC87xx_table[command]; - - - sprintf(buff, "MPV A%d %d=%d", drive, motor, abs(intval)); - } - else // if (dType == PMD8751) - { - trans->state = IDLE_STATE; /* No command sent to the controller. */ - sendMsg = false; - } - - break; - case SET_VELOCITY: - if (abs(intval) > MAX_VELOCITY) - intval = MAX_VELOCITY; - sprintf(buff, "VEL A%d %d=%d", drive, motor, abs(intval)); - break; - case SET_ACCEL: - /* - * The value passed is in steps/sec/sec. - */ - if (intval < MIN_ACCEL) - intval = MIN_ACCEL; - else if (intval > MAX_ACCEL) - intval = MAX_ACCEL; - - sprintf(buff, "ACC A%d %d=%d", drive, motor, intval); - break; - case GO: - sprintf(buff, "GO A%d", drive); - break; - case SET_ENC_RATIO: - trans->state = IDLE_STATE; /* No command sent to the controller. */ - sendMsg = false; - break; - case PRIMITIVE: - case GET_INFO: - /* These commands are not actually done by sending a message, but - rather they will indirectly cause the driver to read the status - of all motors */ - break; - case STOP_AXIS: - sprintf(buff, "HAL A%d", drive); /* Using the smooth stop command */ - break; - case JOG: - if (abs(intval) > MAX_VELOCITY) - velval = MAX_VELOCITY; - else - velval = abs(intval); - - if (dType == PMD8753) - { - if (intval >= 0) - sprintf(buff, "FOR A%d=%d", drive, velval); - else - sprintf(buff, "REV A%d=%d", drive, velval); - } - else if (dType == PMD8751) - { - sprintf(buff, "VEL A%d %d=%d", drive, motor, velval); - - strcpy(motor_call->message, buff); - rtnval = motor_end_trans_com(mr, drvtabptr); - rtnval = (RTN_STATUS) motor_start_trans_com(mr, PMNC87xx_cards); - motor_call->type = PMNC87xx_table[command]; - - // Use Relative Move command for jogging - // because the 8751 does not indicate motion with (FOR and REV) - // ** BUG? ** - if (intval >= 0) - sprintf(buff, "REL A%d=1000000",drive); - else - sprintf(buff, "REL A%d=-1000000",drive); - } - else - { - sendMsg = false; - break; - } - - strcpy(motor_call->message, buff); - rtnval = motor_end_trans_com(mr, drvtabptr); - rtnval = (RTN_STATUS) motor_start_trans_com(mr, PMNC87xx_cards); - motor_call->type = PMNC87xx_table[command]; - - sprintf(buff, "GO A%d", drive); - break; - case SET_PGAIN: - case SET_IGAIN: - case SET_DGAIN: - trans->state = IDLE_STATE; /* No command sent to the controller. */ - sendMsg = false; - break; - case ENABLE_TORQUE: - if (dType == PMD8751) - sprintf(buff, "SER A%d", drive); - else if (dType == PMD8753) - sprintf(buff, "MON A%d", drive); - else - { - trans->state = IDLE_STATE; /* No command sent to the controller. */ - sendMsg = false; - } - - break; - case DISABL_TORQUE: - if (dType == PMD8751) - sprintf(buff, "NOS A%d", drive); - else if (dType == PMD8753) - sprintf(buff, "MOF A%d", drive); - else - { - trans->state = IDLE_STATE; /* No command sent to the controller. */ - sendMsg = false; - } - break; - case SET_HIGH_LIMIT: - case SET_LOW_LIMIT: - trans->state = IDLE_STATE; /* No command sent to the controller. */ - 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("PMNC87xx_build_trans(): buffer overflow.\n"); - else - { - strcat(motor_call->message, buff); - motor_end_trans_com(mr, drvtabptr); - } - } - - return(rtnval); -} diff --git a/motorApp/NewFocusSrc/drvPMNC87xx.cc b/motorApp/NewFocusSrc/drvPMNC87xx.cc deleted file mode 100644 index fb5c45f8..00000000 --- a/motorApp/NewFocusSrc/drvPMNC87xx.cc +++ /dev/null @@ -1,1089 +0,0 @@ -/* -FILENAME... drvPMNC87xx.cc -USAGE... Motor record driver level support for NewFocus PMNC87xx. - -Version: 1.17 -Modified By: sullivan -Last Modified: 2005/03/30 19:10:48 -*/ - -/* - * Original Author: Mark Rivers - * Date: 06/28/06 - * Current Author: Joe 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 10-20-97 mlr initialized from drvOms58 - * .02 10-30-97 mlr Replaced driver calls with gpipIO functions - * .03 10-30-98 mlr Minor code cleanup, improved formatting - * .04 02-01-99 mlr Added temporary fix to delay reading motor positions at - * the end of a move. - * .05 04-18-00 rls PMNC87xx takes 2 to 5 seconds to respond to queries after - * hitting a hard travel limit. Adjusted GPIB and SERIAL - * timeouts accordingly. Deleted communication retries. - * Reworked travel limit processing so that direction - * status bit matches limit switch. Copied recv_mess() - * logic from drvMM4000.c. Use TPE command to determine - * if motor has an encoder. - * .06 10/02/01 rls - allow one retry after a communication error. - * - use motor status response bit-field. - * .07 05-22-03 rls - Converted to R3.14.2. - * .08 10/23/03 rls - recv_mess() eats the controller error response, outputs - * an error message and retries. - * .09 02/03/04 rls - Eliminate erroneous "Motor motion timeout ERROR". - * .10 07/09/04 rls - removed unused Setup() argument. - * .11 07/28/04 rls - "epicsExport" debug variable. - * .12 09/21/04 rls - support for 32axes/controller. - * .13 12/21/04 rls - MS Visual C compatibility; make all epicsExportAddress - * extern "C" linkage. - * - make debug variables always available. - * .14 01/11/06 jps - initialize from drvMM3000.cc - * - */ - -#include -#include -#include -#include -#include -#include "NewFocusRegister.h" -#include "drvPMNCCom.h" -#include "asynOctetSyncIO.h" -#include "asynCommonSyncIO.h" -#include "epicsExport.h" -#include "epicsExit.h" - -#define STATIC static - -#define READ_RESOLUTION "VER" -#define READ_STATUS "STA %d" -#define READ_DIAG "DIAG %d" -#define READ_POS "POS %d" -#define READ_CHAN_SELECT "CHL %d" -#define STOP_ALL "STO" -#define INIT_ALL "INI" -#define MOTOR_ON "MON" -#define MOTOR_OFF "MOF" -#define JOY_ON "JON" -#define GET_IDENT "VER" -#define GET_MPV "MPV" /* Query Minimum Profile Velocity */ - -#define GET_DRT "DRT" /* Query Driver Types */ - -#define VER_STR "Version 1." - -#define PROMPT_EOS ">" -#define NL_EOS "\n" -#define CMND_EOS "\r" - -/* Status byte bits */ -#define M_AXIS_MOVING 0x01 -#define M_MOTOR_POWER 0x02 -#define M_MOTOR_DIRECTION 0x04 -#define M_PLUS_LIMIT 0x08 -#define M_MINUS_LIMIT 0x10 -#define M_HOME_SIGNAL 0x20 - -#define BUFF_SIZE 100 /* Maximum length of string to/from PMNC87xx */ - -#define PMNC_TIMEOUT 3.0 /* Command timeout in sec. */ -#define MESS_ERR -1 - -/*----------------debugging-----------------*/ -volatile int drvPMNC87xxdebug = 0; -extern "C" {epicsExportAddress(int, drvPMNC87xxdebug);} - -static inline void Debug(int level, const char *format, ...) { - #ifdef DEBUG - if (level < drvPMNC87xxdebug) { - va_list pVar; - va_start(pVar, format); - vprintf(format, pVar); - va_end(pVar); - } - #endif -} - -/* --- Local data. --- */ -int PMNC87xx_num_cards = 0; -int PMNC87xx_num_drivers = 0; /* Number of Drivers per Controller */ -char nobuff[BUFF_SIZE]; /* Scratch buffer - noreply commands */ - -/* Track open asyn ports - close on IOC exit */ -#define MAX_SOCKETS PMNC87xx_NUM_CARDS+1 -#define PORT_NAME_SIZE 100 -#define ERROR_STRING_SIZE 100 -#define DEFAULT_TIMEOUT 0.2 - -static int nextSocket = 0; - -/* Pointer to the connection info for each socket - the asynUser structure is defined in asynDriver.h */ -typedef struct { - asynUser *pasynUser; - asynUser *pasynUserCommon; - double timeout; - char errorString[ERROR_STRING_SIZE]; - bool connected; -} socketStruct; -static socketStruct socketStructs[MAX_SOCKETS]; - - -/* Local data required for every driver; see "motordrvComCode.h" */ -#include "motordrvComCode.h" - - - -/*----------------functions-----------------*/ -STATIC int recv_mess(int, char *, int); -STATIC RTN_STATUS send_mess(int, char const *, char *); -STATIC int send_recv_mess(int, char const *, char *, char const *); -STATIC int set_status(int, int); -// STATIC void start_status(int); -static long report(int); -static long init(); -STATIC int motor_init(); -STATIC void query_done(int, int, struct mess_node *); -void closePMNCSockets(void *); - -/*----------------functions-----------------*/ - -struct driver_table PMNC87xx_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 drvPMNC87xx_drvet -{ - long number; - long (*report) (int); - long (*init) (void); -} drvPMNC87xx = {2, report, init}; - -extern "C" {epicsExportAddress(drvet, drvPMNC87xx);} - -STATIC struct thread_args targs = {SCAN_RATE, &PMNC87xx_access, 0.0}; - -/********************************************************* - * Print out driver status report - *********************************************************/ -static long report(int level) -{ - int card; - - if (PMNC87xx_num_cards <=0) - printf(" No PMNC87xx controllers configured.\n"); - else - { - for (card = 0; card < PMNC87xx_num_cards; card++) - { - struct controller *brdptr = motor_state[card]; - - if (brdptr == NULL) - printf(" PMNC87xx controller %d connection failed.\n", card); - else - { - struct PMNCcontroller *cntrl; - - cntrl = (struct PMNCcontroller *) brdptr->DevicePrivate; - printf(" PMNC87xx controller %d asyn port= %s, address=%d, id: %s \n", - card, cntrl->asyn_port, cntrl->asyn_address, - brdptr->ident); - break; - } - } - } - 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 (PMNC87xx_num_cards <= 0) - { - Debug(1, "init(): PMNC87xx driver disabled. PMNC87xxSetup() 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() - ************************************************************/ - -#define CHECKRTN \ - if (recvRtn > 0) { \ - cntrl->status = NORMAL; \ - status.Bits.CNTRL_COMM_ERR = 0; \ - } \ - else { \ - if (cntrl->status == NORMAL) { \ - cntrl->status = RETRY; \ - setReturn=0; \ - } \ - else { \ - cntrl->status = COMM_ERR; \ - status.Bits.CNTRL_COMM_ERR = 1; \ - status.Bits.RA_PROBLEM = 1; \ - setReturn = 1; \ - } \ - goto exit; \ - } - - -STATIC int set_status(int card, int signal) -{ - struct PMNCcontroller *cntrl; - struct mess_node *nodeptr; - register struct mess_info *motor_info; - /* Message parsing variables */ - char *pStr; - char buff[BUFF_SIZE]; - MOTOR_STATUS mstat; - MOTOR_AUX_STATUS auxstat; - struct PMD_axis *signalDef; - int setReturn; - int recvRtn; - int driverID, motorID; - int recvDriver, recvStatus; - long motorData; - int selectMotor; - bool plusdir, ls_active = false; - msta_field status; - - - setReturn = 0; - cntrl = (struct PMNCcontroller *) motor_state[card]->DevicePrivate; - motor_info = &(motor_state[card]->motor_info[signal]); - status.All = motor_info->status.All; - - signalDef = &cntrl->axisDef[signal]; - - /* Get the motor information */ - driverID = signalDef->driverNum; - motorID = signalDef->motorNum; - - if (signalDef->driverType == PMD8753) - { - sprintf(buff, READ_CHAN_SELECT, driverID); - pStr = cntrl->chan_select_string[driverID]; - recvRtn = send_recv_mess(card, buff, pStr, NULL); - CHECKRTN; - Debug(2, "set_status(): ChanSelect_string=%s\n", pStr); - selectMotor = atoi(pStr); - } - else - selectMotor = 0; /* PMD8751 only has one motor */ - - - /* Set defaults in-case motor is not selected */ - motorData = cntrl->last_position[signal]; - mstat.All = 0; - auxstat.All = 0; - - sprintf(buff, READ_STATUS, driverID); - pStr = cntrl->status_string[driverID]; - /* STATUS command does not return a prompt - bug? */ - if (cntrl->changeEOS) - recvRtn = send_recv_mess(card, buff, pStr, NL_EOS); - else - recvRtn = send_recv_mess(card, buff, pStr, NULL); - CHECKRTN; - Debug(2, "set_status(): Status_string=%s\n", pStr); - if (sscanf(pStr, "A%d=0x%x",&recvDriver, &recvStatus) == 2) - { - mstat.All = recvStatus; - Debug(5, "set_status(): drive %d - status byte = %x\n", recvDriver, recvStatus); - } - else - Debug(1, "set_status(): drive %d - INVALID status string %s\n", driverID, pStr); - - - if (signalDef->driverType == PMD8751) - { - sprintf(buff, READ_DIAG, driverID); - pStr = cntrl->aux_status_string[driverID]; - recvRtn = send_recv_mess(card, buff, pStr, NULL); - CHECKRTN; - Debug(2, "set_status(): Aux Status_string=%s\n", pStr); - if (sscanf(pStr, "A%d=0x%x",&recvDriver, &recvStatus) == 2) - { - auxstat.All = recvStatus; - Debug(5, "set_status(): drive %d - status byte = %x\n", recvDriver, recvStatus); - } - else - Debug(1, "set_status(): drive %d - INVALID Aux Status string %s\n", driverID, pStr); - } - - /* Check if set_status() motor is currently selected on driver */ - if (selectMotor == motorID) - { - sprintf(buff, READ_POS, driverID); - pStr = cntrl->position_string[driverID]; - recvRtn = send_recv_mess(card, buff, pStr, NULL); - CHECKRTN; - Debug(2, "set_status(): postion_string=%s\n", pStr); - if (sscanf(pStr, "A%d=%ld",&recvDriver, &motorData) == 2) - { - Debug(5, "set_status(): drive %d = Position:%ld\n", recvDriver, motorData); - } - else - Debug(1, "set_status(): drive %d - INVALID position string %s\n", driverID, pStr); - } - else - { - if (signalDef->driverType == PMD8753) - motorData = cntrl->last_position[signal] = 0; - - Debug(5, "set_status(): NOT SELECTED drive %d, motor %d\n", driverID, motorID); - } - - - nodeptr = motor_info->motor_motion; - - - /* Interpret data and move it into global area */ - - if (signalDef->driverType == PMD8753) // Open-Loop Driver - { - /* Drive Enabled */ - status.Bits.EA_POSITION = (mstat.Bits_8753.powerOn) ? 1: 0; - - if (mstat.Bits_8753.inMotion == false) - status.Bits.RA_DONE = 1; - else if (selectMotor == motorID) // Moving only applies to selected motor - status.Bits.RA_DONE = 0; - - /* Limit Switch Status - NOT AVAILABLE */ - status.Bits.RA_PLUS_LS = 0; - status.Bits.RA_MINUS_LS = 0; - status.Bits.RA_HOME = 0; - - /* encoder status - NOT AVAILABLE */ - status.Bits.EA_SLIP = 0; - status.Bits.EA_SLIP_STALL = 0; - status.Bits.EA_HOME = 0; - } - else if (signalDef->driverType == PMD8751) // Closed-Loop Driver - { - // if (mstat.Bits_8751.moveDone == true && (mstat.Bits_8751.homing == false || motor_info->no_motion_count > 5)) - if (mstat.Bits_8751.moveDone == true) - status.Bits.RA_DONE = 1; - else - status.Bits.RA_DONE = 0; - - /* Drive Enabled */ - status.Bits.EA_POSITION = (auxstat.Bits_8751.servoOn) ? 1: 0; - - if (mstat.Bits_8751.powerOn && auxstat.Bits_8751.servoOn) - { - /* Limit Switch Status */ - status.Bits.RA_PLUS_LS = ((mstat.Bits_8751.forLimit) ? 1: 0); - status.Bits.RA_MINUS_LS = ((mstat.Bits_8751.revLimit) ? 1: 0); - status.Bits.RA_HOME = ((mstat.Bits_8751.homing) ? 1: 0); - } - - /* encoder status - NOT AVAILABLE */ - status.Bits.EA_SLIP = 0; - status.Bits.EA_SLIP_STALL = 0; - status.Bits.EA_HOME = 0; - } - - - Debug(2, "set_status(): Axis:%d, New Pos: %ld, Last Pos: %ld", signal, motorData, cntrl->last_position[signal]); - - if (motorData == cntrl->last_position[signal]) - { - motor_info->no_motion_count++; - status.Bits.RA_DIRECTION = 1; - } - else - { - if (signalDef->driverType == PMD8751) // Closed-Loop Driver - motor_info->position = motorData; - else - motor_info->position += (motorData - cntrl->last_position[signal]); - - if (motor_state[card]->motor_info[signal].encoder_present == YES) - { - if (signalDef->driverType == PMD8751) // Closed-Loop Driver - motor_info->encoder_position = (epicsInt32) motorData; - else - motor_info->encoder_position += (epicsInt32) (motorData - cntrl->last_position[signal]); - } - else - motor_info->encoder_position = 0; - - /* Use sign of motor position (always relative) for direction */ - if (signalDef->driverType == PMD8753) - status.Bits.RA_DIRECTION = (motorData >= 0) ? 1 : 0; - else if (signalDef->driverType == PMD8751) - status.Bits.RA_DIRECTION = ((motorData - cntrl->last_position[signal]) >= 0) ? 1 : 0; - - cntrl->last_position[signal] = motorData; - motor_info->no_motion_count = 0; - } - - - plusdir = (status.Bits.RA_DIRECTION) ? true : false; - Debug(1, ", Pos: %d, Dir: %x\n", motor_info->position, plusdir); - - /* Determine if move done because of limit switches */ - if ((plusdir && status.Bits.RA_PLUS_LS) || (!plusdir && status.Bits.RA_MINUS_LS)) - ls_active = true; - - status.Bits.RA_PROBLEM = 0; - - /* Parse motor velocity? */ - /* NEEDS WORK */ - - motor_info->velocity = 0; - - // if (!plusdir) - // motor_info->velocity *= -1; - - setReturn = (!motor_info->no_motion_count || ls_active == true || - status.Bits.RA_DONE | status.Bits.RA_PROBLEM) ? 1 : 0; - - /* Test for post-move processing. */ - if ((status.Bits.RA_DONE || ls_active == true) ) - { - if (signalDef->driverType == PMD8753) - { - cntrl->last_position[signal] = 0; /* Reset last position after each move */ - - if (selectMotor == motorID) - { - /* Clear position on selected motor */ - sprintf(buff, "CHL A%d=%d", driverID, motorID); - send_recv_mess(card, buff, nobuff, NULL); - } - } - - if (nodeptr != 0) - { - /* Allways turn joystick on after a move */ - /* strcpy(buff, JOY_ON); */ - - if (nodeptr->postmsgptr != 0) /* Test for post move record string */ - { - strcpy(buff, nodeptr->postmsgptr); - send_recv_mess(card, buff, nobuff, NULL); - } - - nodeptr->postmsgptr = NULL; - } - } - -exit: - motor_info->status.All = status.All; - return(setReturn); -} - - -/*****************************************************/ -/* atomic write/read function */ -/* PMNC87xx motor controller has a handshake */ -/* with the return of the prompt '>' character */ -/* send_recv_mess() */ -/*****************************************************/ -STATIC int send_recv_mess(int card, char const *send_com, char *recv_com, char const *eos) -{ - struct PMNCcontroller *cntrl; - int size; - size_t nwrite; - size_t nread = 0; - asynStatus status; - int eomReason; - - - size = strlen(send_com); - recv_com[0] = '\0'; - - if (size > MAX_MSG_SIZE) - { - errlogMessage("drvPMNC87xx:send_recv_mess(); message size violation.\n"); - return(MESS_ERR); - } - else if (size == 0) /* Normal exit on empty input message. */ - return (OK); - - if (!motor_state[card]) - { - errlogPrintf("drvPMNC87xx:send_recv_mess() - invalid card #%d\n", card); - return(MESS_ERR); - } - - Debug(2, "send_recv_mess(): message = %s\n", send_com); - - cntrl = (struct PMNCcontroller *) motor_state[card]->DevicePrivate; - - if (eos) - // Temporary Change to End-of-string - pasynOctetSyncIO->setInputEos(cntrl->pasynUser,eos,strlen(eos)); - - - /* Perform atomic write/read operation */ - status = pasynOctetSyncIO->writeRead(cntrl->pasynUser, send_com, size, - recv_com, BUFF_SIZE-1, - PMNC_TIMEOUT, &nwrite, &nread, &eomReason); - if (eos) - // Reset EOS to default - pasynOctetSyncIO->setInputEos(cntrl->pasynUser,PROMPT_EOS,strlen(PROMPT_EOS)); - - if (status != asynSuccess) - { - int int_status = (int) status; - Debug(3, "send_recv_mess(): ERROR - staus =%d, nread = %d\n", int_status, nread); - recv_com[0] = '\0'; - return(MESS_ERR); - } - - Debug(2, "send_recv_mess(): recv message = \"%s\"\n", recv_com); - return(nread); - -} -/*****************************************************/ -/* send a message to the PMNC87xx board */ -/* send_mess() */ -/*****************************************************/ -STATIC RTN_STATUS send_mess(int card, char const *com, char *name) -{ - struct PMNCcontroller *cntrl; - int size; - size_t nwrite; - - size = strlen(com); - - if (size > MAX_MSG_SIZE) - { - errlogMessage("drvPMNC87xx: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("drvPMNC87xx:send_mess() - invalid card #%d\n", card); - return(ERROR); - } - - if (name != NULL) - { - errlogPrintf("drvPMNC87xx:send_mess() - invalid argument = %s\n", name); - return(ERROR); - } - - Debug(2, "send_mess(): message = %s\n", com); - - cntrl = (struct PMNCcontroller *) motor_state[card]->DevicePrivate; - pasynOctetSyncIO->write(cntrl->pasynUser, com, size, - PMNC_TIMEOUT, &nwrite); - - return(OK); -} - - -/* - * FUNCTION... recv_mess(int card, char *com, int flag) - * - * INPUT ARGUMENTS... - * card - controller card # (0,1,...). - * *com - caller's response buffer. - * flag | FLUSH = flush controller's output buffer; set timeout = 0. - * | !FLUSH = retrieve response into caller's buffer; set timeout. - * | 0 = read until '\n' - * | 1 = read until '>' - * - * LOGIC... - * Initialize: - * - receive timeout to zero - * - received string length to zero. - * - * IF controller card does not exist. - * ERROR RETURN. - * ENDIF - * - * SWITCH on port type. - * CASE port type is GPIB. - * BREAK. - * CASE port type is RS232. - * IF input "flag" indicates NOT flushing the input buffer. - * Set receive timeout nonzero. - * ENDIF - * Call pasynOctetSyncIO->read(). - * - * NOTE: The PMNC87xx sometimes responds to an MS command with an error - * message (see PMNC87xx User's Manual Appendix A). This is an - * unconfirmed PMNC87xx bug. Retry read if this is a Hard Travel - * limit switch error. This effectively flushes the error message. - * - * IF input "com" buffer length is > 3 characters, AND, the 1st - * character is an "E" (Maybe this an unsolicited error - * message response?). - * Call pasynOctetSyncIO->read(). - * ENDIF - * BREAK - * ENDSWITCH - * - * NORMAL RETURN. - */ - -STATIC int recv_mess(int card, char *com, int flag) -{ - struct PMNCcontroller *cntrl; - double timeout = 0.; - int flush = 1; - size_t nread = 0; - int eomReason; - int rtnValue; - asynStatus status; - - /* Check that card exists */ - if (!motor_state[card]) - return(MESS_ERR); - - cntrl = (struct PMNCcontroller *) motor_state[card]->DevicePrivate; - - if (flag != FLUSH) { - flush = 0; - timeout = PMNC_TIMEOUT; - } - if (flush) status = pasynOctetSyncIO->flush(cntrl->pasynUser); - - if (flag == 0) - // Temporary Change to EOS to '\n' - pasynOctetSyncIO->setInputEos(cntrl->pasynUser,NL_EOS,strlen(NL_EOS)); - - status = pasynOctetSyncIO->read(cntrl->pasynUser, com, BUFF_SIZE, - timeout, &nread, &eomReason); - - if (flag == 0) - // Reset EOS to '\n' - pasynOctetSyncIO->setInputEos(cntrl->pasynUser,PROMPT_EOS,strlen(PROMPT_EOS)); - - if (status != asynSuccess) - { - int int_status = (int) status; - com[0] = '\0'; - rtnValue = MESS_ERR; - Debug(3, "recv_mess(): ERROR - staus =%d, nread = %d\n", int_status, nread); - } - else - { - Debug(2, "recv_mess(): message = \"%s\"\n", com); - rtnValue = nread; - } - - return (rtnValue); -} - - -/*****************************************************/ -/* Setup system configuration */ -/* PMNC87xxSetup() */ -/*****************************************************/ -RTN_STATUS -PMNC87xxSetup(int num_cards, /* maximum number of controllers in system. */ - int num_drivers, /* maximum number of drivers per controller */ - int scan_rate) /* polling rate - 1/60 sec units. */ -{ - int itera; - - if (num_cards < 1 || num_cards > PMNC87xx_NUM_CARDS) - PMNC87xx_num_cards = PMNC87xx_NUM_CARDS; - else - PMNC87xx_num_cards = num_cards; - - if (num_drivers < 1 || num_drivers > PMNC87xx_NUM_DRIVERS) - PMNC87xx_num_drivers = PMNC87xx_NUM_DRIVERS; - else - PMNC87xx_num_drivers = num_drivers; - - - /* 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 PMNC87xxConfig 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(PMNC87xx_num_cards * - sizeof(struct controller *)); - - for (itera = 0; itera < PMNC87xx_num_cards; itera++) - motor_state[itera] = (struct controller *) NULL; - - return(OK); -} - - -/*****************************************************/ -/* Configure a controller */ -/* PMNC87xxConfig() */ -/*****************************************************/ -RTN_STATUS -PMNC87xxConfig(int card, /* card being configured */ - const char *port, /* asyn port name */ - int address) /* asyn address (GPIB) */ -{ - struct PMNCcontroller *cntrl; - - if (card < 0 || card >= PMNC87xx_num_cards) - return (ERROR); - - motor_state[card] = (struct controller *) malloc(sizeof(struct controller)); - motor_state[card]->DevicePrivate = malloc(sizeof(struct PMNCcontroller)); - cntrl = (struct PMNCcontroller *) motor_state[card]->DevicePrivate; - - strcpy(cntrl->asyn_port, port); - cntrl->asyn_address = address; - 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 PMNCcontroller *cntrl; - struct PMD_axis *axisdef; - int card_index, motor_index; - char buff[BUFF_SIZE]; - char *bufptr; - int total_axis = 0; - int driverIndex; - int rtnCnt = 0; - asynStatus asynRtn; - bool connectOK; - - initialized = true; /* Indicate that driver is initialized. */ - nextSocket = 0; - - /* Check for setup */ - if (PMNC87xx_num_cards <= 0) - return(ERROR); - - for (card_index = 0; card_index < PMNC87xx_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 PMNCcontroller *) brdptr->DevicePrivate; - - /* Initialize communications channel */ - asynRtn = pasynOctetSyncIO->connect(cntrl->asyn_port, cntrl->asyn_address, &cntrl->pasynUser, NULL); - if (asynRtn != asynSuccess) { - printf("drvPMNC:motor_init(), error calling pasynOctetSyncIO->connect port=%s error=%d\n", - cntrl->asyn_port, asynRtn); - } else { - socketStructs[nextSocket].pasynUserCommon = cntrl->pasynUser; - socketStructs[nextSocket].connected = true; - nextSocket++; - } - - connectOK = (asynRtn == asynSuccess) ? true : false; - - if (connectOK) - { - - int retry; - - - - /* Set command End-of-string */ - pasynOctetSyncIO->setInputEos(cntrl->pasynUser,PROMPT_EOS,strlen(PROMPT_EOS)); - pasynOctetSyncIO->setOutputEos(cntrl->pasynUser,CMND_EOS,strlen(CMND_EOS)); - - - /* flush any junk at input port - should not be any data available */ - pasynOctetSyncIO->flush(cntrl->pasynUser); - - rtnCnt = 0; - retry = 0; - - /* Send a message to the board, see if it exists */ - do - { - rtnCnt = send_recv_mess(card_index, GET_IDENT, buff, NULL); - retry++; - /* Return value is length of response string */ - } while(rtnCnt <= 0 && retry < 3); - - - // Resetting the controller loses the ethernet connection - bad idea - if (false) - { - /* Reset Controller: takes > 5 sec */ - send_recv_mess(card_index, INIT_ALL, nobuff, NULL); - - retry = 0; - rtnCnt = 0; - /* Wait for Controller to return */ - do - { - rtnCnt = send_recv_mess(card_index, GET_IDENT, buff, NULL); - retry++; - /* Return value is length of response string */ - } while(rtnCnt <= 0 && retry < 1000); - - } - - } - - if (connectOK && rtnCnt > 0) - { - strncpy(brdptr->ident, &buff[0], MAX_IDENT_LEN); /* Save Version info */ - brdptr->localaddr = (char *) NULL; - brdptr->motor_in_motion = 0; - - /* Set Motion Master model indicator. */ - bufptr = strstr(brdptr->ident, VER_STR); - if (bufptr == NULL) - { - errlogPrintf("drvPMNC87xx.c:motor_init() - unknown version = %s\n", brdptr->ident); - motor_state[card_index] = (struct controller *) NULL; - continue; - } - /* Check for known version - 1.x */ - switch (*(bufptr + strlen(VER_STR))) - { - case '0': - cntrl->pmnc = PMNC8750; - break; - case '5': - case '6': - cntrl->pmnc = PMNC8752; - break; - default: - errlogPrintf("drvPMNC87xx:motor_init() - invalid model = %s\n", brdptr->ident); - return(ERROR); - break; - } - - /* Check for 'STA\n' version = 1.5.4 - * because this version requires a NL input EOS on the STA command */ - cntrl->changeEOS = (*(bufptr + strlen(VER_STR) + 2) == '4') || - (*(bufptr + strlen(VER_STR) + 2) == '3') ? true : false; - - total_axis = 0; - driverIndex = 0; - axisdef = cntrl->axisDef; - - if (cntrl->pmnc == PMNC8750) - { - /* Use indirect method to determine axis count - Only 8753 driver supported */ - send_mess(card_index, GET_MPV, NULL); - /* Number of return strings will tell us how many axes this controller has */ - /* Return format: A M= */ - while (recv_mess(card_index, buff, 0) > 0) - { - sscanf(buff, "A%d M%d", &driverIndex, &motor_index); - axisdef[total_axis].driverType = PMD8753; - axisdef[total_axis].driverNum = driverIndex; - axisdef[total_axis].motorNum = motor_index; - brdptr->motor_info[total_axis].motor_motion = NULL; - Debug(3, "motor_init(): Next Axis %s\n", buff); - total_axis++; - } - } - else // PMNC8752 - { - union {int All; PMD_model ID;} driver; - int addAxis, newAxis, tmpAxis; - - /* Use direct driver type query (DRT) */ - send_mess(card_index, GET_DRT, NULL); - /* Number of return strings will tell us how many axes this controller has */ - /* Return format: A */ - while (recv_mess(card_index, buff, 0) > 0) - { - sscanf(buff, "A%d=%d", &driverIndex, &driver.All); - if (driver.ID == PMD8753) - addAxis = 3; - else if (driver.ID == PMD8751) - addAxis = 1; - else - { - errlogPrintf("drvPMNC87xx:motor_init() - invalid driver = %d\n", driver.All); - return(ERROR); - } - - Debug(3, "motor_init(): Next Driver %s\n", buff); - - for (newAxis = 0, tmpAxis = total_axis; newAxis < addAxis; newAxis++, tmpAxis++) - { - axisdef[tmpAxis].driverType = driver.ID; - axisdef[tmpAxis].driverNum = driverIndex; - axisdef[tmpAxis].motorNum = newAxis; - brdptr->motor_info[tmpAxis].motor_motion = NULL; - } - - total_axis += addAxis; - } - - } - - brdptr->total_axis = total_axis; - cntrl->total_drivers = driverIndex; - cntrl->status = NORMAL; - Debug(2, "motor_init(): Total Drivers %d\nTotal Axis=%d\n", driverIndex, brdptr->total_axis); - - for (motor_index = 0; motor_index < total_axis; motor_index++) - { - struct mess_info *motor_info = &brdptr->motor_info[motor_index]; - - motor_info->status.All = 0; - motor_info->no_motion_count = 0; - motor_info->encoder_position = 0; - motor_info->position = 0; - cntrl->last_position[motor_index] = 0; /* Used to accumulate position on 8753 drivers */ - - - /* Encoder Enable */ - motor_info->encoder_present = YES; - motor_info->status.Bits.EA_PRESENT = 1; - // motor_info->pid_present = YES; - motor_info->status.Bits.GAIN_SUPPORT = 1; - - 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 *) "PMNC87xx_motor", epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackMedium), - (EPICSTHREADFUNC) motor_task, (void *) &targs); - - // void epicsAtExit( (*epicsExitFunc)(void *arg), void *arg); - /* Remove at exit call - not fully understood yet */ - /* epicsAtExit(&closePMNCSockets, NULL); */ - - return(OK); -} - - -/***************************************************************************************/ -STATIC void CloseSocket(int SocketIndex) -{ - socketStruct *psock; - asynUser *pasynUser; - int status; - - if ((SocketIndex < 0) || (SocketIndex >= nextSocket)) { - printf("drvPMNC CloseSocket: invalid SocketIndex %d\n", SocketIndex); - return; - } - psock = &socketStructs[SocketIndex]; - pasynUser = psock->pasynUserCommon; - status = pasynCommonSyncIO->disconnectDevice(pasynUser); - if (status != asynSuccess ) { - asynPrint(pasynUser, ASYN_TRACE_ERROR, - "drvPMNC CloseSocket: error calling pasynCommonSyncIO->disconnect, status=%d, %s\n", - status, pasynUser->errorMessage); - return; - } else - printf("drvPMNC CloseSocket: Disconnected SocketIndex %d\n",SocketIndex); - - psock->connected = false; -} - -/***************************************************************************************/ -void closePMNCSockets(void *arg) -{ - int i; - - for (i=0; i.512msec) */ - bool slewDone :1; /* Set when trapesoidal slew time over */ - bool accelDone :1; /* Set when trapesoidal accell time over */ - bool servoOn :1; /* Set if servo mode ON - else OpenLoop */ - bool posWrap :1; /* Set on 32 bit overflow (position) */ - bool diagBit :1; /* Used to encode error diagnostics */ - -#else - bool diagBit :1; /* Used to encode error diagnostics */ - bool posWrap :1; /* Set on 32 bit overflow (position) */ - bool servoOn :1; /* Set if servo mode ON - else OpenLoop */ - bool accelDone :1; /* Set when trapesoidal accell time over */ - bool slewDone :1; /* Set when trapesoidal slew time over */ - bool servoOverRun :1; /* Set if servo process time overrun (>.512msec) */ - bool bit6 :1; /* Bit #6 N/A. */ - bool bit7 :1; /* Bit #7 N/A. */ -#endif - } Bits_8751; -} MOTOR_AUX_STATUS; - - - - -#endif /* INCdrvPMNCComh */ -