Simplified paramLib access and show error messages for one poll cycle
Simplified getting and setting paramLib entries via a macro and created a mechanism within poll() which makes sure that error messages are shown for at least one poll cycle. Also moved MAXBUF_ to the SinqController level.
This commit is contained in:
@ -233,13 +233,14 @@ It calls `doReset` and performs some fast polls after `doReset` returns.
|
||||
- `poll`: This is a wrapper around `doPoll` which performs some bookkeeping tasks before and after calling `doPoll`:
|
||||
|
||||
Before calling `doPoll`:
|
||||
- Reset the status problem flag, the communication error flag and the error message.
|
||||
- Check if the paramLib already contains an old error message. If so, put it into a temporary bufffer
|
||||
|
||||
After calling `doPoll`:
|
||||
- Call `checkMovTimeoutWatchdog`. If the movement timed out, create an error message for the user
|
||||
- Update the readback-value for the axis enablement.
|
||||
- Reset `motorStatusProblem_`, `motorStatusCommsError_` and `motorMessageText_` if `doPoll` returned `asynSuccess`
|
||||
- If `doPoll` returns anything other than `asynSuccess` or if an old error message is waiting in the temporary buffer, set `motorStatusProblem` to true, otherwise to false. If an old error message is waiting in the temporary buffer, but `doPoll` returned `asynSuccess`, overwrite the paramLib entry for `motorMessageText` with the old error message.
|
||||
- Run `callParamCallbacks`
|
||||
- Reset `motorMessageText` AFTER updating the PVs. This makes sure that the error message is shown for at least one poll cycle.
|
||||
- Return the status of `doPoll`
|
||||
- `motorPosition`: Returns the parameter library value of the motor position, accounted for the motor record resolution (see section "Motor record resolution MRES")
|
||||
- `setMotorPosition`: Writes the given value into the parameter library, accounted for the motor record resolution (see section "Motor record resolution MRES")
|
||||
|
@ -100,7 +100,7 @@ asynStatus getAxisParam<char>(sinqAxis *axis, const char *indexName,
|
||||
int (sinqController::*func)(), char *readValue,
|
||||
const char *callerFunctionName, int lineNumber) {
|
||||
|
||||
int maxChars = 190;
|
||||
int maxChars = 200;
|
||||
|
||||
int indexValue = (axis->pController()->*func)();
|
||||
asynStatus status = axis->pController()->getStringParam(
|
||||
@ -259,6 +259,8 @@ asynStatus sinqAxis::poll(bool *moving) {
|
||||
asynStatus poll_status = asynSuccess;
|
||||
int homing = 0;
|
||||
int adaptivePolling = 0;
|
||||
char waitingMessage[pC_->MAXBUF_] = {0};
|
||||
char newMessage[pC_->MAXBUF_] = {0};
|
||||
|
||||
/*
|
||||
If adaptive polling is enabled:
|
||||
@ -300,35 +302,42 @@ asynStatus sinqAxis::poll(bool *moving) {
|
||||
lastPollTime_ = ts;
|
||||
|
||||
/*
|
||||
At the beginning of the poll, it is assumed that the axis has no status
|
||||
problems and therefore all error indicators are reset. This does not affect
|
||||
the PVs until callParamCallbacks has been called!
|
||||
|
||||
The motorStatusProblem_ field changes the motor record fields SEVR and STAT.
|
||||
If the "motorMessageText" record currently contains an error message, it
|
||||
should be shown for at least one poll period. To assure this, it is read out
|
||||
here from the paramLib into "waitingMessage". If no new error message was
|
||||
added to the parameter library at the end of the poll cycle, the
|
||||
"waitingMessage" is briefly put into the paramLib again, then the PVs are
|
||||
updated and then the message text is cleared again.
|
||||
*/
|
||||
setAxisParamChecked(this, motorStatusCommsError, false);
|
||||
setAxisParamChecked(this, motorMessageText, "");
|
||||
getAxisParamChecked(this, motorMessageText, &waitingMessage);
|
||||
|
||||
// The poll function is just a wrapper around doPoll and
|
||||
// handles mainly the callParamCallbacks() function. This wrapper is used
|
||||
// to make sure callParamCallbacks() is called in case of a premature
|
||||
// return.
|
||||
// Clear the communication
|
||||
setAxisParamChecked(this, motorStatusCommsError, false);
|
||||
|
||||
/*
|
||||
The poll function is just a wrapper around doPoll and handles mainly the
|
||||
callParamCallbacks() function. This wrapper is used to make sure
|
||||
callParamCallbacks() is called in case of a premature return.
|
||||
*/
|
||||
poll_status = doPoll(moving);
|
||||
|
||||
// If the poll did not succeed, something went wrong and the motor has a
|
||||
// status problem.
|
||||
if (poll_status == asynSuccess) {
|
||||
setAxisParamChecked(this, motorStatusProblem, false);
|
||||
} else {
|
||||
/*
|
||||
If the poll did not succeed OR if an error message is waiting, something
|
||||
went wrong and the motor has a status problem. Otherwise, delete the error
|
||||
message entry which is currently in the paramLib.
|
||||
*/
|
||||
if (poll_status != asynSuccess || waitingMessage[0] != '\0') {
|
||||
setAxisParamChecked(this, motorStatusProblem, true);
|
||||
} else {
|
||||
setAxisParamChecked(this, motorMessageText, "");
|
||||
setAxisParamChecked(this, motorStatusProblem, false);
|
||||
}
|
||||
|
||||
getAxisParamChecked(this, motorStatusHome, &homing);
|
||||
|
||||
/*
|
||||
Motor is in homing mode, was moving, but is not moving anymore -> It can be
|
||||
assumed that the homing procedure is done.
|
||||
*/
|
||||
getAxisParamChecked(this, motorStatusHome, &homing);
|
||||
if (homing == 1 && !(*moving) && wasMoving_) {
|
||||
setAxisParamChecked(this, motorStatusHome, false);
|
||||
setAxisParamChecked(this, motorStatusHomed, true);
|
||||
@ -363,6 +372,12 @@ asynStatus sinqAxis::poll(bool *moving) {
|
||||
poll_status = pl_status;
|
||||
}
|
||||
|
||||
/*
|
||||
Delete the error message AFTER updating the PVs so it is not there anymore
|
||||
during the next poll.
|
||||
*/
|
||||
setAxisParamChecked(this, motorMessageText, "");
|
||||
|
||||
return poll_status;
|
||||
}
|
||||
|
||||
@ -416,7 +431,6 @@ asynStatus sinqAxis::home(double minVelocity, double maxVelocity,
|
||||
|
||||
if (status == asynSuccess) {
|
||||
|
||||
setAxisParamChecked(this, motorMessageText, "Reference drive");
|
||||
setAxisParamChecked(this, motorStatusHome, true);
|
||||
setAxisParamChecked(this, motorStatusHomed, false);
|
||||
setAxisParamChecked(this, motorStatusAtHome, false);
|
||||
|
@ -500,40 +500,8 @@ asynStatus getAxisParam(sinqAxis *axis, const char *indexName,
|
||||
* return asynSuccess;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* If `readValue` is a `char *`, the size of the buffer needs to be provided as
|
||||
* well:
|
||||
* ```
|
||||
* char readValue[20] = {0};
|
||||
* getAxisParamChecked(this, motorStatusProblem_, &readValue, sizeof(readValue))
|
||||
* ```
|
||||
* expands to
|
||||
* ```
|
||||
* {
|
||||
* int indexValue = axis->pController()->motorStatusProblem_();
|
||||
* asynStatus status = axis->pController()->getStringParam(axis->axisNo(),
|
||||
* indexValue, sizeof(readValue), readValue); if (status != asynSuccess) {
|
||||
* return axis->pController()->paramLibAccessFailed( status,
|
||||
* "motorStatusProblem_", axis->axisNo(), __PRETTY_FUNCTION__,
|
||||
* __LINE__);
|
||||
* }
|
||||
* return asynSuccess;
|
||||
* }
|
||||
* ```
|
||||
* =============================================================================
|
||||
*/
|
||||
// #define getAxisParamChecked(axis, indexGetterFunction, readValue, ...) \
|
||||
// { \
|
||||
// asynStatus getStatus = getAxisParam( \
|
||||
// axis, #indexGetterFunction, \
|
||||
// &std::remove_pointer< \
|
||||
// decltype(axis->pController())>::type::indexGetterFunction, \
|
||||
// readValue, __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); \
|
||||
// if (getStatus != asynSuccess) { \
|
||||
// return getStatus; \
|
||||
// } \
|
||||
// }
|
||||
|
||||
#define getAxisParamChecked(axis, indexGetterFunction, readValue) \
|
||||
{ \
|
||||
asynStatus getStatus = getAxisParam( \
|
||||
|
@ -490,17 +490,12 @@ asynStatus sinqController::checkComTimeoutWatchdog(int axisNo,
|
||||
|
||||
asynStatus sinqController::checkComTimeoutWatchdog(sinqAxis *axis) {
|
||||
|
||||
char motorMessage[200] = {0};
|
||||
char errorMessage[MAXBUF_] = {0};
|
||||
|
||||
asynStatus status =
|
||||
checkComTimeoutWatchdog(axis->axisNo(), motorMessage, 200);
|
||||
checkComTimeoutWatchdog(axis->axisNo(), errorMessage, MAXBUF_);
|
||||
if (status == asynError) {
|
||||
status = axis->setStringParam(motorMessageText_, motorMessage);
|
||||
if (status != asynSuccess) {
|
||||
return paramLibAccessFailed(status, "motorMessageText_",
|
||||
axis->axisNo(), __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
setAxisParamChecked(axis, motorMessageText, motorMessage);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@ -543,17 +538,12 @@ asynStatus sinqController::checkMaxSubsequentTimeouts(int timeoutNo, int axisNo,
|
||||
asynStatus sinqController::checkMaxSubsequentTimeouts(int timeoutNo,
|
||||
sinqAxis *axis) {
|
||||
|
||||
char motorMessage[200] = {0};
|
||||
char motorMessage[MAXBUF_] = {0};
|
||||
|
||||
asynStatus status = checkMaxSubsequentTimeouts(timeoutNo, axis->axisNo(),
|
||||
motorMessage, 200);
|
||||
motorMessage, MAXBUF_);
|
||||
if (status == asynError) {
|
||||
status = axis->setStringParam(motorMessageText_, motorMessage);
|
||||
if (status != asynSuccess) {
|
||||
return paramLibAccessFailed(status, "motorMessageText_",
|
||||
axis->axisNo(), __PRETTY_FUNCTION__,
|
||||
__LINE__);
|
||||
}
|
||||
setAxisParamChecked(axis, motorMessageText, motorMessage);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
@ -376,6 +376,11 @@ class epicsShareClass sinqController : public asynMotorController {
|
||||
*/
|
||||
int outstandingForcedFastPolls() { return outstandingForcedFastPolls_; }
|
||||
|
||||
// Maximum error message 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;
|
||||
|
||||
// =========================================================================
|
||||
|
||||
protected:
|
||||
|
Reference in New Issue
Block a user