/* asynMotorAxis.cpp * * Mark Rivers * * This file defines the base class for an asynMotorAxis. It is the class * from which real motor axes are derived. */ #include #include #include #define epicsExportSharedSymbols #include #include "asynMotorAxis.h" #include "asynMotorController.h" static const char *driverName = "asynMotorAxis"; /** Creates a new asynMotorAxis object. * \param[in] pC Pointer to the asynMotorController to which this axis belongs. * \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1. * * Checks that pC is not null, and that axisNo is in the valid range. * Sets a pointer to itself in pC->pAxes[axisNo_]. * Connects pasynUser_ to this asyn port and axisNo. */ asynMotorAxis::asynMotorAxis(class asynMotorController *pC, int axisNo) : pC_(pC), axisNo_(axisNo), statusChanged_(1) { static const char *functionName = "asynMotorAxis::asynMotorAxis"; if (!pC) { printf("%s:%s: Error, controller is NULL\n", driverName, functionName); return; } if ((axisNo < 0) || (axisNo >= pC->numAxes_)) { printf("%s:%s: Error, axis=%d is not in range 0 to %d\n", driverName, functionName, axisNo, pC->numAxes_-1); return; } pC->pAxes_[axisNo] = this; status_.status = 0; profilePositions_ = NULL; profilePositionsRBV_ = NULL; profileFollowingErrors_ = NULL; // Create the asynUser, connect to this axis pasynUser_ = pasynManager->createAsynUser(NULL, NULL); pasynManager->connectDevice(pasynUser_, pC->portName, axisNo); } // We implement the setIntegerParam, setDoubleParam, and callParamCallbacks methods so we can construct // the aggregate status structure and do callbacks on it /** Sets the value for an integer for this axis in the parameter library. * This function takes special action if the parameter is one of the motorStatus parameters * (motorStatusDirection_, motorStatusHomed_, etc.). In that case it sets or clears the appropriate * bit in its private MotorStatus.status structure and if that status has changed sets a flag to * do callbacks to devMotorAsyn when callParamCallbacks() is called. * \param[in] function The function (parameter) number * \param[in] value Value to set */ asynStatus asynMotorAxis::setIntegerParam(int function, int value) { int mask; epicsUInt32 status; // This assumes the parameters defined above are in the same order as the bits the motor record expects! if (function >= pC_->motorStatusDirection_ && function <= pC_->motorStatusHomed_) { status = status_.status; mask = 1 << (function - pC_->motorStatusDirection_); if (value) status |= mask; else status &= ~mask; if (status != status_.status) { status_.status = status; statusChanged_ = 1; } } // Call the base class method return pC_->setIntegerParam(axisNo_, function, value); } /** Sets the value for a double for this axis in the parameter library. * This function takes special action if the parameter is motorPosition_ or motorEncoderPosition_. * In that case it sets the value in the private MotorStatus structure and if the value has changed * then sets a flag to do callbacks to devMotorAsyn when callParamCallbacks() is called. * \param[in] function The function (parameter) number * \param[in] value Value to set */ asynStatus asynMotorAxis::setDoubleParam(int function, double value) { if (function == pC_->motorPosition_) { if (value != status_.position) { statusChanged_ = 1; status_.position = value; } } else if (function == pC_->motorEncoderPosition_) { if (value != status_.encoderPosition) { statusChanged_ = 1; status_.encoderPosition = value; } } // Call the base class method return pC_->setDoubleParam(axisNo_, function, value); } /** Calls the callbacks for any parameters that have changed for this axis in the parameter library. * This function takes special action if the aggregate MotorStatus structure has changed. * In that case it does callbacks on the asynGenericPointer interface, typically to devMotorAsyn. */ asynStatus asynMotorAxis::callParamCallbacks() { if (statusChanged_) { statusChanged_ = 0; pC_->doCallbacksGenericPointer((void *)&status_, pC_->motorStatus_, axisNo_); } return pC_->callParamCallbacks(axisNo_); } /* These are the functions for profile moves */ asynStatus asynMotorAxis::initializeProfile(int maxProfilePoints) { if (profilePositions_) free(profilePositions_); profilePositions_ = (double *)calloc(maxProfilePoints, sizeof(double)); if (profilePositionsRBV_) free(profilePositionsRBV_); profilePositionsRBV_ = (double *)calloc(maxProfilePoints, sizeof(double)); if (profileFollowingErrors_) free(profileFollowingErrors_); profileFollowingErrors_ = (double *)calloc(maxProfilePoints, sizeof(double)); return asynSuccess; } /** Function to build a coordinated move of multiple axes. * This is not currently implemented, as the API still needs work! */ asynStatus asynMotorAxis::buildProfile() { // static const char *functionName = "asynMotorController::buildProfile"; return asynSuccess; } /** Function to execute a coordinated move of multiple axes. * This is not currently implemented, as the API still needs work! */ asynStatus asynMotorAxis::executeProfile() { // static const char *functionName = "asynMotorController::executeProfile"; return asynSuccess; } /** Function to readback the actual motor positions from a coordinated move of multiple axes. * This is not currently implemented, as the API still needs work! */ asynStatus asynMotorAxis::readbackProfile() { // static const char *functionName = "asynMotorController::readbackProfile"; return asynSuccess; }