From 4ec8c9247cd0bc6b876160e6ca228e8067c71e9c Mon Sep 17 00:00:00 2001 From: kpetersn Date: Fri, 12 Apr 2019 15:42:33 -0500 Subject: [PATCH] Removed SmarActMCSSrc; Added motorSmarAct submodule --- .gitmodules | 3 + .../motor.substitutions.smaractmcs | 6 - iocBoot/iocWithAsyn/st.cmd.smaractmcs | 27 - modules/Makefile | 1 + modules/motorSmarAct | 1 + motorApp/Makefile | 3 - motorApp/SmarActMCSSrc/ChangeLog | 2 - motorApp/SmarActMCSSrc/Makefile | 29 - motorApp/SmarActMCSSrc/README | 260 ------ motorApp/SmarActMCSSrc/devSmarActMCSMotor.dbd | 2 - .../SmarActMCSSrc/smarActMCSMotorDriver.cpp | 786 ------------------ .../SmarActMCSSrc/smarActMCSMotorDriver.h | 97 --- 12 files changed, 5 insertions(+), 1212 deletions(-) delete mode 100644 iocBoot/iocWithAsyn/motor.substitutions.smaractmcs delete mode 100644 iocBoot/iocWithAsyn/st.cmd.smaractmcs create mode 160000 modules/motorSmarAct delete mode 100644 motorApp/SmarActMCSSrc/ChangeLog delete mode 100644 motorApp/SmarActMCSSrc/Makefile delete mode 100644 motorApp/SmarActMCSSrc/README delete mode 100644 motorApp/SmarActMCSSrc/devSmarActMCSMotor.dbd delete mode 100644 motorApp/SmarActMCSSrc/smarActMCSMotorDriver.cpp delete mode 100644 motorApp/SmarActMCSSrc/smarActMCSMotorDriver.h diff --git a/.gitmodules b/.gitmodules index eb9aeb74..a8c2fce1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -82,3 +82,6 @@ [submodule "modules/motorPIGCS2"] path = modules/motorPIGCS2 url = https://github.com/epics-motor/motorPIGCS2.git +[submodule "modules/motorSmarAct"] + path = modules/motorSmarAct + url = https://github.com/epics-motor/motorSmarAct.git diff --git a/iocBoot/iocWithAsyn/motor.substitutions.smaractmcs b/iocBoot/iocWithAsyn/motor.substitutions.smaractmcs deleted file mode 100644 index 7af5a401..00000000 --- a/iocBoot/iocWithAsyn/motor.substitutions.smaractmcs +++ /dev/null @@ -1,6 +0,0 @@ -file "$(MOTOR)/db/basic_asyn_motor.db" -{ -pattern -{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT} -{MOTR:B034:, 1, 100, "asynMotor", "P0", 0, "channel1", mm, Pos, 1, 0, 0.2, 0, 1, 0.2, 1e-6, 2, 3, -3, ""} -} diff --git a/iocBoot/iocWithAsyn/st.cmd.smaractmcs b/iocBoot/iocWithAsyn/st.cmd.smaractmcs deleted file mode 100644 index 803864e3..00000000 --- a/iocBoot/iocWithAsyn/st.cmd.smaractmcs +++ /dev/null @@ -1,27 +0,0 @@ -< envPaths - -# Tell EPICS all about the record types, device-support modules, drivers, -# etc. in this build from CARS -dbLoadDatabase("../../dbd/WithAsyn.dbd") -WithAsyn_registerRecordDeviceDriver(pdbbase) - -### Motors -# Motors substitutions, customize this for your motor -dbLoadTemplate "motor.substitutions.smaractmcs" - -# Configure each controller -drvAsynIPPortConfigure("TSP2","ts-b34-nw08:2102",0,0,0) - -# Controller port, asyn port, number of axis, moving poll period, idle poll period -# smarActMCSCreateController(const char *motorPortName, const char *ioPortName, int numAxes, double movingPollPeriod, double idlePollPeriod); -smarActMCSCreateController("P0", "TSP2", 1, 0.020, 1.0) - -# Controller port, axis number, controller channel -# smarActMCSCreateAxis(const char *motorPortName, int axisNumber, int channel) -smarActMCSCreateAxis("P0", 0, 1); -smarActMCSCreateAxis("P0", 0, 0); - -asynSetTraceIOMask("XPS1", 0, 2) - -iocInit() - diff --git a/modules/Makefile b/modules/Makefile index 7768e9a7..2fb7b416 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -33,6 +33,7 @@ SUBMODULES += motorPIGCS2 ifdef LUA SUBMODULES += motorScriptMotor endif +SUBMODULES += motorSmarAct SUBMODULES += motorSmartMotor SUBMODULES += motorThorLabs diff --git a/modules/motorSmarAct b/modules/motorSmarAct new file mode 160000 index 00000000..07001329 --- /dev/null +++ b/modules/motorSmarAct @@ -0,0 +1 @@ +Subproject commit 070013297dd5110cde04a5dfd1875e2280830f9e diff --git a/motorApp/Makefile b/motorApp/Makefile index 72104eea..c5ce2f41 100644 --- a/motorApp/Makefile +++ b/motorApp/Makefile @@ -21,9 +21,6 @@ MotorSimSrc_DEPEND_DIRS = MotorSrc DIRS += PC6KSrc PC6KSrc_DEPEND_DIRS = MotorSrc -DIRS += SmarActMCSSrc -SmarActMCSSrc_DEPEND_DIRS = MotorSrc - endif # Install the edl files diff --git a/motorApp/SmarActMCSSrc/ChangeLog b/motorApp/SmarActMCSSrc/ChangeLog deleted file mode 100644 index 139597f9..00000000 --- a/motorApp/SmarActMCSSrc/ChangeLog +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/motorApp/SmarActMCSSrc/Makefile b/motorApp/SmarActMCSSrc/Makefile deleted file mode 100644 index 58b94c01..00000000 --- a/motorApp/SmarActMCSSrc/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -# Makefile -TOP=../.. - -include $(TOP)/configure/CONFIG -#---------------------------------------- -# ADD MACRO DEFINITIONS AFTER THIS LINE -#============================= - -#================================================== -# Build an IOC support library -LIBRARY_IOC = smarActMCSMotor - -# motorRecord.h will be created from motorRecord.dbd -# install devMotorSoft.dbd into /dbd -DBD += devSmarActMCSMotor.dbd - -INC += smarActMCSMotorDriver.h - -# The following are compiled and added to the Support library -smarActMCSMotor_SRCS += smarActMCSMotorDriver.cpp - -smarActMCSMotor_LIBS += motor -smarActMCSMotor_LIBS += asyn -smarActMCSMotor_LIBS += $(EPICS_BASE_IOC_LIBS) - -include $(TOP)/configure/RULES -#---------------------------------------- -# ADD RULES AFTER THIS LINE - diff --git a/motorApp/SmarActMCSSrc/README b/motorApp/SmarActMCSSrc/README deleted file mode 100644 index 49175510..00000000 --- a/motorApp/SmarActMCSSrc/README +++ /dev/null @@ -1,260 +0,0 @@ -Driver for smarAct MCS Positioner -================================== - -Till Straumann , 9/2011 - -Introduction ------------- - -This driver supports the smarAct MCS Positioner -by implementing subclasses of the 'asynMotorController' -and 'asynMotorAxis' objects. - -Communication with the hardware is established via -a 'asyn port' driver layer and it is thus possible -to use either a physical RS232 port or a terminal -server in a transparent fashion. - -Note: the reader is assumed to be familiar with the -motor record. Please consult relevant documentation. - -Restrictions ------------- - -The driver does not support all features of the MCS -firmware (some of which are outside of the scope of -the motor record). Neither are all features of the -motor record supported. - -The driver currently relies on the presence of a -linear position sensor and uses a command set specific -to such sensors. Rotary sensors and the associated -command set are not supported. Closed-loop mode is -used exclusively for all motion commands. - -Limit switches are not supported (the MCS command -set defines no interface to hardware limit switches). - -The driver operates directly in user coordinates (nm) -no translation into 'steps' is supported. - -The 'JOG' feature of the motor record is implemented -using a relative-move command to a 'far-away' target. -This might or might not work if a different position -sensor (working at a different scale) is employed. - -Acceleration-control is not supported. - -The drivers makes the following assumptions about -the setup - - reset command ('R') is never used by third party - while the driver is running. - - 'synchronous' communication mode ('SCM') is in - effect. - - 'keep-alive' mode is not in effect (but if the - keep-alive time is longer than the driver's - slowest polling period then 'keep-alive' mode - should work). - - sensor is never disabled ('SSE'). Permanent 'on' - or power-save mode are OK. - - sensor type ('SST') is configured correctly (must - be performed once by third-party when a new unit - is commissioned). - - sensor is properly calibrated ('CS') but this - must not be performed by third party while this - driver is running. - - baud rate is configured correctly at both ends - ('CB') and terminal-server or UART port setup. - -Otherwise, a secondary driver using an orthogonal -command set may run concurrently with this driver -as long as it properly shares the asyn port driver -in charge of serial communication. - -Special Features ----------------- - -Position Reference -.................. -After power-up the position sensor must be positioned -to a reference mark in order for it to provide -absolute positions. The 'MOTOR_HOMED' bit in the -'MSTA' field reflects the status of the positioner. -Only if 'MOTOR_HOMED' is set the absolute position -is correct. Note that this bit is read from the -hardware and is hence preserved across IOC reboots -(as long as power from the MCS is not removed). - -Position Holding -................ -All motion commands are executed in 'closed-loop' -mode of the MCS controller, i.e., the controller -hardware itself drives the positioner to the target -in 'closed-loop' mode. -The MCS can also be instructed to actively hold the -target position (compensating small movements, drift -etc.). This feature can be programmed using the -motor record's CNEN field (enabled: MCS holds -target position indefinitely; disabled: MCS goes -to open-loop mode as soon as the target is -reached). - -Usage Information ------------------ -The position sensor has a very high (1nm) -resolution and it is unlikely (especially -in 'no-hold' mode, i.e., if CNEN is 'disabled') -that the target position can be reached -exactly. In order to avoid many retries -the dead-band (RDBD) and/or other parameters -of the motor record may need appropriate -tuning. - -It should also be noted that the positioner -is quite fast and performes moves almost -'instantaneously' (as perceived by an operator) -unless the speed is reduced (VELO). -'JOG' mode is probably useless unless the jog -velocity (JVEL) is set to a relatively low -value which allows the operator to observe -the motion. However, performing a JOG operation -with JVEL at zero will be rejected (since zero -would choose the default speed which is too -high to be useful). The driver immediately -reports the motion as 'DONE' (in MSTA). -It is the user's responsibility to clear the -JOGF/JOGR field if this happens. - -Building an Application -- - - - - - - - - - - - -Building the driver into an application requires - -a) the 'asyn', 'motor' and 'smarActMCSMotor' (this - driver) packages/modules to be built and - installed. The application's RELEASE file must - point to these packages so that the build process - locates headers and libraries etc. - -b) the application's '.dbd' file must contain - - motorSupport.dbd - - devSmarActMCSMotor.dbd - as well as an 'asyn' port driver for serial - communication. In case of a connection via - TCP/IP + terminal server this would be - - drvAsynIPPort.dbd - - These '.dbd' files are best listed in the - application Makefile: - _DBD += motorSupport.dbd - _DBD += devSmarActMCSMotor.dbd - _DBD += drvAsynIPPort.dbd - -c) the application must be linked against - the 'smarActMCSMotor', 'motor' and 'asyn' - libraries, e.g., - - _LIBS += smarActMCSMotor motor asyn - -Driver Run-Time Configuration -- - - - - - - - - - - - - - - -For each MCS controller a driver instance needs -to be configured either from a startup script, -C or C++ code (the C++ constructor takes the -same arguments). -However, at first an asyn port driver for -serial communication must be created (e.g. -from the startup script). E.g., when using -a terminal server then drvAsynIPPort may be -used: - - drvAsynIPPortConfigure("myTS1","terminalserver:port",0,0,0) - -Next, an MCS controller driver instance is -created. The respective call takes the following -arguments: - - -smarActMCSCreateController( - const char *motorPortName, - const char *ioPortName, - int numAxes, - double movingPollPeriod, - double idlePollPeriod); - - motorPortName: unique string to identify this - instance to be used in the - motor record's 'OUT' field. - ioPortName: asyn port name identifying the - serial link for communication - with the MCS. - Note that such a link must - be created prior to creating - a MCS controller driver instance. - numAxes: number of axes this MCS supports. - movingPollPeriod: period (in seconds - since - this is a 'double' parameter - fractional seconds are possible) - at which the MCS is polled for - status changes while the - positioner is moving. - idlePollPeriod: period (in seconds) at which - the MCS is polled for status - changes while the positioner - is stopped. - -E.g., to configure a driver with one axis using -the serial connection 'myTS1' configured in the -prior example we use - -smarActMCSCreateController("myMotor1","myTS1",1,0.02,1.0) - -This results in a polling interval of 20ms -while moving and 1s while idle. The driver -instance is named 'myMotor1' and can be -addressed from a motorRecord's OUT field: - - field(DTYP, "asynMotor") - field(OUT, "asyn(myMotor1,0)") - -After creating a controller, one or more MCS axes -are created for that controller. The respective -call takes the following arguments: - - -smarActMCSCreateAxis( - const char *motorPortName, - int axisNumber, - int channel) -{ - - motorPortName: unique string to identify this - instance to be used in the - motor record's 'OUT' field. - axisNumber: axis number being created. - channel: channel that the axis is physically - connected to. - Note that the channel will be - prepended to the command string - sent to the particular axis. - -Call the smarActMCSCreateAxis() function for -each axis that needs to be configured. - -Terminal Server / RS232 Port Notes -- - - - - - - - - - - - - - - - - - -It is the user's responsibility to configure -the serial port so it matches the MCS' setup. - -Note that a terminal server might need -additional configuration to make sure that -a 'raw' TCP connection is used. Otherwise, -the terminal server might use other protocols -(most notably: the TELNET protocol) on top -of TCP which result in extra characters being -inserted in the data stream which are not -or mis-interpreted by this driver which -expects a 'raw' communication channel. -On some terminal servers a raw TCP socket -may listen on a different port number than -used for a TELNET connection. - diff --git a/motorApp/SmarActMCSSrc/devSmarActMCSMotor.dbd b/motorApp/SmarActMCSSrc/devSmarActMCSMotor.dbd deleted file mode 100644 index 4b28dd52..00000000 --- a/motorApp/SmarActMCSSrc/devSmarActMCSMotor.dbd +++ /dev/null @@ -1,2 +0,0 @@ -registrar(smarActMCSMotorRegister) -#driver(motorMCS) diff --git a/motorApp/SmarActMCSSrc/smarActMCSMotorDriver.cpp b/motorApp/SmarActMCSSrc/smarActMCSMotorDriver.cpp deleted file mode 100644 index bf35d6b7..00000000 --- a/motorApp/SmarActMCSSrc/smarActMCSMotorDriver.cpp +++ /dev/null @@ -1,786 +0,0 @@ - -/* Motor driver support for smarAct MCS RS-232 Controller */ - -/* Derived from ACRMotorDriver.cpp by Mark Rivers, 2011/3/28 */ - -/* Author: Till Straumann , 9/11 */ - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -/* Static configuration parameters (compile-time constants) */ -#undef DEBUG - -#define CMD_LEN 50 -#define REP_LEN 50 -#define DEFLT_TIMEOUT 2.0 - -#define HOLD_FOREVER 60000 -#define HOLD_NEVER 0 -#define FAR_AWAY 1000000000 /*nm*/ -#define UDEG_PER_REV 360000000 - -// Windows and vxWorks do not have rint(), but minGW does -#if defined __MINGW32__ || defined __MINGW64__ -#elif defined _WIN32 || defined vxWorks -double rint(double x) -{ - //middle value point test - if (ceil(x+0.5) == floor(x+0.5)) - { - int a = (int)ceil(x); - if (a%2 == 0) return ceil(x); - else return floor(x); - } - else return floor(x+0.5); -} -#endif - - -/* The asyn motor driver apparently can't cope with exceptions */ -#undef ASYN_CANDO_EXCEPTIONS -/* Define this if exceptions should be thrown and it is OK to abort the application */ -#undef DO_THROW_EXCEPTIONS - -#if defined(ASYN_CANDO_EXCEPTIONS) || defined(DO_THROW_EXCEPTIONS) -#define THROW_(e) throw e -#else -#define THROW_(e) epicsPrintf("%s\n",e.what()); -#endif - -enum SmarActMCSStatus { - Stopped = 0, - Stepping = 1, - Scanning = 2, - Holding = 3, - Targeting = 4, - MoveDelay = 5, - Calibrating = 6, - FindRefMark = 7, - Locked = 9 -}; - -SmarActMCSException::SmarActMCSException(SmarActMCSExceptionType t, const char *fmt, ...) - : t_(t) -{ -va_list ap; - if ( fmt ) { - va_start(ap, fmt); - epicsVsnprintf(str_, sizeof(str_), fmt, ap); - va_end(ap); - } else { - str_[0] = 0; - } -}; - -SmarActMCSException::SmarActMCSException(SmarActMCSExceptionType t, const char *fmt, va_list ap) - : t_(t) -{ - epicsVsnprintf(str_, sizeof(str_), fmt, ap); -} - -/* Parse reply from MCS and return the value converted to a number. - * - * If the string cannot be parsed, i.e., is not in the format - * ':' , , , ',' , - * - * then the routine returns '-1'. - * - * Otherwise, if starts with 'E' - * (which means an 'Error' code) then the (always non-negative) - * error code is returned (may be zero in case of an 'acknowledgement' - * message in synchronous mode). - * - * If the string is parsed successfully then is passed up - * in *val_p. - * - * Hence - return code nonzero -> error (error code if > 0, parse error - * otherwise) - * - return code zero -> successful ACK or command reply; value - * in *val_p. - */ -int -SmarActMCSController::parseReply(const char *reply, int *ax_p, int *val_p) -{ -char cmd[10]; - if ( 3 != sscanf(reply, ":%10[A-Z]%i,%i", cmd, ax_p, val_p) ) - return -1; - return 'E' == cmd[0] ? *val_p : 0; -} - -/* Parse angle from MCS and return the value converted to a number. - * - * If the string cannot be parsed, i.e., is not in the format - * ':' , , , ',' , , ',' , - * - * then the routine returns '-1'. - * - * Otherwise, if starts with 'E' - * (which means an 'Error' code) then the (always non-negative) - * error code is returned (may be zero in case of an 'acknowledgement' - * message in synchronous mode). - * - * If the string is parsed successfully then is passed up - * in *val_p. - * - * Hence - return code nonzero -> error (error code if > 0, parse error - * otherwise) - * - return code zero -> successful ACK or command reply; value - * in *val_p. - */ -int -SmarActMCSController::parseAngle(const char *reply, int *ax_p, int *val_p, int *rot_p) -{ -char cmd[10]; - if ( 4 != sscanf(reply, ":%10[A-Z]%i,%i,%i", cmd, ax_p, val_p, rot_p) ) - return -1; - // Will this ever get called? An error response fewer values than an angle response - return 'E' == cmd[0] ? *val_p : 0; -} - -SmarActMCSController::SmarActMCSController(const char *portName, const char *IOPortName, int numAxes, double movingPollPeriod, double idlePollPeriod) - : asynMotorController(portName, numAxes, - 0, // parameters - 0, // interface mask - 0, // interrupt mask - ASYN_CANBLOCK | ASYN_MULTIDEVICE, - 1, // autoconnect - 0,0) // default priority and stack size - , asynUserMot_p_(0) -{ -asynStatus status; -char junk[100]; -size_t got_junk; -int eomReason; -pAxes_ = (SmarActMCSAxis **)(asynMotorController::pAxes_); - - status = pasynOctetSyncIO->connect(IOPortName, 0, &asynUserMot_p_, NULL); - if ( status ) { - asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, - "SmarActMCSController:SmarActMCSController: cannot connect to MCS controller\n"); - THROW_(SmarActMCSException(MCSConnectionError, "SmarActMCSController: unable to connect serial channel")); - } - - // slurp away any initial telnet negotiation; there is no guarantee that - // the other end will not send some telnet chars in the future. The terminal - // server should really be configured to 'raw' mode! - pasynOctetSyncIO->read(asynUserMot_p_, junk, sizeof(junk), 2.0, &got_junk, &eomReason); - if ( got_junk ) { - epicsPrintf("SmarActMCSController(%s): WARNING - detected unexpected characters on link (%s); make sure you have a RAW (not TELNET) connection\n", portName, IOPortName); - } - - pasynOctetSyncIO->setInputEos ( asynUserMot_p_, "\n", 1 ); - pasynOctetSyncIO->setOutputEos( asynUserMot_p_, "\n", 1 ); - - // Create axes -/* for ( ax=0; axwriteRead( asynUserMot_p_, buf, strlen(buf), rep, len, timeout, &nwrite, got_p, &eomReason); - - //asynPrint(c_p_->pasynUserSelf, ASYN_TRACEIO_DRIVER, "sendCmd()=%s", buf); - - return status; -} - -asynStatus -SmarActMCSController::sendCmd(size_t *got_p, char *rep, int len, double timeout, const char *fmt, ...) -{ -va_list ap; -asynStatus status; - va_start(ap, fmt); - status = sendCmd(got_p, rep, len, timeout, fmt, ap); - va_end(ap); - return status; -} - - -asynStatus SmarActMCSController::sendCmd(size_t *got_p, char *rep, int len, const char *fmt, ...) -{ -va_list ap; -asynStatus status; - va_start(ap, fmt); - status = sendCmd(got_p, rep, len, DEFLT_TIMEOUT, fmt, ap); - va_end(ap); - return status; -} - -asynStatus SmarActMCSController::sendCmd(char *rep, int len, const char *fmt, ...) -{ -va_list ap; -asynStatus status; -size_t got; - va_start(ap, fmt); - status = sendCmd(&got, rep, len, DEFLT_TIMEOUT, fmt, ap); - va_end(ap); - return status; -} - -/* Obtain value of the 'motorClosedLoop_' parameter (which - * maps to the record's CNEN field) - */ -int -SmarActMCSAxis::getClosedLoop() -{ -int val; - c_p_->getIntegerParam(axisNo_, c_p_->motorClosedLoop_, &val); - return val; -} - -SmarActMCSAxis::SmarActMCSAxis(class SmarActMCSController *cnt_p, int axis, int channel) - : asynMotorAxis(cnt_p, axis), c_p_(cnt_p) -{ - int val; - int angle; - int rev; - channel_ = channel; - - asynPrint(c_p_->pasynUserSelf, ASYN_TRACEIO_DRIVER, "SmarActMCSAxis::SmarActMCSAxis -- creating axis %u\n", axis); - - comStatus_ = getVal("GCLS",&vel_); -#ifdef DEBUG - printf("GCLS %u returned %i\n", axis, comStatus_); -#endif - if ( comStatus_ ) - goto bail; - if ( (comStatus_ = getVal("GS", &val)) ) - goto bail; - - if ( Holding == val ) { - // still holding? This means that - in a previous life - the - // axis was configured for 'infinite holding'. Inherit this - // (until the next 'move' command that is). - /// - holdTime_ = HOLD_FOREVER; - } else { - // initial value from 'closed-loop' property - holdTime_ = getClosedLoop() ? HOLD_FOREVER : 0; - } - - // Query the sensor type - if ( (comStatus_ = getVal("GST", &sensorType_)) ) - goto bail; - - // Determine if stage is a rotation stage - if (sensorType_ == 2 || sensorType_ == 8 || sensorType_ == 14 || sensorType_ == 20 || sensorType_ == 22 || sensorType_ == 23 || (sensorType_ >= 25 && sensorType_ <= 29)) { - isRot_ = 1; - - if ( asynSuccess == getAngle(&angle, &rev) ) { - setIntegerParam(c_p_->motorStatusHasEncoder_, 1); - setIntegerParam(c_p_->motorStatusGainSupport_, 1); - } - } - else { - isRot_ = 0; - - if ( asynSuccess == getVal("GP",&val) ) { - setIntegerParam(c_p_->motorStatusHasEncoder_, 1); - setIntegerParam(c_p_->motorStatusGainSupport_, 1); - } - } - - -bail: - setIntegerParam(c_p_->motorStatusProblem_, comStatus_ ? 1 : 0 ); - setIntegerParam(c_p_->motorStatusCommsError_, comStatus_ ? 1 : 0 ); - - callParamCallbacks(); - - if ( comStatus_ ) { - THROW_(SmarActMCSException(MCSCommunicationError, "SmarActMCSAxis::SmarActMCSAxis -- channel %u ASYN error %i", axis, comStatus_)); - } - -} - -/* Read a parameter from the MCS (nothing to do with asyn's parameter - * library). - * - * parm_cmd: MCS command (w/o ':' char) to read parameter - * val_p: where to store the value returned by the MCS - * - * RETURNS: asynError if an error occurred, asynSuccess otherwise. - */ -asynStatus -SmarActMCSAxis::getVal(const char *parm_cmd, int *val_p) -{ -char rep[REP_LEN]; -asynStatus st; -int ax; - - //asynPrint(c_p_->pasynUserSelf, ASYN_TRACEIO_DRIVER, "getVal() cmd=:%s%u", parm_cmd, this->channel_); - - //st = c_p_->sendCmd(rep, sizeof(rep), ":%s%u", parm_cmd, this->axisNo_); - st = c_p_->sendCmd(rep, sizeof(rep), ":%s%u", parm_cmd, this->channel_); - if ( st ) - return st; - return c_p_->parseReply(rep, &ax, val_p) ? asynError: asynSuccess; -} - -/* Read the position of rotation stage - * - * parm_cmd: MCS command (w/o ':' char) to read parameter - * val_p: where to store the value returned by the MCS - * - * RETURNS: asynError if an error occurred, asynSuccess otherwise. - */ -asynStatus -SmarActMCSAxis::getAngle(int *val_p, int *rev_p) -{ -char rep[REP_LEN]; -asynStatus st; -int ax; - - //asynPrint(c_p_->pasynUserSelf, ASYN_TRACEIO_DRIVER, "getAngle() cmd=:%s%u", parm_cmd, this->channel_); - - st = c_p_->sendCmd(rep, sizeof(rep), ":GA%u", this->channel_); - if ( st ) - return st; - return c_p_->parseAngle(rep, &ax, val_p, rev_p) ? asynError: asynSuccess; -} - -asynStatus -SmarActMCSAxis::poll(bool *moving_p) -{ -int val; -int angle; -int rev; -enum SmarActMCSStatus status; - - if ( isRot_ ) { - if ( (comStatus_ = getAngle(&angle, &rev)) ) - goto bail; - // Convert angle and revs to total angle - val = rev * UDEG_PER_REV + angle; - } - else { - if ( (comStatus_ = getVal("GP", &val)) ) - goto bail; - } - - setDoubleParam(c_p_->motorEncoderPosition_, (double)val); - setDoubleParam(c_p_->motorPosition_, (double)val); -#ifdef DEBUG - printf("POLL (position %d)", val); -#endif - - if ( (comStatus_ = getVal("GS", &val)) ) - goto bail; - - status = (enum SmarActMCSStatus)val; - - switch ( status ) { - default: - *moving_p = false; - break; - - /* If we use 'infinite' holding (until the next 'move' command) - * then the 'Holding' state must be considered 'not moving'. However, - * if we use a 'finite' holding time then we probably should consider - * the 'move' command incomplete until the holding time expires. - */ - case Holding: - *moving_p = HOLD_FOREVER == holdTime_ ? false : true; - break; - - case Stepping: - case Scanning: - case Targeting: - case MoveDelay: - case Calibrating: - case FindRefMark: - *moving_p = true; - break; - } - - setIntegerParam(c_p_->motorStatusDone_, ! *moving_p ); - - - /* Check if the sensor 'knows' absolute position and - * update the MSTA 'HOMED' bit. - */ - if ( (comStatus_ = getVal("GPPK", &val)) ) - goto bail; - - setIntegerParam(c_p_->motorStatusHomed_, val ? 1 : 0 ); - -#ifdef DEBUG - printf(" status %u", status); -#endif - -bail: - setIntegerParam(c_p_->motorStatusProblem_, comStatus_ ? 1 : 0 ); - setIntegerParam(c_p_->motorStatusCommsError_, comStatus_ ? 1 : 0 ); -#ifdef DEBUG - printf("\n"); -#endif - - callParamCallbacks(); - - return comStatus_; -} - -asynStatus -SmarActMCSAxis::moveCmd(const char *fmt, ...) -{ -int val, ax; -char rep[REP_LEN]; -size_t got; -double tout = DEFLT_TIMEOUT; -va_list ap; - - va_start(ap, fmt); - comStatus_ = c_p_->sendCmd(&got, rep, sizeof(rep), tout, fmt, ap); - va_end(ap); - - if ( comStatus_ ) - goto bail; - - if ( c_p_->parseReply(rep, &ax, &val) ) { - comStatus_ = asynError; - goto bail; - } - -bail: -#ifdef DEBUG - printf("\n"); -#endif - - return comStatus_; -} - -asynStatus -SmarActMCSAxis::setSpeed(double velocity) -{ -long vel; -asynStatus status; - - if ( (vel = (long)rint(fabs(velocity))) != vel_ ) { - /* change speed */ - if ( asynSuccess == (status = moveCmd(":SCLS%u,%ld", channel_, vel)) ) { - vel_ = vel; - } - return status; - } - return asynSuccess; -} - -asynStatus -SmarActMCSAxis::move(double position, int relative, double min_vel, double max_vel, double accel) -{ -const char *fmt_rot = relative ? ":MAR%u,%ld,%d,%d" : ":MAA%u,%ld,%d,%d"; -const char *fmt_lin = relative ? ":MPR%u,%ld,%d" : ":MPA%u,%ld,%d"; -const char *fmt; -double rpos; -long angle; -int rev; - - if ( isRot_ ) { - fmt = fmt_rot; - } else { - fmt = fmt_lin; - } - -#ifdef DEBUG - printf("Move to %f (speed %f - %f)\n", position, min_vel, max_vel); -#endif - - if ( (comStatus_ = setSpeed(max_vel)) ) - goto bail; - - /* cache 'closed-loop' setting until next move */ - holdTime_ = getClosedLoop() ? HOLD_FOREVER : 0; - - rpos = rint(position); - - if ( isRot_ ) { - angle = (long)rpos % UDEG_PER_REV; - rev = (int)(rpos / UDEG_PER_REV); - if (angle < 0) { - angle += UDEG_PER_REV; - rev -= 1; - } - comStatus_ = moveCmd(fmt, channel_, angle, rev, holdTime_); - } else { - comStatus_ = moveCmd(fmt, channel_, (long)rpos, holdTime_); - } - -bail: - if ( comStatus_ ) { - setIntegerParam(c_p_->motorStatusProblem_, 1); - setIntegerParam(c_p_->motorStatusCommsError_, 1); - callParamCallbacks(); - } - return comStatus_; -} - -asynStatus -SmarActMCSAxis::home(double min_vel, double max_vel, double accel, int forwards) -{ - -#ifdef DEBUG - printf("Home %u\n", forwards); -#endif - - if ( (comStatus_ = setSpeed(max_vel)) ) - goto bail; - - /* cache 'closed-loop' setting until next move */ - holdTime_ = getClosedLoop() ? HOLD_FOREVER : 0; - - comStatus_ = moveCmd(":FRM%u,%u,%d,%d", channel_, forwards ? 0 : 1, holdTime_, isRot_ ? 1 : 0); - -bail: - if ( comStatus_ ) { - setIntegerParam(c_p_->motorStatusProblem_, 1); - setIntegerParam(c_p_->motorStatusCommsError_, 1); - callParamCallbacks(); - } - return comStatus_; -} - -asynStatus -SmarActMCSAxis::stop(double acceleration) -{ -#ifdef DEBUG - printf("Stop\n"); -#endif - comStatus_ = moveCmd(":S%u", channel_); - - if ( comStatus_ ) { - setIntegerParam(c_p_->motorStatusProblem_, 1); - setIntegerParam(c_p_->motorStatusCommsError_, 1); - callParamCallbacks(); - } - return comStatus_; -} - -asynStatus -SmarActMCSAxis::setPosition(double position) -{ -double rpos; - - rpos = rint(position); - - if ( isRot_ ) { - // For rotation stages the revolution will always be set to zero - // Only set position if it is between zero an 360 degrees - if (rpos >= 0.0 && rpos < (double)UDEG_PER_REV) { - comStatus_ = moveCmd(":SP%u,%d", channel_, (long)rpos); - } else { - comStatus_ = asynError; - } - } else { - comStatus_ = moveCmd(":SP%u,%d", channel_, (long)rpos); - } - - if ( comStatus_ ) { - setIntegerParam(c_p_->motorStatusProblem_, 1); - setIntegerParam(c_p_->motorStatusCommsError_, 1); - callParamCallbacks(); - } - return comStatus_; -} - -asynStatus -SmarActMCSAxis::moveVelocity(double min_vel, double max_vel, double accel) -{ -long speed = (long)rint(fabs(max_vel)); -long tgt_pos = FAR_AWAY; - - /* No MCS command we an use directly. Just use a 'relative move' to - * very far target. - */ - -#ifdef DEBUG - printf("moveVelocity (%f - %f)\n", min_vel, max_vel); -#endif - - if ( 0 == speed ) { - /* Here we are in a dilemma. If we set the MCS' speed to zero - * then it will move at unlimited speed which is so fast that - * 'JOG' makes no sense. - * Just 'STOP' the motion - hope that works... - */ - setIntegerParam(c_p_->motorStop_, 1); - callParamCallbacks(); - return asynSuccess; - } - - if ( max_vel < 0 ) { - tgt_pos = -tgt_pos; - } - - if ( (comStatus_ = setSpeed(max_vel)) ) - goto bail; - - comStatus_ = moveCmd(":MPR%u,%ld,0", channel_, tgt_pos); - -bail: - if ( comStatus_ ) { - setIntegerParam(c_p_->motorStatusProblem_, 1); - setIntegerParam(c_p_->motorStatusCommsError_, 1); - callParamCallbacks(); - } - return comStatus_; -} - -/* iocsh wrapping and registration business (stolen from ACRMotorDriver.cpp) */ -static const iocshArg cc_a0 = {"Port name [string]", iocshArgString}; -static const iocshArg cc_a1 = {"I/O port name [string]", iocshArgString}; -static const iocshArg cc_a2 = {"Number of axes [int]", iocshArgInt}; -static const iocshArg cc_a3 = {"Moving poll period (s) [double]", iocshArgDouble}; -static const iocshArg cc_a4 = {"Idle poll period (s) [double]", iocshArgDouble}; - -static const iocshArg * const cc_as[] = {&cc_a0, &cc_a1, &cc_a2, &cc_a3, &cc_a4}; - -static const iocshFuncDef cc_def = {"smarActMCSCreateController", sizeof(cc_as)/sizeof(cc_as[0]), cc_as}; - -extern "C" void * -smarActMCSCreateController( - const char *motorPortName, - const char *ioPortName, - int numAxes, - double movingPollPeriod, - double idlePollPeriod) -{ -void *rval = 0; - // the asyn stuff doesn't seem to be prepared for exceptions. I get segfaults - // if constructing a controller (or axis) incurs an exception even if its - // caught (IMHO asyn should behave as if the controller/axis never existed...) -#ifdef ASYN_CANDO_EXCEPTIONS - try { -#endif - rval = new SmarActMCSController(motorPortName, ioPortName, numAxes, movingPollPeriod, idlePollPeriod); -#ifdef ASYN_CANDO_EXCEPTIONS - } catch (SmarActMCSException &e) { - epicsPrintf("smarActMCSCreateController failed (exception caught):\n%s\n", e.what()); - rval = 0; - } -#endif - - return rval; -} - -static void cc_fn(const iocshArgBuf *args) -{ - smarActMCSCreateController( - args[0].sval, - args[1].sval, - args[2].ival, - args[3].dval, - args[4].dval); -} - - -static const iocshArg ca_a0 = {"Controller Port name [string]", iocshArgString}; -static const iocshArg ca_a1 = {"Axis number [int]", iocshArgInt}; -static const iocshArg ca_a2 = {"Channel [int]", iocshArgInt}; - -static const iocshArg * const ca_as[] = {&ca_a0, &ca_a1, &ca_a2}; - -/* iocsh wrapping and registration business (stolen from ACRMotorDriver.cpp) */ -/* smarActMCSCreateAxis called to create each axis of the smarActMCS controller*/ -static const iocshFuncDef ca_def = {"smarActMCSCreateAxis", 3, ca_as}; - -extern "C" void * -smarActMCSCreateAxis( - const char *controllerPortName, - int axisNumber, - int channel) -{ -void *rval = 0; - -SmarActMCSController *pC; -SmarActMCSAxis *pAxis; -asynMotorAxis *pAsynAxis; - - // the asyn stuff doesn't seem to be prepared for exceptions. I get segfaults - // if constructing a controller (or axis) incurs an exception even if its - // caught (IMHO asyn should behave as if the controller/axis never existed...) -#ifdef ASYN_CANDO_EXCEPTIONS - try { -#endif -// rval = new SmarActMCSAxis(, axisNumber, channel); - pC = (SmarActMCSController*) findAsynPortDriver(controllerPortName); - if (!pC) { - printf("smarActMCSCreateAxis: Error port %s not found\n", controllerPortName); - rval = 0; - return rval; - } - // check if axis number already exists - pAsynAxis = pC->getAxis(axisNumber); - if (pAsynAxis != NULL) { // axis already exists - epicsPrintf("SmarActMCSCreateAxis failed:axis %u already exists\n", axisNumber); -#ifdef ASYN_CANDO_EXCEPTIONS - THROW_(SmarActMCSException(MCSCommunicationError, "axis %u already exists", axisNumber)); -#endif - rval = 0; - return rval; - } - pC->lock(); - pAxis = new SmarActMCSAxis(pC, axisNumber, channel); - pAxis = NULL; - pC->unlock(); - -#ifdef ASYN_CANDO_EXCEPTIONS - } catch (SmarActMCSException &e) { - epicsPrintf("SmarActMCSAxis failed (exception caught):\n%s\n", e.what()); - rval = 0; - } -#endif - - return rval; -} - -static void ca_fn(const iocshArgBuf *args) -{ - smarActMCSCreateAxis( - args[0].sval, - args[1].ival, - args[2].ival); -} - -static void smarActMCSMotorRegister(void) -{ - iocshRegister(&cc_def, cc_fn); // smarActMCSCreateController - iocshRegister(&ca_def, ca_fn); // smarActMCSCreateAxis -} - -extern "C" { -epicsExportRegistrar(smarActMCSMotorRegister); -} diff --git a/motorApp/SmarActMCSSrc/smarActMCSMotorDriver.h b/motorApp/SmarActMCSSrc/smarActMCSMotorDriver.h deleted file mode 100644 index 910d671e..00000000 --- a/motorApp/SmarActMCSSrc/smarActMCSMotorDriver.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef SMARACT_MCS_MOTOR_DRIVER_H -#define SMARACT_MCS_MOTOR_DRIVER_H - -/* Motor driver support for smarAct MCS RS-232 Controller */ - -/* Derived from ACRMotorDriver.cpp by Mark Rivers, 2011/3/28 */ - -/* Author: Till Straumann , 9/11 */ - -#ifdef __cplusplus - -#include -#include -#include -#include - -enum SmarActMCSExceptionType { - MCSUnknownError, - MCSConnectionError, - MCSCommunicationError, -}; - -class SmarActMCSException : public std::exception { -public: - SmarActMCSException(SmarActMCSExceptionType t, const char *fmt, ...); - SmarActMCSException(SmarActMCSExceptionType t) - : t_(t) - { str_[0] = 0; } - SmarActMCSException() - : t_(MCSUnknownError) - { str_[0] = 0; } - SmarActMCSException(SmarActMCSExceptionType t, const char *fmt, va_list ap); - SmarActMCSExceptionType getType() - const { return t_; } - virtual const char *what() - const throw() {return str_ ;} -protected: - char str_[100]; - SmarActMCSExceptionType t_; -}; - - -class SmarActMCSAxis : public asynMotorAxis -{ -public: - SmarActMCSAxis(class SmarActMCSController *cnt_p, int axis, int channel); - asynStatus poll(bool *moving_p); - asynStatus move(double position, int relative, double min_vel, double max_vel, double accel); - asynStatus home(double min_vel, double max_vel, double accel, int forwards); - asynStatus stop(double acceleration); - asynStatus setPosition(double position); - asynStatus moveVelocity(double min_vel, double max_vel, double accel); - - virtual asynStatus getVal(const char *parm, int *val_p); - virtual asynStatus getAngle(int *val_p, int *rev_p); - virtual asynStatus moveCmd(const char *cmd, ...); - virtual int getClosedLoop(); - - int getVel() const { return vel_; } - -protected: - asynStatus setSpeed(double velocity); - -private: - SmarActMCSController *c_p_; // pointer to asynMotorController for this axis - asynStatus comStatus_; - int vel_; - unsigned holdTime_; - int channel_; - int sensorType_; - int isRot_; - -friend class SmarActMCSController; -}; - -class SmarActMCSController : public asynMotorController -{ -public: - SmarActMCSController(const char *portName, const char *IOPortName, int numAxes, double movingPollPeriod, double idlePollPeriod); - virtual asynStatus sendCmd(size_t *got_p, char *rep, int len, double timeout, const char *fmt, va_list ap); - virtual asynStatus sendCmd(size_t *got_p, char *rep, int len, double timeout, const char *fmt, ...); - virtual asynStatus sendCmd(size_t *got_p, char *rep, int len, const char *fmt, ...); - virtual asynStatus sendCmd(char *rep, int len, const char *fmt, ...); - - static int parseReply(const char *reply, int *ax_p, int *val_p); - static int parseAngle(const char *reply, int *ax_p, int *val_p, int *rot_p); - -protected: - SmarActMCSAxis **pAxes_; - -private: - asynUser *asynUserMot_p_; -friend class SmarActMCSAxis; -}; - -#endif // _cplusplus -#endif // SMARACT_MCS_MOTOR_DRIVER_H