diff --git a/Makefile b/Makefile index a9d4d74..06efa83 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ REQUIRED+=sinqMotor motorBase_VERSION=7.2.2 # Specify the version of sinqMotor we want to build against -sinqMotor_VERSION=mathis_s +sinqMotor_VERSION=0.8.0 # These headers allow to depend on this library for derived drivers. HEADERS += src/turboPmacAxis.h diff --git a/src/turboPmacAxis.cpp b/src/turboPmacAxis.cpp index a5e3ac1..64ef8b3 100644 --- a/src/turboPmacAxis.cpp +++ b/src/turboPmacAxis.cpp @@ -35,7 +35,8 @@ static void epicsInithookFunction(initHookState iState) { } } -turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo) +turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo, + bool initialize) : sinqAxis(pC, axisNo), pC_(pC) { asynStatus status = asynSuccess; @@ -63,13 +64,17 @@ turboPmacAxis::turboPmacAxis(turboPmacController *pC, int axisNo) exit(-1); } - // Register the hook function during construction of the first axis object - if (axes.empty()) { - initHookRegister(&epicsInithookFunction); - } + if (initialize) { + // Register the hook function during construction of the first axis + // object + if (axes.empty()) { + initHookRegister(&epicsInithookFunction); + } - // Collect all axes into this list which will be used in the hook function - axes.push_back(this); + // Collect all axes into this list which will be used in the hook + // function + axes.push_back(this); + } // Initialize all member variables waitForHandshake_ = false; @@ -360,39 +365,43 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { __PRETTY_FUNCTION__, __LINE__); } - // Intepret the status + // Create the unique callsite identifier manually so it can be used later in + // the shouldBePrinted calls. + msgPrintControlKey keyStatus = msgPrintControlKey( + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); + bool resetCountStatus = true; + + // Interpret the status switch (axStatus) { case -6: + // Axis is stopping *moving = true; - - asynPrint( - pC_->pasynUserSelf, ASYN_TRACE_FLOW, - "Controller \"%s\", axis %d => %s, line %d\nAxis is stopping\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); break; case -5: + // Axis is deactivated *moving = false; - asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW, - "Controller \"%s\", axis %d => %s, line %d\nAxis is " - "deactivated\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); - pl_status = setStringParam(pC_->motorMessageText_, "Deactivated"); if (pl_status != asynSuccess) { return pC_->paramLibAccessFailed(pl_status, "motorMessageText_", axisNo_, __PRETTY_FUNCTION__, __LINE__); } - break; case -4: + // Emergency stop *moving = false; - asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nEmergency stop " - "activated\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); + if (pC_->msgPrintControl_.shouldBePrinted(keyStatus, true, + pC_->pasynUserSelf)) { + asynPrint( + pC_->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nEmergency stop " + "activated.%s\n", + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, + pC_->msgPrintControl_.getSuffix()); + } + resetCountStatus = false; pl_status = setStringParam(pC_->motorMessageText_, "Emergency stop"); if (pl_status != asynSuccess) { @@ -403,13 +412,9 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { break; case -3: + // Disabled *moving = false; - asynPrint( - pC_->pasynUserSelf, ASYN_TRACE_FLOW, - "Controller \"%s\", axis %d => %s, line %d\nAxis %d is disabled\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_); - pl_status = setStringParam(pC_->motorMessageText_, "Disabled"); if (pl_status != asynSuccess) { return pC_->paramLibAccessFailed(pl_status, "motorMessageText_", @@ -419,43 +424,24 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { break; case 0: + // Idle *moving = false; - - asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW, - "Controller \"%s\", axis %d => %s, line %d\nAxis is idle\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); break; case 1: + // Move order acknowledged *moving = true; - - asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW, - "Controller \"%s\", axis %d => %s, line %d\nMove order " - "acknowledged\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); break; case 2: + // Move order confirmed possible *moving = true; - - asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW, - "Controller \"%s\", axis %d => %s, line %d\nMove order is " - "possible\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); break; case 3: + // Axis in Air Cushion Output status *moving = true; - - asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW, - "Controller \"%s\", axis %d => %s, line %d\nAxis in Air " - "Cushion Output status\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); break; case 4: + // Axis in Air Cushion Input status *moving = true; - - asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW, - "Controller \"%s\", axis %d => %s, line %d\nAxis in Air " - "Cushion Input status\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); break; case 5: *moving = true; @@ -469,12 +455,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { default: *moving = false; - asynPrint( - pC_->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nReached unreachable " - "state P%2.2d00 = %d\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_, - axStatus); + if (pC_->msgPrintControl_.shouldBePrinted(keyStatus, true, + pC_->pasynUserSelf)) { + + asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nReached " + "unreachable state P%2.2d00 = %d.%s\n", + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, + axisNo_, axStatus, pC_->msgPrintControl_.getSuffix()); + } + resetCountStatus = false; + snprintf(userMessage, sizeof(userMessage), "Unknown state P%2.2d00 = %d has been reached. Please call " "the support.", @@ -487,6 +478,10 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { } } + if (resetCountStatus) { + pC_->msgPrintControl_.resetCount(keyStatus); + } + if (*moving) { // If the axis is moving, evaluate the movement direction if ((currentPosition - previousPosition) > 0) { @@ -496,19 +491,30 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { } } - // Error handling + // Create the unique callsite identifier manually so it can be used later in + // the shouldBePrinted calls. + msgPrintControlKey keyError = msgPrintControlKey( + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); + bool resetError = true; + switch (error) { case 0: - // No error + // No error -> Reset the message repetition watchdog + pC_->msgPrintControl_.shouldBePrinted(keyError, false, + pC_->pasynUserSelf); break; case 1: // EPICS should already prevent this issue in the first place, // since it contains the user limits - asynPrint( - pC_->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nTarget position would " - "exceed user limits.\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); + if (pC_->msgPrintControl_.shouldBePrinted(keyError, true, + pC_->pasynUserSelf)) { + asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nTarget " + "position would exceed user limits.%s\n", + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, + pC_->msgPrintControl_.getSuffix()); + } + resetError = false; pl_status = setStringParam(pC_->motorMessageText_, "Target position would exceed software " @@ -523,11 +529,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { break; case 5: // Command not possible - asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nAxis is " - "still moving, but received another move command. EPICS " - "should prevent this, check if *moving is set correctly.\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); + if (pC_->msgPrintControl_.shouldBePrinted(keyStatus, true, + pC_->pasynUserSelf)) { + asynPrint( + pC_->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nAxis is " + "still moving, but received another move command. EPICS " + "should prevent this, check if *moving is set correctly.%s\n", + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, + pC_->msgPrintControl_.getSuffix()); + } + resetError = false; pl_status = setStringParam(pC_->motorMessageText_, "Axis received move command while it is " @@ -541,12 +553,15 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { poll_status = asynError; break; case 8: - asynPrint( - pC_->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nAir cushion feedback " - "stopped during movement (P%2.2d01 = %d).\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_, - error); + if (pC_->msgPrintControl_.shouldBePrinted(keyError, true, + pC_->pasynUserSelf)) { + asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nAir cushion " + "feedback stopped during movement (P%2.2d01 = %d).%s\n", + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, + axisNo_, error, pC_->msgPrintControl_.getSuffix()); + } + resetError = false; snprintf(userMessage, sizeof(userMessage), "Air cushion feedback stopped during movement (P%2.2d01 = " @@ -561,11 +576,16 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { } break; case 9: - asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nNo air cushion " - "feedback before movement start (P%2.2d01 = %d).\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, - axisNo_, error); + if (pC_->msgPrintControl_.shouldBePrinted(keyError, true, + pC_->pasynUserSelf)) { + asynPrint( + pC_->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nNo air cushion " + "feedback before movement start (P%2.2d01 = %d).%s\n", + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_, + error, pC_->msgPrintControl_.getSuffix()); + } + resetError = false; snprintf(userMessage, sizeof(userMessage), "No air cushion feedback before movement start (P%2.2d01 = " @@ -585,10 +605,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { error case can only happen if either the axis has an incremental encoder which is not properly homed or if a bug occured. */ - asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nAxis hit the " - "controller limits.\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); + + if (pC_->msgPrintControl_.shouldBePrinted(keyError, true, + pC_->pasynUserSelf)) { + asynPrint( + pC_->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nAxis hit the " + "controller limits.%s\n", + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, + pC_->msgPrintControl_.getSuffix()); + } + resetError = false; snprintf(userMessage, sizeof(userMessage), "Software limits or end switch hit (P%2.2d01 = %d). Try " @@ -608,10 +635,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { break; case 11: // Following error - asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nMaximum allowed " - "following error exceeded.\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); + + if (pC_->msgPrintControl_.shouldBePrinted(keyError, true, + pC_->pasynUserSelf)) { + asynPrint( + pC_->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nMaximum allowed " + "following error exceeded.%s\n", + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, + pC_->msgPrintControl_.getSuffix()); + } + resetError = false; snprintf(command, sizeof(command), "Maximum allowed following error exceeded (P%2.2d01 = %d). " @@ -629,6 +663,16 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { break; case 12: + if (pC_->msgPrintControl_.shouldBePrinted(keyError, true, + pC_->pasynUserSelf)) { + asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nSecurity " + "input is triggered (P%2.2d01 = %d).%s\n", + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, + axisNo_, error, pC_->msgPrintControl_.getSuffix()); + } + resetError = false; + snprintf(command, sizeof(command), "Security input is triggered (P%2.2d01 = %d). Check the SPS " "for errors (if available). Otherwise please call " @@ -646,11 +690,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { case 13: // Driver hardware error triggered - asynPrint( - pC_->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nDriver hardware error " - "triggered.\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__); + + if (pC_->msgPrintControl_.shouldBePrinted(keyError, true, + pC_->pasynUserSelf)) { + asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nDriver " + "hardware error triggered.%s\n", + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, + pC_->msgPrintControl_.getSuffix()); + } + resetError = false; + snprintf(command, sizeof(command), "Driver hardware error (P%2.2d01 = 13). " "Please call the support.", @@ -667,12 +717,16 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { case 14: // EPICS should already prevent this issue in the first place, // since it contains the user limits - asynPrint( - pC_->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nMove command exceeds " - "hardware limits (P%2.2d01 = %d).\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_, - error); + + if (pC_->msgPrintControl_.shouldBePrinted(keyError, true, + pC_->pasynUserSelf)) { + asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nMove " + "command exceeds hardware limits (P%2.2d01 = %d).%s\n", + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, + axisNo_, error, pC_->msgPrintControl_.getSuffix()); + } + resetError = false; snprintf(userMessage, sizeof(userMessage), "Move command exceeds hardware limits (P%2.2d01 = %d). Please " @@ -688,11 +742,17 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { poll_status = asynError; break; default: - asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nUnknown error " - "P%2.2d01 = %d.\n", - pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, - axisNo_, error); + + if (pC_->msgPrintControl_.shouldBePrinted(keyError, true, + pC_->pasynUserSelf)) { + asynPrint( + pC_->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nUnknown error " + "P%2.2d01 = %d.%s\n", + pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__, axisNo_, + error, pC_->msgPrintControl_.getSuffix()); + } + resetError = false; snprintf(userMessage, sizeof(userMessage), "Unknown error P%2.2d01 = %d. Please call the support.", @@ -708,6 +768,10 @@ asynStatus turboPmacAxis::doPoll(bool *moving) { break; } + if (resetError) { + pC_->msgPrintControl_.resetCount(keyError); + } + // Update the parameter library if (error != 0) { pl_status = setIntegerParam(pC_->motorStatusProblem_, true); diff --git a/src/turboPmacAxis.h b/src/turboPmacAxis.h index c11029a..858c2e6 100644 --- a/src/turboPmacAxis.h +++ b/src/turboPmacAxis.h @@ -15,7 +15,8 @@ class turboPmacAxis : public sinqAxis { * @param pController Pointer to the associated controller * @param axisNo Index of the axis */ - turboPmacAxis(turboPmacController *pController, int axisNo); + turboPmacAxis(turboPmacController *pController, int axisNo, + bool initialize = true); /** * @brief Destroy the turboPmacAxis diff --git a/src/turboPmacController.cpp b/src/turboPmacController.cpp index fe367ad..982f231 100644 --- a/src/turboPmacController.cpp +++ b/src/turboPmacController.cpp @@ -133,39 +133,18 @@ 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 error is emitted. */ -turboPmacAxis *turboPmacController::getAxis(asynUser *pasynUser) { +turboPmacAxis *turboPmacController::getTurboPmacAxis(asynUser *pasynUser) { asynMotorAxis *asynAxis = asynMotorController::getAxis(pasynUser); - return turboPmacController::castToAxis(asynAxis); + return dynamic_cast(asynAxis); } /* Access one of the axes of the controller via the axis index. If the axis does not exist or is not a Axis, the function must return Null */ -turboPmacAxis *turboPmacController::getAxis(int axisNo) { +turboPmacAxis *turboPmacController::getTurboPmacAxis(int axisNo) { asynMotorAxis *asynAxis = asynMotorController::getAxis(axisNo); - return turboPmacController::castToAxis(asynAxis); -} - -turboPmacAxis *turboPmacController::castToAxis(asynMotorAxis *asynAxis) { - - // ========================================================================= - - // If the axis slot of the pAxes_ array is empty, a nullptr must be returned - if (asynAxis == nullptr) { - return nullptr; - } - - // Here, an error is emitted since asyn_axis is not a nullptr but also not - // an instance of Axis - turboPmacAxis *axis = dynamic_cast(asynAxis); - if (axis == nullptr) { - asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nAxis is not " - "an instance of turboPmacAxis", - portName, axis->axisNo_, __PRETTY_FUNCTION__, __LINE__); - } - return axis; + return dynamic_cast(asynAxis); } asynStatus turboPmacController::writeRead(int axisNo, const char *command, @@ -204,7 +183,7 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command, // ========================================================================= - turboPmacAxis *axis = getAxis(axisNo); + turboPmacAxis *axis = getTurboPmacAxis(axisNo); if (axis == nullptr) { // We already did the error logging directly in getAxis return asynError; @@ -261,10 +240,6 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command, // +1 for the carriage return. const size_t fullComandLength = offset + commandLength + 1; - asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, - "Controller \"%s\", axis %d => %s, line %d\nSending command %s", - portName, axisNo, __PRETTY_FUNCTION__, __LINE__, fullCommand); - /* We use separated write and read commands here, not the combined writeRead method, because the latter is actually a flushWriteRead (see @@ -282,12 +257,19 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command, status = pasynOctetSyncIO->write(lowLevelPortUser_, fullCommand, fullComandLength, comTimeout_, &nbytesOut); + msgPrintControlKey writeKey = + msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__); + if (status == asynTimeout) { - asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nTimeout while " - "writing to the MCU\n", - portName, axisNo, __PRETTY_FUNCTION__, __LINE__); + if (msgPrintControl_.shouldBePrinted(writeKey, true, pasynUserSelf)) { + asynPrint( + this->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nTimeout while " + "writing to the MCU.%s\n", + portName, axisNo, __PRETTY_FUNCTION__, __LINE__, + msgPrintControl_.getSuffix()); + } timeoutStatus = checkComTimeoutWatchdog(axisNo, drvMessageText, sizeof(drvMessageText)); @@ -309,23 +291,35 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command, } } } else if (status != asynSuccess) { - asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nError %s while " - "writing to the controller\n", - portName, axisNo, __PRETTY_FUNCTION__, __LINE__, - stringifyAsynStatus(status)); + if (msgPrintControl_.shouldBePrinted(writeKey, true, pasynUserSelf)) { + asynPrint( + this->pasynUserSelf, 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()); + } + } else { + msgPrintControl_.resetCount(writeKey); } // Read the response from the MCU buffer status = pasynOctetSyncIO->read(lowLevelPortUser_, response, MAXBUF_, comTimeout_, &nbytesIn, &eomReason); + msgPrintControlKey readKey = + msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__); + if (status == asynTimeout) { - asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nTimeout while " - "reading from the MCU\n", - portName, axisNo, __PRETTY_FUNCTION__, __LINE__); + if (msgPrintControl_.shouldBePrinted(readKey, true, pasynUserSelf)) { + asynPrint( + this->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nTimeout while " + "reading from the MCU.%s\n", + portName, axisNo, __PRETTY_FUNCTION__, __LINE__, + msgPrintControl_.getSuffix()); + } // Add this event to the back of the timeout event counter timeoutStatus = checkComTimeoutWatchdog(axisNo, drvMessageText, @@ -348,11 +342,16 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command, } } } else if (status != asynSuccess) { - asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nError %s while " - "reading from the controller\n", - portName, axisNo, __PRETTY_FUNCTION__, __LINE__, - stringifyAsynStatus(status)); + if (msgPrintControl_.shouldBePrinted(readKey, true, pasynUserSelf)) { + asynPrint( + this->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nError %s while " + "reading from the controller.%s\n", + portName, axisNo, __PRETTY_FUNCTION__, __LINE__, + stringifyAsynStatus(status), msgPrintControl_.getSuffix()); + } + } else { + msgPrintControl_.resetCount(readKey); } if (timeoutStatus == asynError) { @@ -360,6 +359,8 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command, } // The message should only ever terminate due to reason 2 + msgPrintControlKey terminateKey = + msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__); if (eomReason != 2) { status = asynError; @@ -367,10 +368,16 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command, "Terminated message due to reason %d (should be 2).", eomReason); - asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER, - "Controller \"%s\", axis %d => %s, line %d\nMessage " - "terminated due to reason %i\n", - portName, axisNo, __PRETTY_FUNCTION__, __LINE__, eomReason); + if (msgPrintControl_.shouldBePrinted(terminateKey, true, + pasynUserSelf)) { + asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, + "Controller \"%s\", axis %d => %s, line %d\nMessage " + "terminated due to reason %i.%s\n", + portName, axisNo, __PRETTY_FUNCTION__, __LINE__, + eomReason, msgPrintControl_.getSuffix()); + } + } else { + msgPrintControl_.resetCount(terminateKey); } /* @@ -382,20 +389,30 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command, numReceivedResponses++; } } + msgPrintControlKey numResponsesKey = + msgPrintControlKey(portName, axisNo, __PRETTY_FUNCTION__, __LINE__); if (numExpectedResponses != numReceivedResponses) { adjustResponseForPrint(modResponse, response, MAXBUF_); - asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nUnexpected " - "response '%s' (carriage returns are replaced with spaces) " - "for command %s\n", - portName, axisNo, __PRETTY_FUNCTION__, __LINE__, modResponse, - command); + + if (msgPrintControl_.shouldBePrinted(numResponsesKey, true, + pasynUserSelf)) { + asynPrint( + this->pasynUserSelf, 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()); + } + snprintf(drvMessageText, sizeof(drvMessageText), "Received unexpected response '%s' (carriage returns " "are replaced with spaces) for command %s. " "Please call the support", modResponse, command); status = asynError; + } else { + msgPrintControl_.resetCount(numResponsesKey); } // Create custom error messages for different failure modes, if no error @@ -425,23 +442,12 @@ asynStatus turboPmacController::writeRead(int axisNo, const char *command, // Log the overall status (communication successfull or not) if (status == asynSuccess) { - - asynPrint(lowLevelPortUser_, ASYN_TRACEIO_DRIVER, - "Controller \"%s\", axis %d => %s, line %d\nDevice " - "response: %s (carriage returns are replaced with spaces)\n", - portName, axisNo, __PRETTY_FUNCTION__, __LINE__, modResponse); paramLibStatus = axis->setIntegerParam(this->motorStatusCommsError_, 0); } else { - asynPrint(lowLevelPortUser_, ASYN_TRACE_ERROR, - "Controller \"%s\", axis %d => %s, line %d\nCommunication " - "failed for command %s (%s)\n", - portName, axisNo, __PRETTY_FUNCTION__, __LINE__, fullCommand, - stringifyAsynStatus(status)); - - // 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 + // 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) { @@ -482,11 +488,7 @@ asynStatus turboPmacController::writeInt32(asynUser *pasynUser, // ===================================================================== - turboPmacAxis *axis = getAxis(pasynUser); - if (axis == nullptr) { - // We already did the error logging directly in getAxis - return asynError; - } + turboPmacAxis *axis = getTurboPmacAxis(pasynUser); // Handle custom PVs if (function == rereadEncoderPosition_) { @@ -538,8 +540,8 @@ asynStatus turboPmacCreateController(const char *portName, https://github.com/epics-modules/motor/blob/master/motorApp/MotorSrc/asynMotorController.cpp https://github.com/epics-modules/asyn/blob/master/asyn/asynPortDriver/asynPortDriver.cpp - The created object is registered in EPICS in its constructor and can safely - be "leaked" here. + The created object is registered in EPICS in its constructor and can + safely be "leaked" here. */ #pragma GCC diagnostic ignored "-Wunused-but-set-variable" #pragma GCC diagnostic ignored "-Wunused-variable" @@ -578,8 +580,8 @@ static void configTurboPmacCreateControllerCallFunc(const iocshArgBuf *args) { args[3].dval, args[4].dval, args[5].dval); } -// This function is made known to EPICS in turboPmac.dbd and is called by EPICS -// in order to register both functions in the IOC shell +// This function is made known to EPICS in turboPmac.dbd and is called by +// EPICS in order to register both functions in the IOC shell static void turboPmacControllerRegister(void) { iocshRegister(&configTurboPmacCreateController, configTurboPmacCreateControllerCallFunc); diff --git a/src/turboPmacController.h b/src/turboPmacController.h index b0f8824..ab913ad 100644 --- a/src/turboPmacController.h +++ b/src/turboPmacController.h @@ -40,7 +40,7 @@ class turboPmacController : public sinqController { * @return turboPmacAxis* If no axis could be found, this is a * nullptr */ - turboPmacAxis *getAxis(asynUser *pasynUser); + turboPmacAxis *getTurboPmacAxis(asynUser *pasynUser); /** * @brief Get the axis object @@ -49,18 +49,18 @@ class turboPmacController : public sinqController { * @return turboPmacAxis* If no axis could be found, this is a * nullptr */ - turboPmacAxis *getAxis(int axisNo); + turboPmacAxis *getTurboPmacAxis(int axisNo); /** * @brief Overloaded function of sinqController * - * The function is overloaded in order to read motorCanDisable_ + * The function is overloaded in order to read motorCanDisable_. * * @param pasynUser * @param value * @return asynStatus */ - asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value); + virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value); /** * @brief Overloaded function of sinqController @@ -71,7 +71,7 @@ class turboPmacController : public sinqController { * @param value New value * @return asynStatus */ - asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); + virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); protected: asynUser *lowLevelPortUser_; @@ -95,15 +95,6 @@ class turboPmacController : public sinqController { asynStatus writeRead(int axisNo, const char *command, char *response, int numExpectedResponses); - /** - * @brief Save cast of the given asynAxis pointer to a turboPmacAxis - * pointer. If the cast fails, this function returns a nullptr. - * - * @param asynAxis - * @return turboPmacAxis* - */ - turboPmacAxis *castToAxis(asynMotorAxis *asynAxis); - /** * @brief Specialized version of sinqController::errMsgCouldNotParseResponse * for turboPmac