Compare commits
31 Commits
Author | SHA1 | Date | |
---|---|---|---|
1703542770 | |||
c7d1dc4930 | |||
6fd3848f13 | |||
56f08f3c76 | |||
168bfae983 | |||
0e29750d13 | |||
ba5b921aca | |||
1b810fb353 | |||
4bc3388bc6 | |||
c759156058 | |||
eca513f3a0 | |||
26175290bf | |||
e316fcf67b | |||
6cf00adb60 | |||
9710d442b8 | |||
8dd1dc4af2 | |||
a758db1211 | |||
a11d10cb6c | |||
ba353c4e5d | |||
55b523ddaa | |||
75292a6a9c | |||
53bbe2aae8 | |||
1597dc34e0 | |||
dde7066f40 | |||
b4d6447b32 | |||
2f83060ec1 | |||
a3e3a79788 | |||
2c5fdc7d0a | |||
7bf31ac256 | |||
63a5fcd518 | |||
47e72d65a9 |
@ -4,7 +4,7 @@
|
||||
|
||||
## 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
|
||||
|
||||
@ -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.
|
||||
- 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
|
||||
|
||||
turboPmac exports the following IOC shell functions:
|
||||
@ -54,11 +52,11 @@ setMaxSubsequentTimeouts("$(DRIVER_PORT)", 20);
|
||||
setThresholdComTimeout("$(DRIVER_PORT)", 300, 10);
|
||||
|
||||
# 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)")
|
||||
epicsEnvSet("SINQDBPATH","$(turboPmac_DB)/turboPmac.db")
|
||||
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
|
||||
|
@ -31,3 +31,14 @@ record(longout, "$(INSTR)FlushHardware") {
|
||||
field(PINI, "NO")
|
||||
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)")
|
||||
}
|
Submodule sinqMotor updated: 5689402375...41dfd1de5a
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,10 @@
|
||||
#ifndef turboPmacAXIS_H
|
||||
#define turboPmacAXIS_H
|
||||
#include "sinqAxis.h"
|
||||
#include "sinqController.h"
|
||||
#include "turboPmacController.h"
|
||||
#include <memory>
|
||||
|
||||
// Forward declaration of the controller class to resolve the cyclic dependency
|
||||
// between the controller and the axis .h-file. See
|
||||
// https://en.cppreference.com/w/cpp/language/class.
|
||||
class turboPmacController;
|
||||
struct turboPmacAxisImpl;
|
||||
|
||||
class turboPmacAxis : public sinqAxis {
|
||||
public:
|
||||
@ -21,6 +20,7 @@ class turboPmacAxis : public sinqAxis {
|
||||
/**
|
||||
* @brief Destroy the turboPmacAxis
|
||||
*
|
||||
* This destructor is necessary in order to use the PIMPL idiom.
|
||||
*/
|
||||
virtual ~turboPmacAxis();
|
||||
|
||||
@ -31,7 +31,7 @@ class turboPmacAxis : public sinqAxis {
|
||||
* value is currently not used.
|
||||
* @return asynStatus
|
||||
*/
|
||||
asynStatus stop(double acceleration);
|
||||
virtual asynStatus stop(double acceleration);
|
||||
|
||||
/**
|
||||
* @brief Implementation of the `doHome` function from sinqAxis. The
|
||||
@ -43,8 +43,8 @@ class turboPmacAxis : public sinqAxis {
|
||||
* @param forwards
|
||||
* @return asynStatus
|
||||
*/
|
||||
asynStatus doHome(double minVelocity, double maxVelocity,
|
||||
double acceleration, int forwards);
|
||||
virtual asynStatus doHome(double minVelocity, double maxVelocity,
|
||||
double acceleration, int forwards);
|
||||
|
||||
/**
|
||||
* @brief Implementation of the `doPoll` function from sinqAxis. The
|
||||
@ -53,7 +53,7 @@ class turboPmacAxis : public sinqAxis {
|
||||
* @param moving
|
||||
* @return asynStatus
|
||||
*/
|
||||
asynStatus doPoll(bool *moving);
|
||||
virtual asynStatus doPoll(bool *moving);
|
||||
|
||||
/**
|
||||
* @brief Implementation of the `doMove` function from sinqAxis. The
|
||||
@ -66,8 +66,9 @@ class turboPmacAxis : public sinqAxis {
|
||||
* @param acceleration
|
||||
* @return asynStatus
|
||||
*/
|
||||
asynStatus doMove(double position, int relative, double min_velocity,
|
||||
double max_velocity, double acceleration);
|
||||
virtual asynStatus doMove(double position, int relative,
|
||||
double min_velocity, double max_velocity,
|
||||
double acceleration);
|
||||
|
||||
/**
|
||||
* @brief Readout of some values from the controller at IOC startup
|
||||
@ -79,7 +80,7 @@ class turboPmacAxis : public sinqAxis {
|
||||
*
|
||||
* @return asynStatus
|
||||
*/
|
||||
asynStatus init();
|
||||
virtual asynStatus init();
|
||||
|
||||
/**
|
||||
* @brief Implementation of the `doReset` function from sinqAxis.
|
||||
@ -87,7 +88,7 @@ class turboPmacAxis : public sinqAxis {
|
||||
* @param on
|
||||
* @return asynStatus
|
||||
*/
|
||||
asynStatus doReset();
|
||||
virtual asynStatus doReset();
|
||||
|
||||
/**
|
||||
* @brief Enable / disable the axis.
|
||||
@ -95,7 +96,7 @@ class turboPmacAxis : public sinqAxis {
|
||||
* @param on
|
||||
* @return asynStatus
|
||||
*/
|
||||
asynStatus enable(bool on);
|
||||
virtual asynStatus enable(bool on);
|
||||
|
||||
/**
|
||||
* @brief Read the encoder type (incremental or absolute) for this axis from
|
||||
@ -103,14 +104,14 @@ class turboPmacAxis : public sinqAxis {
|
||||
*
|
||||
* @return asynStatus
|
||||
*/
|
||||
asynStatus readEncoderType();
|
||||
virtual asynStatus readEncoderType();
|
||||
|
||||
/**
|
||||
* @brief Trigger a rereading of the encoder position.
|
||||
*
|
||||
* @return asynStatus
|
||||
*/
|
||||
asynStatus rereadEncoder();
|
||||
virtual asynStatus rereadEncoder();
|
||||
|
||||
/**
|
||||
* @brief Interpret the error code and populate the user message accordingly
|
||||
@ -122,14 +123,29 @@ class turboPmacAxis : public sinqAxis {
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief Return a pointer to the axis controller
|
||||
*/
|
||||
virtual turboPmacController *pController() override { return pC_; };
|
||||
|
||||
private:
|
||||
turboPmacController *pC_;
|
||||
|
||||
bool waitForHandshake_;
|
||||
time_t timeAtHandshake_;
|
||||
|
||||
// The axis status is used when enabling / disabling the motor
|
||||
int axisStatus_;
|
||||
std::unique_ptr<turboPmacAxisImpl> pTurboPmacA_;
|
||||
};
|
||||
|
||||
#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,
|
||||
const char *ipPortConfigName,
|
||||
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
|
||||
asynStatus status = asynSuccess;
|
||||
|
||||
// Initialization of all member variables
|
||||
comTimeout_ = comTimeout;
|
||||
|
||||
// Maximum allowed number of subsequent timeouts before the user is
|
||||
// informed.
|
||||
maxSubsequentTimeouts_ = 10;
|
||||
setMaxSubsequentTimeouts(10);
|
||||
|
||||
// =========================================================================
|
||||
// Create additional parameter library entries
|
||||
|
||||
status = createParam("REREAD_ENCODER_POSITION", asynParamInt32,
|
||||
&rereadEncoderPosition_);
|
||||
&pTurboPmacC_->rereadEncoderPosition);
|
||||
if (status != asynSuccess) {
|
||||
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
|
||||
@ -71,7 +93,8 @@ turboPmacController::turboPmacController(const char *portName,
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
status = createParam("READ_CONFIG", asynParamInt32, &readConfig_);
|
||||
status =
|
||||
createParam("READ_CONFIG", asynParamInt32, &pTurboPmacC_->readConfig);
|
||||
if (status != asynSuccess) {
|
||||
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
|
||||
@ -81,7 +104,19 @@ turboPmacController::turboPmacController(const char *portName,
|
||||
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) {
|
||||
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a "
|
||||
@ -100,7 +135,7 @@ turboPmacController::turboPmacController(const char *portName,
|
||||
const char *message_from_device =
|
||||
"\006"; // Hex-code for ACK (acknowledge) -> Each message from the MCU
|
||||
// is terminated by this value
|
||||
status = pasynOctetSyncIO->setInputEos(pasynOctetSyncIOipPort_,
|
||||
status = pasynOctetSyncIO->setInputEos(pasynOctetSyncIOipPort(),
|
||||
message_from_device,
|
||||
strlen(message_from_device));
|
||||
if (status != asynSuccess) {
|
||||
@ -109,7 +144,7 @@ turboPmacController::turboPmacController(const char *portName,
|
||||
"(setting input EOS failed with %s).\nTerminating IOC",
|
||||
portName, __PRETTY_FUNCTION__, __LINE__,
|
||||
stringifyAsynStatus(status));
|
||||
pasynOctetSyncIO->disconnect(pasynOctetSyncIOipPort_);
|
||||
pasynOctetSyncIO->disconnect(pasynOctetSyncIOipPort());
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@ -121,7 +156,7 @@ turboPmacController::turboPmacController(const char *portName,
|
||||
"with %s).\nTerminating IOC",
|
||||
portName, __PRETTY_FUNCTION__, __LINE__,
|
||||
stringifyAsynStatus(status));
|
||||
pasynOctetSyncIO->disconnect(pasynOctetSyncIOipPort_);
|
||||
pasynOctetSyncIO->disconnect(pasynOctetSyncIOipPort());
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@ -131,17 +166,21 @@ turboPmacController::turboPmacController(const char *portName,
|
||||
We try to connect to the port via the port name provided by the constructor.
|
||||
If this fails, the function is terminated via exit.
|
||||
*/
|
||||
pasynInt32SyncIO->connect(ipPortConfigName, 0, &pasynInt32SyncIOipPort_,
|
||||
NULL);
|
||||
if (status != asynSuccess || pasynInt32SyncIOipPort_ == nullptr) {
|
||||
pasynInt32SyncIO->connect(ipPortConfigName, 0,
|
||||
&pTurboPmacC_->pasynInt32SyncIOipPort, NULL);
|
||||
if (status != asynSuccess ||
|
||||
pTurboPmacC_->pasynInt32SyncIOipPort == nullptr) {
|
||||
errlogPrintf("Controller \"%s\" => %s, line %d:\nFATAL ERROR (cannot "
|
||||
"connect to MCU controller).\n"
|
||||
"Terminating IOC",
|
||||
portName, __PRETTY_FUNCTION__, __LINE__);
|
||||
pasynOctetSyncIO->disconnect(pasynOctetSyncIOipPort());
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
turboPmacController::~turboPmacController() {}
|
||||
|
||||
/*
|
||||
Access one of the axes of the controller via the axis adress stored in asynUser.
|
||||
If the axis does not exist or is not a Axis, a nullptr is returned and an
|
||||
@ -167,7 +206,6 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
||||
|
||||
// Definition of local variables.
|
||||
asynStatus status = asynSuccess;
|
||||
asynStatus paramLibStatus = asynSuccess;
|
||||
asynStatus timeoutStatus = asynSuccess;
|
||||
// char fullCommand[MAXBUF_] = {0};
|
||||
char drvMessageText[MAXBUF_] = {0};
|
||||
@ -215,20 +253,20 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
||||
*/
|
||||
status = pasynOctetSyncIO->writeRead(
|
||||
pasynOctetSyncIOipPort(), command, commandLength, response, MAXBUF_,
|
||||
comTimeout_, &nbytesOut, &nbytesIn, &eomReason);
|
||||
pTurboPmacC_->comTimeout, &nbytesOut, &nbytesIn, &eomReason);
|
||||
|
||||
msgPrintControlKey comKey =
|
||||
msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||
|
||||
if (status == asynTimeout) {
|
||||
|
||||
if (msgPrintControl_.shouldBePrinted(comKey, true, pasynUser())) {
|
||||
if (getMsgPrintControl().shouldBePrinted(comKey, true, pasynUser())) {
|
||||
asynPrint(
|
||||
this->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nTimeout while "
|
||||
"writing to the controller. Retrying ...%s\n",
|
||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
||||
msgPrintControl_.getSuffix());
|
||||
getMsgPrintControl().getSuffix());
|
||||
}
|
||||
|
||||
timeoutStatus = checkComTimeoutWatchdog(axisNo, drvMessageText,
|
||||
@ -239,13 +277,14 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
||||
checkMaxSubsequentTimeouts(timeoutCounter, axis);
|
||||
timeoutCounter += 1;
|
||||
|
||||
if (maxSubsequentTimeoutsExceeded_) {
|
||||
if (maxSubsequentTimeoutsExceeded()) {
|
||||
break;
|
||||
}
|
||||
|
||||
status = pasynOctetSyncIO->writeRead(
|
||||
pasynOctetSyncIOipPort(), command, commandLength, response,
|
||||
MAXBUF_, comTimeout_, &nbytesOut, &nbytesIn, &eomReason);
|
||||
MAXBUF_, pTurboPmacC_->comTimeout, &nbytesOut, &nbytesIn,
|
||||
&eomReason);
|
||||
if (status != asynTimeout) {
|
||||
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line "
|
||||
@ -255,16 +294,28 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
||||
}
|
||||
}
|
||||
} else if (status != asynSuccess) {
|
||||
if (msgPrintControl_.shouldBePrinted(comKey, true, pasynUser())) {
|
||||
if (getMsgPrintControl().shouldBePrinted(comKey, true, pasynUser())) {
|
||||
asynPrint(
|
||||
this->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nError %s while "
|
||||
"writing to the controller.%s\n",
|
||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
||||
stringifyAsynStatus(status), msgPrintControl_.getSuffix());
|
||||
stringifyAsynStatus(status), getMsgPrintControl().getSuffix());
|
||||
}
|
||||
} 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) {
|
||||
@ -301,16 +352,17 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
||||
"string detected\"). Please call the support.",
|
||||
reasonStringified);
|
||||
|
||||
if (msgPrintControl_.shouldBePrinted(terminateKey, true, pasynUser())) {
|
||||
if (getMsgPrintControl().shouldBePrinted(terminateKey, true,
|
||||
pasynUser())) {
|
||||
|
||||
asynPrint(this->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nMessage "
|
||||
"terminated due to reason %s.%s\n",
|
||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__,
|
||||
reasonStringified, msgPrintControl_.getSuffix());
|
||||
reasonStringified, getMsgPrintControl().getSuffix());
|
||||
}
|
||||
} else {
|
||||
msgPrintControl_.resetCount(terminateKey, pasynUser());
|
||||
getMsgPrintControl().resetCount(terminateKey, pasynUser());
|
||||
}
|
||||
|
||||
/*
|
||||
@ -327,15 +379,15 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
||||
if (numExpectedResponses != numReceivedResponses) {
|
||||
adjustResponseForPrint(modResponse, response, MAXBUF_);
|
||||
|
||||
if (msgPrintControl_.shouldBePrinted(numResponsesKey, true,
|
||||
pasynUser())) {
|
||||
if (getMsgPrintControl().shouldBePrinted(numResponsesKey, true,
|
||||
pasynUser())) {
|
||||
asynPrint(
|
||||
this->pasynUser(), ASYN_TRACE_ERROR,
|
||||
"Controller \"%s\", axis %d => %s, line %d\nUnexpected "
|
||||
"response '%s' (carriage returns are replaced with spaces) "
|
||||
"for command %s.%s\n",
|
||||
portName, axisNo, __PRETTY_FUNCTION__, __LINE__, modResponse,
|
||||
command, msgPrintControl_.getSuffix());
|
||||
command, getMsgPrintControl().getSuffix());
|
||||
}
|
||||
|
||||
snprintf(drvMessageText, sizeof(drvMessageText),
|
||||
@ -345,7 +397,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
||||
modResponse, command);
|
||||
status = asynError;
|
||||
} else {
|
||||
msgPrintControl_.resetCount(numResponsesKey, pasynUser());
|
||||
getMsgPrintControl().resetCount(numResponsesKey, pasynUser());
|
||||
}
|
||||
|
||||
// Create custom error messages for different failure modes, if no error
|
||||
@ -375,41 +427,18 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command,
|
||||
|
||||
// Log the overall status (communication successfull or not)
|
||||
if (status == asynSuccess) {
|
||||
paramLibStatus = axis->setIntegerParam(this->motorStatusCommsError_, 0);
|
||||
setAxisParamChecked(axis, motorStatusCommsError, false);
|
||||
} else {
|
||||
// Check if the axis already is in an error communication mode. If
|
||||
// it is not, upstream the error. This is done to avoid "flooding"
|
||||
// the user with different error messages if more than one error
|
||||
// ocurred before an error-free communication
|
||||
paramLibStatus =
|
||||
getIntegerParam(axisNo, motorStatusProblem_, &motorStatusProblem);
|
||||
if (paramLibStatus != asynSuccess) {
|
||||
return paramLibAccessFailed(paramLibStatus, "motorStatusProblem_",
|
||||
axisNo, __PRETTY_FUNCTION__, __LINE__);
|
||||
}
|
||||
getAxisParamChecked(axis, motorStatusProblem, &motorStatusProblem);
|
||||
|
||||
if (motorStatusProblem == 0) {
|
||||
paramLibStatus =
|
||||
axis->setStringParam(motorMessageText_, drvMessageText);
|
||||
if (paramLibStatus != asynSuccess) {
|
||||
return paramLibAccessFailed(paramLibStatus, "motorMessageText_",
|
||||
axisNo, __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
|
||||
paramLibStatus = axis->setIntegerParam(motorStatusProblem_, 1);
|
||||
if (paramLibStatus != asynSuccess) {
|
||||
return paramLibAccessFailed(paramLibStatus,
|
||||
"motorStatusProblem", axisNo,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
}
|
||||
|
||||
paramLibStatus = axis->setIntegerParam(motorStatusProblem_, 1);
|
||||
if (paramLibStatus != asynSuccess) {
|
||||
return paramLibAccessFailed(paramLibStatus,
|
||||
"motorStatusCommsError_", axisNo,
|
||||
__PRETTY_FUNCTION__, __LINE__);
|
||||
}
|
||||
setAxisParamChecked(axis, motorMessageText, drvMessageText);
|
||||
setAxisParamChecked(axis, motorStatusProblem, true);
|
||||
setAxisParamChecked(axis, motorStatusCommsError, true);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
@ -421,13 +450,13 @@ asynStatus turboPmacController::doFlushHardware() {
|
||||
constant defined in pmacAsynIPPort.c. This reason is then used within
|
||||
the write method of pasynInt32SyncIO to select the flush function.
|
||||
*/
|
||||
int temp = pasynInt32SyncIOipPort_->reason;
|
||||
pasynInt32SyncIOipPort_->reason = FLUSH_HARDWARE;
|
||||
int temp = pTurboPmacC_->pasynInt32SyncIOipPort->reason;
|
||||
pTurboPmacC_->pasynInt32SyncIOipPort->reason = FLUSH_HARDWARE;
|
||||
asynStatus status = (asynStatus)pasynInt32SyncIO->write(
|
||||
pasynInt32SyncIOipPort_, 1, comTimeout_);
|
||||
pTurboPmacC_->pasynInt32SyncIOipPort, 1, pTurboPmacC_->comTimeout);
|
||||
|
||||
// Reset the status afterwards
|
||||
pasynInt32SyncIOipPort_->reason = temp;
|
||||
pTurboPmacC_->pasynInt32SyncIOipPort->reason = temp;
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -440,11 +469,11 @@ asynStatus turboPmacController::writeInt32(asynUser *pasynUser,
|
||||
turboPmacAxis *axis = getTurboPmacAxis(pasynUser);
|
||||
|
||||
// Handle custom PVs
|
||||
if (function == rereadEncoderPosition_) {
|
||||
if (function == rereadEncoderPosition()) {
|
||||
return axis->rereadEncoder();
|
||||
} else if (function == readConfig_) {
|
||||
} else if (function == readConfig()) {
|
||||
return axis->init();
|
||||
} else if (function == flushHardware_) {
|
||||
} else if (function == flushHardware()) {
|
||||
return doFlushHardware();
|
||||
} else {
|
||||
return sinqController::writeInt32(pasynUser, value);
|
||||
@ -462,6 +491,19 @@ asynStatus turboPmacController::couldNotParseResponse(const char *command,
|
||||
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
|
||||
* iocsh */
|
||||
|
@ -10,7 +10,14 @@
|
||||
#define turboPmacController_H
|
||||
#include "sinqAxis.h"
|
||||
#include "sinqController.h"
|
||||
#include "turboPmacAxis.h"
|
||||
#include <memory>
|
||||
|
||||
// Forward declaration of the controller class to resolve the cyclic dependency
|
||||
// between the controller and the axis .h-file. See
|
||||
// https://en.cppreference.com/w/cpp/language/class.
|
||||
class turboPmacAxis;
|
||||
|
||||
struct turboPmacControllerImpl;
|
||||
|
||||
class turboPmacController : public sinqController {
|
||||
public:
|
||||
@ -33,6 +40,13 @@ class turboPmacController : public sinqController {
|
||||
double idlePollPeriod, double comTimeout,
|
||||
int numExtraParams = 0);
|
||||
|
||||
/**
|
||||
* @brief Destroy the controller. Its implementation is empty, however the
|
||||
* destructor needs to be provided for handling turboPmacControllerImpl.
|
||||
*
|
||||
*/
|
||||
virtual ~turboPmacController();
|
||||
|
||||
/**
|
||||
* @brief Get the axis object
|
||||
*
|
||||
@ -116,36 +130,17 @@ class turboPmacController : public sinqController {
|
||||
asynStatus doFlushHardware();
|
||||
|
||||
// Accessors for additional PVs
|
||||
int rereadEncoderPosition() { return rereadEncoderPosition_; }
|
||||
int readConfig() { return readConfig_; }
|
||||
int flushHardware() { return flushHardware_; }
|
||||
int rereadEncoderPosition();
|
||||
int readConfig();
|
||||
int flushHardware();
|
||||
int limFromHardware();
|
||||
|
||||
// Set the maximum buffer size. This is an empirical value which must be
|
||||
// large enough to avoid overflows for all commands to the device /
|
||||
// responses from it.
|
||||
static const uint32_t MAXBUF_ = 200;
|
||||
asynUser *pasynInt32SyncIOipPort();
|
||||
|
||||
asynUser *pasynInt32SyncIOipPort() { return pasynInt32SyncIOipPort_; }
|
||||
private:
|
||||
std::unique_ptr<turboPmacControllerImpl> pTurboPmacC_;
|
||||
|
||||
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 */
|
||||
|
Reference in New Issue
Block a user