Compare commits
26 Commits
Author | SHA1 | Date | |
---|---|---|---|
eca513f3a0 | |||
26175290bf | |||
e316fcf67b | |||
6cf00adb60 | |||
9710d442b8 | |||
8dd1dc4af2 | |||
a758db1211 | |||
a11d10cb6c | |||
ba353c4e5d | |||
55b523ddaa | |||
75292a6a9c | |||
53bbe2aae8 | |||
1597dc34e0 | |||
dde7066f40 | |||
b4d6447b32 | |||
2f83060ec1 | |||
a3e3a79788 | |||
2c5fdc7d0a | |||
7bf31ac256 | |||
47e72d65a9 | |||
5298b5ef69 | |||
29f23216ad | |||
26bc3df876 | |||
87d3cbb3eb | |||
66552d5ffc | |||
253f65b25b |
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[submodule "sinqmotor"]
|
||||||
|
path = sinqmotor
|
||||||
|
url = https://gitea.psi.ch/lin-epics-modules/sinqmotor
|
||||||
|
[submodule "sinqMotor"]
|
||||||
|
path = sinqMotor
|
||||||
|
url = https://gitea.psi.ch/lin-epics-modules/sinqMotor
|
12
Makefile
12
Makefile
@ -1,4 +1,4 @@
|
|||||||
# Use the PSI build system
|
# Include the external Makefile
|
||||||
include /ioc/tools/driver.makefile
|
include /ioc/tools/driver.makefile
|
||||||
|
|
||||||
MODULE=turboPmac
|
MODULE=turboPmac
|
||||||
@ -8,28 +8,30 @@ ARCH_FILTER=RHEL%
|
|||||||
|
|
||||||
# Additional module dependencies
|
# Additional module dependencies
|
||||||
REQUIRED+=motorBase
|
REQUIRED+=motorBase
|
||||||
REQUIRED+=sinqMotor
|
|
||||||
|
|
||||||
# Specify the version of motorBase we want to build against
|
# Specify the version of motorBase we want to build against
|
||||||
motorBase_VERSION=7.2.2
|
motorBase_VERSION=7.2.2
|
||||||
|
|
||||||
# Specify the version of sinqMotor we want to build against
|
|
||||||
sinqMotor_VERSION=mathis_s
|
|
||||||
|
|
||||||
# These headers allow to depend on this library for derived drivers.
|
# These headers allow to depend on this library for derived drivers.
|
||||||
HEADERS += src/pmacAsynIPPort.h
|
HEADERS += src/pmacAsynIPPort.h
|
||||||
HEADERS += src/turboPmacAxis.h
|
HEADERS += src/turboPmacAxis.h
|
||||||
HEADERS += src/turboPmacController.h
|
HEADERS += src/turboPmacController.h
|
||||||
|
|
||||||
# Source files to build
|
# Source files to build
|
||||||
|
SOURCES += sinqMotor/src/msgPrintControl.cpp
|
||||||
|
SOURCES += sinqMotor/src/sinqAxis.cpp
|
||||||
|
SOURCES += sinqMotor/src/sinqController.cpp
|
||||||
SOURCES += src/pmacAsynIPPort.c
|
SOURCES += src/pmacAsynIPPort.c
|
||||||
SOURCES += src/turboPmacAxis.cpp
|
SOURCES += src/turboPmacAxis.cpp
|
||||||
SOURCES += src/turboPmacController.cpp
|
SOURCES += src/turboPmacController.cpp
|
||||||
|
|
||||||
# Store the record files
|
# Store the record files
|
||||||
|
TEMPLATES += sinqMotor/db/asynRecord.db
|
||||||
|
TEMPLATES += sinqMotor/db/sinqMotor.db
|
||||||
TEMPLATES += db/turboPmac.db
|
TEMPLATES += db/turboPmac.db
|
||||||
|
|
||||||
# This file registers the motor-specific functions in the IOC shell.
|
# This file registers the motor-specific functions in the IOC shell.
|
||||||
|
DBDS += sinqMotor/src/sinqMotor.dbd
|
||||||
DBDS += src/turboPmac.dbd
|
DBDS += src/turboPmac.dbd
|
||||||
|
|
||||||
USR_CFLAGS += -Wall -Wextra -Weffc++ -Wunused-result -Werror # -Wpedantic // Does not work because EPICS macros trigger warnings
|
USR_CFLAGS += -Wall -Wextra -Weffc++ -Wunused-result -Werror # -Wpedantic // Does not work because EPICS macros trigger warnings
|
10
README.md
10
README.md
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
This is a driver for the Turbo PMAC motion controller with the SINQ communication protocol. It is based on the sinqMotor shared library (https://git.psi.ch/sinq-epics-modules/sinqmotor). The header files contain detailed documentation for all public functions. The headers themselves are exported when building the library to allow other drivers to depend on this one.
|
This is a driver for the Turbo PMAC motion controller with the SINQ communication protocol. It is based on the sinqMotor shared library (https://gitea.psi.ch/lin-epics-modules/sinqMotor). The header files contain detailed documentation for all public functions. The headers themselves are exported when building the library to allow other drivers to depend on this one.
|
||||||
|
|
||||||
## User guide
|
## User guide
|
||||||
|
|
||||||
@ -14,8 +14,6 @@ The folder "utils" contains utility scripts for working with pmac motor controll
|
|||||||
- writeRead.py: Allows sending commands to and receiving commands from a pmac controller over an ethernet connection.
|
- writeRead.py: Allows sending commands to and receiving commands from a pmac controller over an ethernet connection.
|
||||||
- analyzeTcpDump.py: Parse the TCP communication between an IOC and a MCU and format it into a dictionary. "demo.py" shows how this data can be easily visualized for analysis.
|
- analyzeTcpDump.py: Parse the TCP communication between an IOC and a MCU and format it into a dictionary. "demo.py" shows how this data can be easily visualized for analysis.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### IOC startup script
|
### IOC startup script
|
||||||
|
|
||||||
turboPmac exports the following IOC shell functions:
|
turboPmac exports the following IOC shell functions:
|
||||||
@ -54,11 +52,11 @@ setMaxSubsequentTimeouts("$(DRIVER_PORT)", 20);
|
|||||||
setThresholdComTimeout("$(DRIVER_PORT)", 300, 10);
|
setThresholdComTimeout("$(DRIVER_PORT)", 300, 10);
|
||||||
|
|
||||||
# Parametrize the EPICS record database with the substitution file named after the MCU.
|
# Parametrize the EPICS record database with the substitution file named after the MCU.
|
||||||
epicsEnvSet("SINQDBPATH","$(sinqMotor_DB)/sinqMotor.db")
|
epicsEnvSet("SINQDBPATH","$(turboPmac_DB)/sinqMotor.db")
|
||||||
dbLoadTemplate("$(TOP)/$(DRIVER_PORT).substitutions", "INSTR=$(INSTR)$(DRIVER_PORT):,CONTROLLER=$(DRIVER_PORT)")
|
dbLoadTemplate("$(TOP)/$(DRIVER_PORT).substitutions", "INSTR=$(INSTR)$(DRIVER_PORT):,CONTROLLER=$(DRIVER_PORT)")
|
||||||
epicsEnvSet("SINQDBPATH","$(turboPmac_DB)/turboPmac.db")
|
epicsEnvSet("SINQDBPATH","$(turboPmac_DB)/turboPmac.db")
|
||||||
dbLoadTemplate("$(TOP)/$(DRIVER_PORT).substitutions", "INSTR=$(INSTR)$(DRIVER_PORT):,CONTROLLER=$(DRIVER_PORT)")
|
dbLoadTemplate("$(TOP)/$(DRIVER_PORT).substitutions", "INSTR=$(INSTR)$(DRIVER_PORT):,CONTROLLER=$(DRIVER_PORT)")
|
||||||
dbLoadRecords("$(sinqMotor_DB)/asynRecord.db","P=$(INSTR)$(DRIVER_PORT),PORT=$(IP_PORT)")
|
dbLoadRecords("$(turboPmac_DB)/asynRecord.db","P=$(INSTR)$(DRIVER_PORT),PORT=$(IP_PORT)")
|
||||||
```
|
```
|
||||||
|
|
||||||
### Additional records
|
### Additional records
|
||||||
@ -73,4 +71,4 @@ Please see the documentation for the module sinqMotor: https://git.psi.ch/sinq-e
|
|||||||
|
|
||||||
### How to build it
|
### How to build it
|
||||||
|
|
||||||
Please see the documentation for the module sinqMotor: https://git.psi.ch/sinq-epics-modules/sinqmotor/-/blob/main/README.md.
|
This driver can be compiled and installed by running `make install` from the same directory where the Makefile is located. However, since it uses the git submodule sinqMotor, make sure that the correct version of the submodule repository is checked out AND the change is commited (`git status` shows no non-committed changes). Please see the section "Usage as static dependency" in https://git.psi.ch/sinq-epics-modules/sinqmotor/-/blob/main/README.md for more details.
|
||||||
|
@ -31,3 +31,14 @@ record(longout, "$(INSTR)FlushHardware") {
|
|||||||
field(PINI, "NO")
|
field(PINI, "NO")
|
||||||
field(VAL, "1")
|
field(VAL, "1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# If this PV is set to 1 (default), the position limits are read out from the
|
||||||
|
# controller. Otherwise, the limits given in the substitution file (DHLM and
|
||||||
|
# DLLM) are used.
|
||||||
|
# This record is coupled to the parameter library via limFromHardware -> LIM_FROM_HARDWARE.
|
||||||
|
record(longout, "$(INSTR)$(M):LimFromHardware") {
|
||||||
|
field(DTYP, "asynInt32")
|
||||||
|
field(OUT, "@asyn($(CONTROLLER),$(AXIS),1) LIM_FROM_HARDWARE")
|
||||||
|
field(PINI, "YES")
|
||||||
|
field(VAL, "$(LIMFROMHARDWARE=1)")
|
||||||
|
}
|
1
sinqMotor
Submodule
1
sinqMotor
Submodule
Submodule sinqMotor added at bdefc6090d
@ -13,6 +13,14 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
struct turboPmacAxisImpl {
|
||||||
|
bool waitForHandshake;
|
||||||
|
time_t timeAtHandshake;
|
||||||
|
// The axis status is used when enabling / disabling the motor
|
||||||
|
int axisStatus;
|
||||||
|
bool needInit;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Contains all instances of turboPmacAxis which have been created and is used in
|
Contains all instances of turboPmacAxis which have been created and is used in
|
||||||
the initialization hook function.
|
the initialization hook function.
|
||||||
@ -54,10 +62,11 @@ turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo,
|
|||||||
axes.push_back(this);
|
axes.push_back(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize all member variables
|
pTurboPmacA_ = std::make_unique<turboPmacAxisImpl>(
|
||||||
waitForHandshake_ = false;
|
(turboPmacAxisImpl){.waitForHandshake = false,
|
||||||
timeAtHandshake_ = 0;
|
.timeAtHandshake = 0,
|
||||||
axisStatus_ = 0;
|
.axisStatus = 0,
|
||||||
|
.needInit = false});
|
||||||
|
|
||||||
// Provide initial values for some parameter library entries
|
// Provide initial values for some parameter library entries
|
||||||
status = pC_->setIntegerParam(axisNo_, pC_->rereadEncoderPosition(), 0);
|
status = pC_->setIntegerParam(axisNo_, pC_->rereadEncoderPosition(), 0);
|
||||||
@ -71,6 +80,20 @@ turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo,
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Even though this happens already in sinqAxis, a default value for
|
||||||
|
// motorMessageText is set here again, because apparently the sinqAxis
|
||||||
|
// constructor is not run before the string is accessed?
|
||||||
|
status = setStringParam(pC_->motorMessageText(), "");
|
||||||
|
if (status != asynSuccess) {
|
||||||
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
|
"Controller \"%s\", axis %d => %s, line %d:\nFATAL ERROR "
|
||||||
|
"(setting a parameter value failed "
|
||||||
|
"with %s)\n. Terminating IOC",
|
||||||
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
pC_->stringifyAsynStatus(status));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
// turboPmac motors can always be disabled
|
// turboPmac motors can always be disabled
|
||||||
status = pC_->setIntegerParam(axisNo_, pC_->motorCanDisable(), 1);
|
status = pC_->setIntegerParam(axisNo_, pC_->motorCanDisable(), 1);
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
@ -79,8 +102,8 @@ turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Default values for the watchdog timeout mechanism
|
// Default values for the watchdog timeout mechanism
|
||||||
offsetMovTimeout_ = 30; // seconds
|
setOffsetMovTimeout(30.0); // seconds
|
||||||
scaleMovTimeout_ = 2.0;
|
setScaleMovTimeout(2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
turboPmacAxis::~turboPmacAxis(void) {
|
turboPmacAxis::~turboPmacAxis(void) {
|
||||||
@ -144,15 +167,15 @@ asynStatus turboPmacAxis::init() {
|
|||||||
"with controller during IOC initialization. Check if you used "
|
"with controller during IOC initialization. Check if you used "
|
||||||
"\"pmacAsynIPPortConfigure\" instead of the standard "
|
"\"pmacAsynIPPortConfigure\" instead of the standard "
|
||||||
"\"drvAsynIPPortConfigure\" function in the .cmd file in order to "
|
"\"drvAsynIPPortConfigure\" function in the .cmd file in order to "
|
||||||
"create the port driver.\nTerminating IOC.\n",
|
"create the port driver.\n",
|
||||||
pC_->portName, axisNo(), __PRETTY_FUNCTION__, __LINE__);
|
pC_->portName, axisNo(), __PRETTY_FUNCTION__, __LINE__);
|
||||||
exit(-1);
|
pTurboPmacA_->needInit = true;
|
||||||
}
|
}
|
||||||
nvals = sscanf(response, "%d %lf %lf %lf %lf %d", &axStatus, &motorPos,
|
nvals = sscanf(response, "%d %lf %lf %lf %lf %d", &axStatus, &motorPos,
|
||||||
&motorVmax, &motorVelocity, &motorAccel, &acoDelay);
|
&motorVmax, &motorVelocity, &motorAccel, &acoDelay);
|
||||||
|
|
||||||
// The acoDelay is given in milliseconds -> Convert to seconds, rounded up
|
// The acoDelay is given in milliseconds -> Convert to seconds, rounded up
|
||||||
offsetMovTimeout_ = std::ceil(acoDelay / 1000.0);
|
setOffsetMovTimeout(std::ceil(acoDelay / 1000.0));
|
||||||
|
|
||||||
// The PMAC electronic specifies the acceleration in m/s^2. Since we
|
// The PMAC electronic specifies the acceleration in m/s^2. Since we
|
||||||
// otherwise work with the base length mm, the acceleration is converted
|
// otherwise work with the base length mm, the acceleration is converted
|
||||||
@ -201,7 +224,12 @@ asynStatus turboPmacAxis::init() {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->readEncoderType();
|
status = this->readEncoderType();
|
||||||
|
if (status == asynSuccess) {
|
||||||
|
pTurboPmacA_->needInit = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform the actual poll
|
// Perform the actual poll
|
||||||
@ -237,13 +265,20 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
|
if (pTurboPmacA_->needInit) {
|
||||||
|
rw_status = init();
|
||||||
|
if (rw_status != asynSuccess) {
|
||||||
|
return rw_status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Are we currently waiting for a handshake?
|
// Are we currently waiting for a handshake?
|
||||||
if (waitForHandshake_) {
|
if (pTurboPmacA_->waitForHandshake) {
|
||||||
|
|
||||||
// Check if the handshake takes too long and communicate an error in
|
// Check if the handshake takes too long and communicate an error in
|
||||||
// this case. A handshake should not take more than 5 seconds.
|
// this case. A handshake should not take more than 5 seconds.
|
||||||
time_t currentTime = time(NULL);
|
time_t currentTime = time(NULL);
|
||||||
bool timedOut = (currentTime > timeAtHandshake_ + 5);
|
bool timedOut = (currentTime > pTurboPmacA_->timeAtHandshake + 5);
|
||||||
|
|
||||||
if (pC_->getMsgPrintControl().shouldBePrinted(
|
if (pC_->getMsgPrintControl().shouldBePrinted(
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, timedOut,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, timedOut,
|
||||||
@ -253,7 +288,7 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
"handshake at %ld s and didn't get a positive reply yet "
|
"handshake at %ld s and didn't get a positive reply yet "
|
||||||
"(current time is %ld s).\n",
|
"(current time is %ld s).\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
timeAtHandshake_, currentTime);
|
pTurboPmacA_->timeAtHandshake, currentTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timedOut) {
|
if (timedOut) {
|
||||||
@ -265,6 +300,7 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
axisNo_, __PRETTY_FUNCTION__,
|
axisNo_, __PRETTY_FUNCTION__,
|
||||||
__LINE__);
|
__LINE__);
|
||||||
}
|
}
|
||||||
|
pTurboPmacA_->waitForHandshake = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(command, sizeof(command), "P%2.2d23 P%2.2d01", axisNo_,
|
snprintf(command, sizeof(command), "P%2.2d23 P%2.2d01", axisNo_,
|
||||||
@ -284,11 +320,11 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
// If an error occurred while waiting for the handshake, abort the
|
// If an error occurred while waiting for the handshake, abort the
|
||||||
// waiting procedure and continue with the poll in order to handle
|
// waiting procedure and continue with the poll in order to handle
|
||||||
// the error.
|
// the error.
|
||||||
waitForHandshake_ = false;
|
pTurboPmacA_->waitForHandshake = false;
|
||||||
} else if (handshakePerformed == 1) {
|
} else if (handshakePerformed == 1) {
|
||||||
// Handshake has been performed successfully -> Continue with the
|
// Handshake has been performed successfully -> Continue with the
|
||||||
// poll
|
// poll
|
||||||
waitForHandshake_ = false;
|
pTurboPmacA_->waitForHandshake = false;
|
||||||
} else {
|
} else {
|
||||||
// Still waiting for the handshake - try again in the next busy
|
// Still waiting for the handshake - try again in the next busy
|
||||||
// poll. This is already part of the movement procedure.
|
// poll. This is already part of the movement procedure.
|
||||||
@ -372,7 +408,7 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
lowLimit = lowLimit + limitsOffset;
|
lowLimit = lowLimit + limitsOffset;
|
||||||
|
|
||||||
// Store the axis status
|
// Store the axis status
|
||||||
axisStatus_ = axStatus;
|
pTurboPmacA_->axisStatus = axStatus;
|
||||||
|
|
||||||
// Update the enablement PV
|
// Update the enablement PV
|
||||||
pl_status = setIntegerParam(pC_->motorEnableRBV(),
|
pl_status = setIntegerParam(pC_->motorEnableRBV(),
|
||||||
@ -397,13 +433,6 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
case -5:
|
case -5:
|
||||||
// Axis is deactivated
|
// Axis is deactivated
|
||||||
*moving = false;
|
*moving = false;
|
||||||
|
|
||||||
pl_status = setStringParam(pC_->motorMessageText(), "Deactivated");
|
|
||||||
if (pl_status != asynSuccess) {
|
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
|
||||||
axisNo_, __PRETTY_FUNCTION__,
|
|
||||||
__LINE__);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case -4:
|
case -4:
|
||||||
// Emergency stop
|
// Emergency stop
|
||||||
@ -426,19 +455,10 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
axisNo_, __PRETTY_FUNCTION__,
|
axisNo_, __PRETTY_FUNCTION__,
|
||||||
__LINE__);
|
__LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case -3:
|
case -3:
|
||||||
// Disabled
|
// Disabled
|
||||||
*moving = false;
|
*moving = false;
|
||||||
|
|
||||||
pl_status = setStringParam(pC_->motorMessageText(), "Disabled");
|
|
||||||
if (pl_status != asynSuccess) {
|
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
|
||||||
axisNo_, __PRETTY_FUNCTION__,
|
|
||||||
__LINE__);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
// Idle
|
// Idle
|
||||||
@ -461,13 +481,53 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
*moving = true;
|
*moving = true;
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
|
// Motor is moving normally
|
||||||
|
*moving = true;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
// Jog start
|
||||||
|
*moving = true;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
// Jog forward
|
||||||
|
*moving = true;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
// Jog backward
|
||||||
|
*moving = true;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
// Jog break
|
||||||
|
*moving = true;
|
||||||
|
break;
|
||||||
|
case 10:
|
||||||
|
// Jog step forward
|
||||||
|
*moving = true;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
// Jog step backward
|
||||||
|
*moving = true;
|
||||||
|
break;
|
||||||
|
case 12:
|
||||||
|
// Jog stop
|
||||||
|
*moving = true;
|
||||||
|
break;
|
||||||
|
case 13:
|
||||||
|
// Backlash
|
||||||
|
*moving = true;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
// Move order out of range - this is also handled as an error
|
||||||
|
*moving = false;
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
// Move is interrupted, but the motor is not ready to receive another
|
||||||
|
// move command. Therefore it is treated as still moving.
|
||||||
|
*moving = true;
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
// Move is resumed
|
||||||
*moving = true;
|
*moving = true;
|
||||||
|
|
||||||
asynPrint(
|
|
||||||
pC_->pasynUser(), ASYN_TRACE_FLOW,
|
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is moving\n",
|
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
*moving = false;
|
*moving = false;
|
||||||
@ -549,19 +609,30 @@ asynStatus turboPmacAxis::doPoll(bool *moving) {
|
|||||||
__LINE__);
|
__LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
pl_status = pC_->setDoubleParam(axisNo_, pC_->motorHighLimitFromDriver(),
|
int limFromHardware = 0;
|
||||||
highLimit);
|
pl_status =
|
||||||
|
pC_->getIntegerParam(axisNo_, pC_->limFromHardware(), &limFromHardware);
|
||||||
if (pl_status != asynSuccess) {
|
if (pl_status != asynSuccess) {
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorHighLimitFromDriver_",
|
return pC_->paramLibAccessFailed(pl_status, "limFromHardware", axisNo_,
|
||||||
axisNo_, __PRETTY_FUNCTION__,
|
__PRETTY_FUNCTION__, __LINE__);
|
||||||
__LINE__);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pl_status =
|
if (limFromHardware != 0) {
|
||||||
pC_->setDoubleParam(axisNo_, pC_->motorLowLimitFromDriver(), lowLimit);
|
pl_status = pC_->setDoubleParam(
|
||||||
if (pl_status != asynSuccess) {
|
axisNo_, pC_->motorHighLimitFromDriver(), highLimit);
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorLowLimit_", axisNo_,
|
if (pl_status != asynSuccess) {
|
||||||
__PRETTY_FUNCTION__, __LINE__);
|
return pC_->paramLibAccessFailed(
|
||||||
|
pl_status, "motorHighLimitFromDriver_", axisNo_,
|
||||||
|
__PRETTY_FUNCTION__, __LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
|
pl_status = pC_->setDoubleParam(axisNo_, pC_->motorLowLimitFromDriver(),
|
||||||
|
lowLimit);
|
||||||
|
if (pl_status != asynSuccess) {
|
||||||
|
return pC_->paramLibAccessFailed(pl_status, "motorLowLimit_",
|
||||||
|
axisNo_, __PRETTY_FUNCTION__,
|
||||||
|
__LINE__);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pl_status = setMotorPosition(currentPosition);
|
pl_status = setMotorPosition(currentPosition);
|
||||||
@ -599,8 +670,7 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
|||||||
resetError = false;
|
resetError = false;
|
||||||
|
|
||||||
status = setStringParam(pC_->motorMessageText(),
|
status = setStringParam(pC_->motorMessageText(),
|
||||||
"Target position would exceed software "
|
"Target position would exceed software limits");
|
||||||
"limits. Please call the support.");
|
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
||||||
axisNo_, __PRETTY_FUNCTION__,
|
axisNo_, __PRETTY_FUNCTION__,
|
||||||
@ -783,10 +853,10 @@ asynStatus turboPmacAxis::handleError(int error, char *userMessage,
|
|||||||
}
|
}
|
||||||
resetError = false;
|
resetError = false;
|
||||||
|
|
||||||
snprintf(userMessage, sizeUserMessage,
|
snprintf(
|
||||||
"Driver hardware error (P%2.2d01 = 13). "
|
userMessage, sizeUserMessage,
|
||||||
"Please call the support.",
|
"Driver hardware error (P%2.2d01 = 13). Please call the support.",
|
||||||
axisNo_);
|
axisNo_);
|
||||||
status = setStringParam(pC_->motorMessageText(), userMessage);
|
status = setStringParam(pC_->motorMessageText(), userMessage);
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
return pC_->paramLibAccessFailed(status, "motorMessageText_",
|
||||||
@ -965,8 +1035,8 @@ asynStatus turboPmacAxis::doMove(double position, int relative,
|
|||||||
|
|
||||||
// In the next poll, we will check if the handshake has been performed in a
|
// In the next poll, we will check if the handshake has been performed in a
|
||||||
// reasonable time
|
// reasonable time
|
||||||
waitForHandshake_ = true;
|
pTurboPmacA_->waitForHandshake = true;
|
||||||
timeAtHandshake_ = time(NULL);
|
pTurboPmacA_->timeAtHandshake = time(NULL);
|
||||||
|
|
||||||
// Waiting for a handshake is already part of the movement procedure =>
|
// Waiting for a handshake is already part of the movement procedure =>
|
||||||
// Start the watchdog
|
// Start the watchdog
|
||||||
@ -1008,6 +1078,10 @@ asynStatus turboPmacAxis::stop(double acceleration) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the driver to idle state and move out of the handshake wait loop,
|
||||||
|
// if we're currently inside it.
|
||||||
|
pTurboPmacA_->waitForHandshake = false;
|
||||||
|
|
||||||
return rw_status;
|
return rw_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1042,6 +1116,10 @@ asynStatus turboPmacAxis::doReset() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the driver to idle state and move out of the handshake wait loop,
|
||||||
|
// if we're currently inside it.
|
||||||
|
pTurboPmacA_->waitForHandshake = false;
|
||||||
|
|
||||||
return rw_status;
|
return rw_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1084,22 +1162,7 @@ asynStatus turboPmacAxis::doHome(double min_velocity, double max_velocity,
|
|||||||
axisNo_, __PRETTY_FUNCTION__,
|
axisNo_, __PRETTY_FUNCTION__,
|
||||||
__LINE__);
|
__LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
pl_status = setStringParam(pC_->motorMessageText(), "Homing");
|
|
||||||
if (pl_status != asynSuccess) {
|
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
|
||||||
axisNo_, __PRETTY_FUNCTION__,
|
|
||||||
__LINE__);
|
|
||||||
}
|
|
||||||
return callParamCallbacks();
|
return callParamCallbacks();
|
||||||
} else {
|
|
||||||
pl_status = setStringParam(pC_->motorMessageText(),
|
|
||||||
"Can't home a motor with absolute encoder");
|
|
||||||
if (pl_status != asynSuccess) {
|
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
|
||||||
axisNo_, __PRETTY_FUNCTION__,
|
|
||||||
__LINE__);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return asynSuccess;
|
return asynSuccess;
|
||||||
@ -1271,6 +1334,8 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
// Status of parameter library operations
|
// Status of parameter library operations
|
||||||
asynStatus pl_status = asynSuccess;
|
asynStatus pl_status = asynSuccess;
|
||||||
|
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Continue regardless of the status returned by the poll; we just want to
|
Continue regardless of the status returned by the poll; we just want to
|
||||||
find out whether the motor is currently moving or not. If the poll
|
find out whether the motor is currently moving or not. If the poll
|
||||||
@ -1280,14 +1345,15 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
bool moving = false;
|
bool moving = false;
|
||||||
doPoll(&moving);
|
doPoll(&moving);
|
||||||
|
|
||||||
// =========================================================================
|
|
||||||
|
|
||||||
// If the axis is currently moving, it cannot be disabled. Ignore the
|
// If the axis is currently moving, it cannot be disabled. Ignore the
|
||||||
// command and inform the user. We check the last known status of the axis
|
// command and inform the user. We check the last known status of the axis
|
||||||
// instead of "moving", since status -6 is also moving, but the motor can
|
// instead of "moving", since status -6 is also moving, but the motor can
|
||||||
// actually be disabled in this state!
|
// actually be disabled in this state!
|
||||||
if (axisStatus_ == 1 || axisStatus_ == 2 || axisStatus_ == 3 ||
|
int axStatus = pTurboPmacA_->axisStatus;
|
||||||
axisStatus_ == 4 || axisStatus_ == 5) {
|
if (axStatus == 1 || axStatus == 2 || axStatus == 3 || axStatus == 4 ||
|
||||||
|
axStatus == 5 || axStatus == 6 || axStatus == 7 || axStatus == 8 ||
|
||||||
|
axStatus == 9 || axStatus == 10 || axStatus == 11 || axStatus == 12 ||
|
||||||
|
axStatus == 13 || axStatus == 15 || axStatus == 16) {
|
||||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is not "
|
"Controller \"%s\", axis %d => %s, line %d\nAxis is not "
|
||||||
"idle and can therefore not be enabled / disabled.\n",
|
"idle and can therefore not be enabled / disabled.\n",
|
||||||
@ -1307,7 +1373,7 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
|
|
||||||
// Axis is already enabled / disabled and a new enable / disable command
|
// Axis is already enabled / disabled and a new enable / disable command
|
||||||
// was sent => Do nothing
|
// was sent => Do nothing
|
||||||
if ((axisStatus_ != -3) == on) {
|
if ((axStatus != -3) == on) {
|
||||||
asynPrint(
|
asynPrint(
|
||||||
pC_->pasynUser(), ASYN_TRACE_WARNING,
|
pC_->pasynUser(), ASYN_TRACE_WARNING,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nAxis is already %s.\n",
|
"Controller \"%s\", axis %d => %s, line %d\nAxis is already %s.\n",
|
||||||
@ -1330,16 +1396,7 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
"Controller \"%s\", axis %d => %s, line %d\n%s axis\n",
|
"Controller \"%s\", axis %d => %s, line %d\n%s axis\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
on ? "Enable" : "Disable");
|
on ? "Enable" : "Disable");
|
||||||
if (on == 0) {
|
|
||||||
pl_status = setStringParam(pC_->motorMessageText(), "Disabling ...");
|
|
||||||
} else {
|
|
||||||
pl_status = setStringParam(pC_->motorMessageText(), "Enabling ...");
|
|
||||||
}
|
|
||||||
if (pl_status != asynSuccess) {
|
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
|
||||||
axisNo_, __PRETTY_FUNCTION__,
|
|
||||||
__LINE__);
|
|
||||||
}
|
|
||||||
rw_status = pC_->writeRead(axisNo_, command, response, 0);
|
rw_status = pC_->writeRead(axisNo_, command, response, 0);
|
||||||
if (rw_status != asynSuccess) {
|
if (rw_status != asynSuccess) {
|
||||||
return rw_status;
|
return rw_status;
|
||||||
@ -1357,13 +1414,13 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
if (rw_status != asynSuccess) {
|
if (rw_status != asynSuccess) {
|
||||||
return rw_status;
|
return rw_status;
|
||||||
}
|
}
|
||||||
nvals = sscanf(response, "%d", &axisStatus_);
|
nvals = sscanf(response, "%d", &pTurboPmacA_->axisStatus);
|
||||||
if (nvals != 1) {
|
if (nvals != 1) {
|
||||||
return pC_->couldNotParseResponse(command, response, axisNo_,
|
return pC_->couldNotParseResponse(command, response, axisNo_,
|
||||||
__PRETTY_FUNCTION__, __LINE__);
|
__PRETTY_FUNCTION__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((axisStatus_ != -3) == on) {
|
if ((pTurboPmacA_->axisStatus != -3) == on) {
|
||||||
bool moving = false;
|
bool moving = false;
|
||||||
// Perform a poll to update the parameter library
|
// Perform a poll to update the parameter library
|
||||||
poll(&moving);
|
poll(&moving);
|
||||||
@ -1373,7 +1430,7 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
|
|
||||||
// Failed to change axis status within timeout_enable_disable => Send a
|
// Failed to change axis status within timeout_enable_disable => Send a
|
||||||
// corresponding message
|
// corresponding message
|
||||||
asynPrint(pC_->pasynUser(), ASYN_TRACE_FLOW,
|
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nFailed to %s axis "
|
"Controller \"%s\", axis %d => %s, line %d\nFailed to %s axis "
|
||||||
"within %d seconds\n",
|
"within %d seconds\n",
|
||||||
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
|
||||||
@ -1382,7 +1439,7 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
// Output message to user
|
// Output message to user
|
||||||
snprintf(command, sizeof(command), "Failed to %s within %d seconds",
|
snprintf(command, sizeof(command), "Failed to %s within %d seconds",
|
||||||
on ? "enable" : "disable", timeout_enable_disable);
|
on ? "enable" : "disable", timeout_enable_disable);
|
||||||
pl_status = setStringParam(pC_->motorMessageText(), "Enabling ...");
|
pl_status = setStringParam(pC_->motorMessageText(), command);
|
||||||
if (pl_status != asynSuccess) {
|
if (pl_status != asynSuccess) {
|
||||||
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
return pC_->paramLibAccessFailed(pl_status, "motorMessageText_",
|
||||||
axisNo_, __PRETTY_FUNCTION__,
|
axisNo_, __PRETTY_FUNCTION__,
|
||||||
@ -1391,6 +1448,17 @@ asynStatus turboPmacAxis::enable(bool on) {
|
|||||||
return asynError;
|
return asynError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool turboPmacAxis::needInit() { return pTurboPmacA_->needInit; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Instruct the axis to run its init() function during the next poll
|
||||||
|
*
|
||||||
|
* @param needInit
|
||||||
|
*/
|
||||||
|
void turboPmacAxis::setNeedInit(bool needInit) {
|
||||||
|
pTurboPmacA_->needInit = needInit;
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************************/
|
/*************************************************************************************/
|
||||||
/** The following functions are C-wrappers, and can be called directly from
|
/** The following functions are C-wrappers, and can be called directly from
|
||||||
* iocsh */
|
* iocsh */
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
#ifndef turboPmacAXIS_H
|
#ifndef turboPmacAXIS_H
|
||||||
#define turboPmacAXIS_H
|
#define turboPmacAXIS_H
|
||||||
#include "sinqAxis.h"
|
#include "sinqAxis.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct turboPmacAxisImpl;
|
||||||
|
|
||||||
// Forward declaration of the controller class to resolve the cyclic dependency
|
// Forward declaration of the controller class to resolve the cyclic dependency
|
||||||
// between the controller and the axis .h-file. See
|
// between the controller and the axis .h-file. See
|
||||||
@ -31,7 +34,7 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
* value is currently not used.
|
* value is currently not used.
|
||||||
* @return asynStatus
|
* @return asynStatus
|
||||||
*/
|
*/
|
||||||
asynStatus stop(double acceleration);
|
virtual asynStatus stop(double acceleration);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implementation of the `doHome` function from sinqAxis. The
|
* @brief Implementation of the `doHome` function from sinqAxis. The
|
||||||
@ -43,8 +46,8 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
* @param forwards
|
* @param forwards
|
||||||
* @return asynStatus
|
* @return asynStatus
|
||||||
*/
|
*/
|
||||||
asynStatus doHome(double minVelocity, double maxVelocity,
|
virtual asynStatus doHome(double minVelocity, double maxVelocity,
|
||||||
double acceleration, int forwards);
|
double acceleration, int forwards);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implementation of the `doPoll` function from sinqAxis. The
|
* @brief Implementation of the `doPoll` function from sinqAxis. The
|
||||||
@ -53,7 +56,7 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
* @param moving
|
* @param moving
|
||||||
* @return asynStatus
|
* @return asynStatus
|
||||||
*/
|
*/
|
||||||
asynStatus doPoll(bool *moving);
|
virtual asynStatus doPoll(bool *moving);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implementation of the `doMove` function from sinqAxis. The
|
* @brief Implementation of the `doMove` function from sinqAxis. The
|
||||||
@ -66,8 +69,9 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
* @param acceleration
|
* @param acceleration
|
||||||
* @return asynStatus
|
* @return asynStatus
|
||||||
*/
|
*/
|
||||||
asynStatus doMove(double position, int relative, double min_velocity,
|
virtual asynStatus doMove(double position, int relative,
|
||||||
double max_velocity, double acceleration);
|
double min_velocity, double max_velocity,
|
||||||
|
double acceleration);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Readout of some values from the controller at IOC startup
|
* @brief Readout of some values from the controller at IOC startup
|
||||||
@ -79,7 +83,7 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
*
|
*
|
||||||
* @return asynStatus
|
* @return asynStatus
|
||||||
*/
|
*/
|
||||||
asynStatus init();
|
virtual asynStatus init();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Implementation of the `doReset` function from sinqAxis.
|
* @brief Implementation of the `doReset` function from sinqAxis.
|
||||||
@ -87,7 +91,7 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
* @param on
|
* @param on
|
||||||
* @return asynStatus
|
* @return asynStatus
|
||||||
*/
|
*/
|
||||||
asynStatus doReset();
|
virtual asynStatus doReset();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enable / disable the axis.
|
* @brief Enable / disable the axis.
|
||||||
@ -95,7 +99,7 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
* @param on
|
* @param on
|
||||||
* @return asynStatus
|
* @return asynStatus
|
||||||
*/
|
*/
|
||||||
asynStatus enable(bool on);
|
virtual asynStatus enable(bool on);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read the encoder type (incremental or absolute) for this axis from
|
* @brief Read the encoder type (incremental or absolute) for this axis from
|
||||||
@ -103,14 +107,14 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
*
|
*
|
||||||
* @return asynStatus
|
* @return asynStatus
|
||||||
*/
|
*/
|
||||||
asynStatus readEncoderType();
|
virtual asynStatus readEncoderType();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Trigger a rereading of the encoder position.
|
* @brief Trigger a rereading of the encoder position.
|
||||||
*
|
*
|
||||||
* @return asynStatus
|
* @return asynStatus
|
||||||
*/
|
*/
|
||||||
asynStatus rereadEncoder();
|
virtual asynStatus rereadEncoder();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Interpret the error code and populate the user message accordingly
|
* @brief Interpret the error code and populate the user message accordingly
|
||||||
@ -122,14 +126,24 @@ class turboPmacAxis : public sinqAxis {
|
|||||||
*/
|
*/
|
||||||
asynStatus handleError(int error, char *userMessage, int sizeUserMessage);
|
asynStatus handleError(int error, char *userMessage, int sizeUserMessage);
|
||||||
|
|
||||||
protected:
|
/**
|
||||||
|
* @brief Check if the axis needs to run its initialization function
|
||||||
|
*
|
||||||
|
* @return true
|
||||||
|
* @return false
|
||||||
|
*/
|
||||||
|
bool needInit();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Instruct the axis to run its init() function during the next poll
|
||||||
|
*
|
||||||
|
* @param needInit
|
||||||
|
*/
|
||||||
|
void setNeedInit(bool needInit);
|
||||||
|
|
||||||
|
private:
|
||||||
turboPmacController *pC_;
|
turboPmacController *pC_;
|
||||||
|
std::unique_ptr<turboPmacAxisImpl> pTurboPmacA_;
|
||||||
bool waitForHandshake_;
|
|
||||||
time_t timeAtHandshake_;
|
|
||||||
|
|
||||||
// The axis status is used when enabling / disabling the motor
|
|
||||||
int axisStatus_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,6 +31,24 @@ void adjustResponseForPrint(char *dst, const char *src, size_t buf_length) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct turboPmacControllerImpl {
|
||||||
|
|
||||||
|
// Timeout for the communication process in seconds
|
||||||
|
double comTimeout;
|
||||||
|
|
||||||
|
char lastResponse[sinqController::MAXBUF_];
|
||||||
|
|
||||||
|
// User for writing int32 values to the port driver.
|
||||||
|
asynUser *pasynInt32SyncIOipPort;
|
||||||
|
|
||||||
|
// Indices of additional PVs
|
||||||
|
int rereadEncoderPosition;
|
||||||
|
int readConfig;
|
||||||
|
int flushHardware;
|
||||||
|
int limFromHardware;
|
||||||
|
};
|
||||||
|
#define NUM_turboPmac_DRIVER_PARAMS 3
|
||||||
|
|
||||||
turboPmacController::turboPmacController(const char *portName,
|
turboPmacController::turboPmacController(const char *portName,
|
||||||
const char *ipPortConfigName,
|
const char *ipPortConfigName,
|
||||||
int numAxes, double movingPollPeriod,
|
int numAxes, double movingPollPeriod,
|
||||||
@ -47,21 +65,25 @@ turboPmacController::turboPmacController(const char *portName,
|
|||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// The paramLib indices are populated with the calls to createParam
|
||||||
|
pTurboPmacC_ =
|
||||||
|
std::make_unique<turboPmacControllerImpl>((turboPmacControllerImpl){
|
||||||
|
.comTimeout = comTimeout,
|
||||||
|
.lastResponse = {0},
|
||||||
|
});
|
||||||
|
|
||||||
// Initialization of local variables
|
// Initialization of local variables
|
||||||
asynStatus status = asynSuccess;
|
asynStatus status = asynSuccess;
|
||||||
|
|
||||||
// Initialization of all member variables
|
|
||||||
comTimeout_ = comTimeout;
|
|
||||||
|
|
||||||
// Maximum allowed number of subsequent timeouts before the user is
|
// Maximum allowed number of subsequent timeouts before the user is
|
||||||
// informed.
|
// informed.
|
||||||
maxSubsequentTimeouts_ = 10;
|
setMaxSubsequentTimeouts(10);
|
||||||
|
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
// Create additional parameter library entries
|
// Create additional parameter library entries
|
||||||
|
|
||||||
status = createParam("REREAD_ENCODER_POSITION", asynParamInt32,
|
status = createParam("REREAD_ENCODER_POSITION", asynParamInt32,
|
||||||
&rereadEncoderPosition_);
|
&pTurboPmacC_->rereadEncoderPosition);
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
|
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
|
||||||
@ -71,7 +93,8 @@ turboPmacController::turboPmacController(const char *portName,
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = createParam("READ_CONFIG", asynParamInt32, &readConfig_);
|
status =
|
||||||
|
createParam("READ_CONFIG", asynParamInt32, &pTurboPmacC_->readConfig);
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
|
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
|
||||||
@ -81,7 +104,19 @@ turboPmacController::turboPmacController(const char *portName,
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = createParam("FLUSH_HARDWARE", asynParamInt32, &flushHardware_);
|
status = createParam("FLUSH_HARDWARE", asynParamInt32,
|
||||||
|
&pTurboPmacC_->flushHardware);
|
||||||
|
if (status != asynSuccess) {
|
||||||
|
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
|
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
|
||||||
|
"parameter failed with %s).\nTerminating IOC",
|
||||||
|
portName, __PRETTY_FUNCTION__, __LINE__,
|
||||||
|
stringifyAsynStatus(status));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
status = createParam("LIM_FROM_HARDWARE", asynParamInt32,
|
||||||
|
&pTurboPmacC_->limFromHardware);
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
|
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
|
||||||
@ -100,7 +135,7 @@ turboPmacController::turboPmacController(const char *portName,
|
|||||||
const char *message_from_device =
|
const char *message_from_device =
|
||||||
"\006"; // Hex-code for ACK (acknowledge) -> Each message from the MCU
|
"\006"; // Hex-code for ACK (acknowledge) -> Each message from the MCU
|
||||||
// is terminated by this value
|
// is terminated by this value
|
||||||
status = pasynOctetSyncIO->setInputEos(pasynOctetSyncIOipPort_,
|
status = pasynOctetSyncIO->setInputEos(pasynOctetSyncIOipPort(),
|
||||||
message_from_device,
|
message_from_device,
|
||||||
strlen(message_from_device));
|
strlen(message_from_device));
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
@ -109,7 +144,7 @@ turboPmacController::turboPmacController(const char *portName,
|
|||||||
"(setting input EOS failed with %s).\nTerminating IOC",
|
"(setting input EOS failed with %s).\nTerminating IOC",
|
||||||
portName, __PRETTY_FUNCTION__, __LINE__,
|
portName, __PRETTY_FUNCTION__, __LINE__,
|
||||||
stringifyAsynStatus(status));
|
stringifyAsynStatus(status));
|
||||||
pasynOctetSyncIO->disconnect(pasynOctetSyncIOipPort_);
|
pasynOctetSyncIO->disconnect(pasynOctetSyncIOipPort());
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +156,7 @@ turboPmacController::turboPmacController(const char *portName,
|
|||||||
"with %s).\nTerminating IOC",
|
"with %s).\nTerminating IOC",
|
||||||
portName, __PRETTY_FUNCTION__, __LINE__,
|
portName, __PRETTY_FUNCTION__, __LINE__,
|
||||||
stringifyAsynStatus(status));
|
stringifyAsynStatus(status));
|
||||||
pasynOctetSyncIO->disconnect(pasynOctetSyncIOipPort_);
|
pasynOctetSyncIO->disconnect(pasynOctetSyncIOipPort());
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,13 +166,15 @@ turboPmacController::turboPmacController(const char *portName,
|
|||||||
We try to connect to the port via the port name provided by the constructor.
|
We try to connect to the port via the port name provided by the constructor.
|
||||||
If this fails, the function is terminated via exit.
|
If this fails, the function is terminated via exit.
|
||||||
*/
|
*/
|
||||||
pasynInt32SyncIO->connect(ipPortConfigName, 0, &pasynInt32SyncIOipPort_,
|
pasynInt32SyncIO->connect(ipPortConfigName, 0,
|
||||||
NULL);
|
&pTurboPmacC_->pasynInt32SyncIOipPort, NULL);
|
||||||
if (status != asynSuccess || pasynInt32SyncIOipPort_ == nullptr) {
|
if (status != asynSuccess ||
|
||||||
|
pTurboPmacC_->pasynInt32SyncIOipPort == nullptr) {
|
||||||
errlogPrintf("Controller \"%s\" => %s, line %d:\nFATAL ERROR (cannot "
|
errlogPrintf("Controller \"%s\" => %s, line %d:\nFATAL ERROR (cannot "
|
||||||
"connect to MCU controller).\n"
|
"connect to MCU controller).\n"
|
||||||
"Terminating IOC",
|
"Terminating IOC",
|
||||||
portName, __PRETTY_FUNCTION__, __LINE__);
|
portName, __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
pasynOctetSyncIO->disconnect(pasynOctetSyncIOipPort());
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,20 +252,20 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
*/
|
*/
|
||||||
status = pasynOctetSyncIO->writeRead(
|
status = pasynOctetSyncIO->writeRead(
|
||||||
pasynOctetSyncIOipPort(), command, commandLength, response, MAXBUF_,
|
pasynOctetSyncIOipPort(), command, commandLength, response, MAXBUF_,
|
||||||
comTimeout_, &nbytesOut, &nbytesIn, &eomReason);
|
pTurboPmacC_->comTimeout, &nbytesOut, &nbytesIn, &eomReason);
|
||||||
|
|
||||||
msgPrintControlKey comKey =
|
msgPrintControlKey comKey =
|
||||||
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||||
|
|
||||||
if (status == asynTimeout) {
|
if (status == asynTimeout) {
|
||||||
|
|
||||||
if (msgPrintControl_.shouldBePrinted(comKey, true, pasynUser())) {
|
if (getMsgPrintControl().shouldBePrinted(comKey, true, pasynUser())) {
|
||||||
asynPrint(
|
asynPrint(
|
||||||
this->pasynUser(), ASYN_TRACE_ERROR,
|
this->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nTimeout while "
|
"Controller \"%s\", axis %d => %s, line %d\nTimeout while "
|
||||||
"writing to the controller. Retrying ...%s\n",
|
"writing to the controller. Retrying ...%s\n",
|
||||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
||||||
msgPrintControl_.getSuffix());
|
getMsgPrintControl().getSuffix());
|
||||||
}
|
}
|
||||||
|
|
||||||
timeoutStatus = checkComTimeoutWatchdog(axisNo, drvMessageText,
|
timeoutStatus = checkComTimeoutWatchdog(axisNo, drvMessageText,
|
||||||
@ -239,13 +276,14 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
checkMaxSubsequentTimeouts(timeoutCounter, axis);
|
checkMaxSubsequentTimeouts(timeoutCounter, axis);
|
||||||
timeoutCounter += 1;
|
timeoutCounter += 1;
|
||||||
|
|
||||||
if (maxSubsequentTimeoutsExceeded_) {
|
if (maxSubsequentTimeoutsExceeded()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = pasynOctetSyncIO->writeRead(
|
status = pasynOctetSyncIO->writeRead(
|
||||||
pasynOctetSyncIOipPort(), command, commandLength, response,
|
pasynOctetSyncIOipPort(), command, commandLength, response,
|
||||||
MAXBUF_, comTimeout_, &nbytesOut, &nbytesIn, &eomReason);
|
MAXBUF_, pTurboPmacC_->comTimeout, &nbytesOut, &nbytesIn,
|
||||||
|
&eomReason);
|
||||||
if (status != asynTimeout) {
|
if (status != asynTimeout) {
|
||||||
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\", axis %d => %s, line "
|
"Controller \"%s\", axis %d => %s, line "
|
||||||
@ -255,16 +293,28 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (status != asynSuccess) {
|
} else if (status != asynSuccess) {
|
||||||
if (msgPrintControl_.shouldBePrinted(comKey, true, pasynUser())) {
|
if (getMsgPrintControl().shouldBePrinted(comKey, true, pasynUser())) {
|
||||||
asynPrint(
|
asynPrint(
|
||||||
this->pasynUser(), ASYN_TRACE_ERROR,
|
this->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nError %s while "
|
"Controller \"%s\", axis %d => %s, line %d\nError %s while "
|
||||||
"writing to the controller.%s\n",
|
"writing to the controller.%s\n",
|
||||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
||||||
stringifyAsynStatus(status), msgPrintControl_.getSuffix());
|
stringifyAsynStatus(status), getMsgPrintControl().getSuffix());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
msgPrintControl_.resetCount(comKey, pasynUser());
|
getMsgPrintControl().resetCount(comKey, pasynUser());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != asynSuccess) {
|
||||||
|
/*
|
||||||
|
Since the communication failed, there is the possibility that the
|
||||||
|
controller is not connected at all to the network. In that case, we
|
||||||
|
cannot be sure that the information read out in the init method of the
|
||||||
|
axis is still up-to-date the next time we get a connection. Therefore,
|
||||||
|
an info flag is set which the axis object can use at the start of its
|
||||||
|
poll method to try to initialize itself.
|
||||||
|
*/
|
||||||
|
axis->setNeedInit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timeoutStatus == asynError) {
|
if (timeoutStatus == asynError) {
|
||||||
@ -301,16 +351,17 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
"string detected\"). Please call the support.",
|
"string detected\"). Please call the support.",
|
||||||
reasonStringified);
|
reasonStringified);
|
||||||
|
|
||||||
if (msgPrintControl_.shouldBePrinted(terminateKey, true, pasynUser())) {
|
if (getMsgPrintControl().shouldBePrinted(terminateKey, true,
|
||||||
|
pasynUser())) {
|
||||||
|
|
||||||
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nMessage "
|
"Controller \"%s\", axis %d => %s, line %d\nMessage "
|
||||||
"terminated due to reason %s.%s\n",
|
"terminated due to reason %s.%s\n",
|
||||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
||||||
reasonStringified, msgPrintControl_.getSuffix());
|
reasonStringified, getMsgPrintControl().getSuffix());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
msgPrintControl_.resetCount(terminateKey, pasynUser());
|
getMsgPrintControl().resetCount(terminateKey, pasynUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -327,15 +378,15 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
if (numExpectedResponses != numReceivedResponses) {
|
if (numExpectedResponses != numReceivedResponses) {
|
||||||
adjustResponseForPrint(modResponse, response, MAXBUF_);
|
adjustResponseForPrint(modResponse, response, MAXBUF_);
|
||||||
|
|
||||||
if (msgPrintControl_.shouldBePrinted(numResponsesKey, true,
|
if (getMsgPrintControl().shouldBePrinted(numResponsesKey, true,
|
||||||
pasynUser())) {
|
pasynUser())) {
|
||||||
asynPrint(
|
asynPrint(
|
||||||
this->pasynUser(), ASYN_TRACE_ERROR,
|
this->pasynUser(), ASYN_TRACE_ERROR,
|
||||||
"Controller \"%s\", axis %d => %s, line %d\nUnexpected "
|
"Controller \"%s\", axis %d => %s, line %d\nUnexpected "
|
||||||
"response '%s' (carriage returns are replaced with spaces) "
|
"response '%s' (carriage returns are replaced with spaces) "
|
||||||
"for command %s.%s\n",
|
"for command %s.%s\n",
|
||||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, modResponse,
|
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, modResponse,
|
||||||
command, msgPrintControl_.getSuffix());
|
command, getMsgPrintControl().getSuffix());
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(drvMessageText, sizeof(drvMessageText),
|
snprintf(drvMessageText, sizeof(drvMessageText),
|
||||||
@ -345,7 +396,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
modResponse, command);
|
modResponse, command);
|
||||||
status = asynError;
|
status = asynError;
|
||||||
} else {
|
} else {
|
||||||
msgPrintControl_.resetCount(numResponsesKey, pasynUser());
|
getMsgPrintControl().resetCount(numResponsesKey, pasynUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create custom error messages for different failure modes, if no error
|
// Create custom error messages for different failure modes, if no error
|
||||||
@ -384,15 +435,15 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
paramLibStatus =
|
paramLibStatus =
|
||||||
getIntegerParam(axisNo, motorStatusProblem_, &motorStatusProblem);
|
getIntegerParam(axisNo, motorStatusProblem_, &motorStatusProblem);
|
||||||
if (paramLibStatus != asynSuccess) {
|
if (paramLibStatus != asynSuccess) {
|
||||||
return paramLibAccessFailed(paramLibStatus, "motorStatusProblem_",
|
return paramLibAccessFailed(paramLibStatus, "motorStatusProblem",
|
||||||
axisNo, __PRETTY_FUNCTION__, __LINE__);
|
axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (motorStatusProblem == 0) {
|
if (motorStatusProblem == 0) {
|
||||||
paramLibStatus =
|
paramLibStatus =
|
||||||
axis->setStringParam(motorMessageText_, drvMessageText);
|
axis->setStringParam(motorMessageText(), drvMessageText);
|
||||||
if (paramLibStatus != asynSuccess) {
|
if (paramLibStatus != asynSuccess) {
|
||||||
return paramLibAccessFailed(paramLibStatus, "motorMessageText_",
|
return paramLibAccessFailed(paramLibStatus, "motorMessageText",
|
||||||
axisNo, __PRETTY_FUNCTION__,
|
axisNo, __PRETTY_FUNCTION__,
|
||||||
__LINE__);
|
__LINE__);
|
||||||
}
|
}
|
||||||
@ -407,7 +458,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
|||||||
paramLibStatus = axis->setIntegerParam(motorStatusProblem_, 1);
|
paramLibStatus = axis->setIntegerParam(motorStatusProblem_, 1);
|
||||||
if (paramLibStatus != asynSuccess) {
|
if (paramLibStatus != asynSuccess) {
|
||||||
return paramLibAccessFailed(paramLibStatus,
|
return paramLibAccessFailed(paramLibStatus,
|
||||||
"motorStatusCommsError_", axisNo,
|
"motorStatusCommsError", axisNo,
|
||||||
__PRETTY_FUNCTION__, __LINE__);
|
__PRETTY_FUNCTION__, __LINE__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -421,13 +472,13 @@ asynStatus turboPmacController::doFlushHardware() {
|
|||||||
constant defined in pmacAsynIPPort.c. This reason is then used within
|
constant defined in pmacAsynIPPort.c. This reason is then used within
|
||||||
the write method of pasynInt32SyncIO to select the flush function.
|
the write method of pasynInt32SyncIO to select the flush function.
|
||||||
*/
|
*/
|
||||||
int temp = pasynInt32SyncIOipPort_->reason;
|
int temp = pTurboPmacC_->pasynInt32SyncIOipPort->reason;
|
||||||
pasynInt32SyncIOipPort_->reason = FLUSH_HARDWARE;
|
pTurboPmacC_->pasynInt32SyncIOipPort->reason = FLUSH_HARDWARE;
|
||||||
asynStatus status = (asynStatus)pasynInt32SyncIO->write(
|
asynStatus status = (asynStatus)pasynInt32SyncIO->write(
|
||||||
pasynInt32SyncIOipPort_, 1, comTimeout_);
|
pTurboPmacC_->pasynInt32SyncIOipPort, 1, pTurboPmacC_->comTimeout);
|
||||||
|
|
||||||
// Reset the status afterwards
|
// Reset the status afterwards
|
||||||
pasynInt32SyncIOipPort_->reason = temp;
|
pTurboPmacC_->pasynInt32SyncIOipPort->reason = temp;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,11 +491,11 @@ asynStatus turboPmacController::writeInt32(asynUser *pasynUser,
|
|||||||
turboPmacAxis *axis = getTurboPmacAxis(pasynUser);
|
turboPmacAxis *axis = getTurboPmacAxis(pasynUser);
|
||||||
|
|
||||||
// Handle custom PVs
|
// Handle custom PVs
|
||||||
if (function == rereadEncoderPosition_) {
|
if (function == rereadEncoderPosition()) {
|
||||||
return axis->rereadEncoder();
|
return axis->rereadEncoder();
|
||||||
} else if (function == readConfig_) {
|
} else if (function == readConfig()) {
|
||||||
return axis->init();
|
return axis->init();
|
||||||
} else if (function == flushHardware_) {
|
} else if (function == flushHardware()) {
|
||||||
return doFlushHardware();
|
return doFlushHardware();
|
||||||
} else {
|
} else {
|
||||||
return sinqController::writeInt32(pasynUser, value);
|
return sinqController::writeInt32(pasynUser, value);
|
||||||
@ -462,6 +513,19 @@ asynStatus turboPmacController::couldNotParseResponse(const char *command,
|
|||||||
command, modifiedResponse, axisNo, functionName, lineNumber);
|
command, modifiedResponse, axisNo, functionName, lineNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int turboPmacController::rereadEncoderPosition() {
|
||||||
|
return pTurboPmacC_->rereadEncoderPosition;
|
||||||
|
}
|
||||||
|
int turboPmacController::readConfig() { return pTurboPmacC_->readConfig; }
|
||||||
|
int turboPmacController::flushHardware() { return pTurboPmacC_->flushHardware; }
|
||||||
|
int turboPmacController::limFromHardware() {
|
||||||
|
return pTurboPmacC_->limFromHardware;
|
||||||
|
}
|
||||||
|
|
||||||
|
asynUser *turboPmacController::pasynInt32SyncIOipPort() {
|
||||||
|
return pTurboPmacC_->pasynInt32SyncIOipPort;
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************************/
|
/*************************************************************************************/
|
||||||
/** The following functions are C-wrappers, and can be called directly from
|
/** The following functions are C-wrappers, and can be called directly from
|
||||||
* iocsh */
|
* iocsh */
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
#include "sinqAxis.h"
|
#include "sinqAxis.h"
|
||||||
#include "sinqController.h"
|
#include "sinqController.h"
|
||||||
#include "turboPmacAxis.h"
|
#include "turboPmacAxis.h"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
struct turboPmacControllerImpl;
|
||||||
|
|
||||||
class turboPmacController : public sinqController {
|
class turboPmacController : public sinqController {
|
||||||
public:
|
public:
|
||||||
@ -116,36 +119,17 @@ class turboPmacController : public sinqController {
|
|||||||
asynStatus doFlushHardware();
|
asynStatus doFlushHardware();
|
||||||
|
|
||||||
// Accessors for additional PVs
|
// Accessors for additional PVs
|
||||||
int rereadEncoderPosition() { return rereadEncoderPosition_; }
|
int rereadEncoderPosition();
|
||||||
int readConfig() { return readConfig_; }
|
int readConfig();
|
||||||
int flushHardware() { return flushHardware_; }
|
int flushHardware();
|
||||||
|
int limFromHardware();
|
||||||
|
|
||||||
// Set the maximum buffer size. This is an empirical value which must be
|
asynUser *pasynInt32SyncIOipPort();
|
||||||
// large enough to avoid overflows for all commands to the device /
|
|
||||||
// responses from it.
|
|
||||||
static const uint32_t MAXBUF_ = 200;
|
|
||||||
|
|
||||||
asynUser *pasynInt32SyncIOipPort() { return pasynInt32SyncIOipPort_; }
|
private:
|
||||||
|
std::unique_ptr<turboPmacControllerImpl> pTurboPmacC_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/*
|
|
||||||
Timeout for the communication process in seconds
|
|
||||||
*/
|
|
||||||
double comTimeout_;
|
|
||||||
|
|
||||||
char lastResponse[MAXBUF_];
|
|
||||||
|
|
||||||
// User for writing int32 values to the port driver.
|
|
||||||
asynUser *pasynInt32SyncIOipPort_;
|
|
||||||
|
|
||||||
// Indices of additional PVs
|
|
||||||
#define FIRST_turboPmac_PARAM rereadEncoderPosition_
|
|
||||||
int rereadEncoderPosition_;
|
|
||||||
int readConfig_;
|
|
||||||
int flushHardware_;
|
|
||||||
#define LAST_turboPmac_PARAM flushHardware_
|
|
||||||
};
|
};
|
||||||
#define NUM_turboPmac_DRIVER_PARAMS \
|
|
||||||
(&LAST_turboPmac_PARAM - &FIRST_turboPmac_PARAM + 1)
|
|
||||||
|
|
||||||
#endif /* turboPmacController_H */
|
#endif /* turboPmacController_H */
|
||||||
|
Reference in New Issue
Block a user