Applied PIMPL by moving members to internal struct sinqAxisImpl

This change makes sinqMotor ready for 1.x releases where ABI stability
and backwards compatibility is guaranteed.
This commit is contained in:
2025-05-22 13:56:44 +02:00
parent 275672aaef
commit 83aa437b6b
4 changed files with 299 additions and 218 deletions
+60 -25
View File
@@ -3,11 +3,31 @@
#include "sinqAxis.h"
#include "epicsExport.h"
#include "iocsh.h"
#include "msgPrintControl.h"
#include "sinqController.h"
#include <epicsTime.h>
#include <errlog.h>
#include <math.h>
#include <unistd.h>
struct sinqAxisImpl {
// Internal variables used in the movement timeout watchdog
time_t expectedArrivalTime;
time_t offsetMovTimeout;
double scaleMovTimeout;
bool watchdogMovActive;
// Store the motor target position for the movement time calculation
double targetPosition;
bool wasMoving;
/*
Store the time since the last poll
*/
epicsTimeStamp lastPollTime;
};
// Generic fallback - if the compiler tries to compile this function, it fails.
template <typename T>
asynStatus setAxisParam(sinqAxis *axis, const char *indexName,
@@ -184,13 +204,17 @@ sinqAxis::sinqAxis(class sinqController *pC, int axisNo)
: asynMotorAxis((asynMotorController *)pC, axisNo), pC_(pC) {
asynStatus status = asynSuccess;
watchdogMovActive_ = false;
scaleMovTimeout_ = 2.0;
offsetMovTimeout_ = 30;
targetPosition_ = 0.0;
wasMoving_ = false;
epicsTimeStamp lastPollTime;
epicsTimeGetCurrent(&lastPollTime);
epicsTimeGetCurrent(&lastPollTime_);
pSinqA_ = std::make_unique<sinqAxisImpl>(
(sinqAxisImpl){.expectedArrivalTime = 0,
.offsetMovTimeout = 30,
.scaleMovTimeout = 2.0,
.watchdogMovActive = false,
.targetPosition = 0.0,
.wasMoving = false,
.lastPollTime = lastPollTime});
// This check is also done in asynMotorAxis, but there the IOC continues
// running even though the configuration is incorrect. When failing this
@@ -346,10 +370,10 @@ asynStatus sinqAxis::poll(bool *moving) {
*/
if (adaptivePolling != 0 && pC_->outstandingForcedFastPolls() == 0) {
// Motor wasn't moving during the last poll
if (!wasMoving_) {
if (!pSinqA_->wasMoving) {
// Add the idle poll period
epicsTimeStamp earliestTimeNextPoll = lastPollTime_;
epicsTimeStamp earliestTimeNextPoll = pSinqA_->lastPollTime;
epicsTimeAddSeconds(&earliestTimeNextPoll, pC_->idlePollPeriod());
if (epicsTimeLessThanEqual(&earliestTimeNextPoll, &ts) == 0) {
@@ -360,7 +384,7 @@ asynStatus sinqAxis::poll(bool *moving) {
}
// Update the start time of the last poll
lastPollTime_ = ts;
pSinqA_->lastPollTime = ts;
/*
If the "motorMessageText" record currently contains an error message, it
@@ -411,7 +435,7 @@ asynStatus sinqAxis::poll(bool *moving) {
assumed that the homing procedure is done.
*/
getAxisParamChecked(this, motorStatusHome, &homing);
if (homing == 1 && !(*moving) && wasMoving_) {
if (homing == 1 && !(*moving) && pSinqA_->wasMoving) {
setAxisParamChecked(this, motorStatusHome, false);
setAxisParamChecked(this, motorStatusHomed, true);
setAxisParamChecked(this, motorStatusAtHome, true);
@@ -419,7 +443,7 @@ asynStatus sinqAxis::poll(bool *moving) {
// Update the wasMoving status
if (pC_->outstandingForcedFastPolls() == 0) {
wasMoving_ = *moving;
pSinqA_->wasMoving = *moving;
}
// Check and update the watchdog
@@ -467,7 +491,7 @@ asynStatus sinqAxis::move(double position, int relative, double minVelocity,
// Store the target position internally
getAxisParamChecked(this, motorRecResolution, &motorRecRes);
targetPosition_ = position * motorRecRes;
pSinqA_->targetPosition = position * motorRecRes;
status = doMove(position, relative, minVelocity, maxVelocity, acceleration);
if (status != asynSuccess) {
@@ -485,7 +509,7 @@ asynStatus sinqAxis::move(double position, int relative, double minVelocity,
setAxisParamChecked(this, motorStatusAtHome, false);
// Needed for adaptive polling
wasMoving_ = true;
pSinqA_->wasMoving = true;
return pC_->callParamCallbacks();
}
@@ -507,7 +531,7 @@ asynStatus sinqAxis::home(double minVelocity, double maxVelocity,
setAxisParamChecked(this, motorStatusHome, true);
setAxisParamChecked(this, motorStatusHomed, false);
setAxisParamChecked(this, motorStatusAtHome, false);
wasMoving_ = true;
pSinqA_->wasMoving = true;
status = assertConnected();
if (status != asynSuccess) {
@@ -681,7 +705,7 @@ asynStatus sinqAxis::startMovTimeoutWatchdog() {
time_t timeAccel = 0;
// Activate the watchdog
watchdogMovActive_ = true;
pSinqA_->watchdogMovActive = true;
/*
NOTE: This function must not be called in the constructor (e.g. in order
@@ -717,8 +741,9 @@ asynStatus sinqAxis::startMovTimeoutWatchdog() {
motorVelocity = motorVelocityRec * motorRecRes;
if (pl_status == asynSuccess) {
timeContSpeed = std::ceil(
std::fabs(targetPosition_ - motorPos) / motorVelocity);
timeContSpeed =
std::ceil(std::fabs(pSinqA_->targetPosition - motorPos) /
motorVelocity);
}
}
@@ -734,11 +759,11 @@ asynStatus sinqAxis::startMovTimeoutWatchdog() {
}
// Calculate the expected arrival time
expectedArrivalTime_ =
time(NULL) + offsetMovTimeout_ +
scaleMovTimeout_ * (timeContSpeed + 2 * timeAccel);
pSinqA_->expectedArrivalTime =
time(NULL) + pSinqA_->offsetMovTimeout +
pSinqA_->scaleMovTimeout * (timeContSpeed + 2 * timeAccel);
} else {
watchdogMovActive_ = false;
pSinqA_->watchdogMovActive = false;
}
return asynSuccess;
}
@@ -749,8 +774,8 @@ asynStatus sinqAxis::checkMovTimeoutWatchdog(bool moving) {
getAxisParamChecked(this, motorEnableMovWatchdog, &enableMovWatchdog);
// Not moving or watchdog not active / enabled
if (enableMovWatchdog == 0 || !moving || !watchdogMovActive_) {
watchdogMovActive_ = false;
if (enableMovWatchdog == 0 || !moving || !pSinqA_->watchdogMovActive) {
pSinqA_->watchdogMovActive = false;
return asynSuccess;
}
@@ -760,7 +785,7 @@ asynStatus sinqAxis::checkMovTimeoutWatchdog(bool moving) {
__PRETTY_FUNCTION__, __LINE__);
// Check if the expected time of arrival has been exceeded.
if (expectedArrivalTime_ < time(NULL)) {
if (pSinqA_->expectedArrivalTime < time(NULL)) {
// Check the watchdog
if (pC_->getMsgPrintControl().shouldBePrinted(key, true,
pC_->pasynUser())) {
@@ -768,7 +793,7 @@ asynStatus sinqAxis::checkMovTimeoutWatchdog(bool moving) {
"Controller \"%s\", axis %d => %s, line %d:\nExceeded "
"expected arrival time %ld (current time is %ld).\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
expectedArrivalTime_, time(NULL));
pSinqA_->expectedArrivalTime, time(NULL));
}
setAxisParamChecked(
@@ -783,6 +808,16 @@ asynStatus sinqAxis::checkMovTimeoutWatchdog(bool moving) {
return asynSuccess;
}
asynStatus sinqAxis::setOffsetMovTimeout(time_t offsetMovTimeout) {
pSinqA_->offsetMovTimeout = offsetMovTimeout;
return asynSuccess;
}
asynStatus sinqAxis::setScaleMovTimeout(time_t scaleMovTimeout) {
pSinqA_->scaleMovTimeout = scaleMovTimeout;
return asynSuccess;
}
// =============================================================================
// IOC shell functions
extern "C" {