diff --git a/motorApp/NewportSrc/drvMM4000Asyn.c b/motorApp/NewportSrc/drvMM4000Asyn.c new file mode 100644 index 00000000..6cebdde8 --- /dev/null +++ b/motorApp/NewportSrc/drvMM4000Asyn.c @@ -0,0 +1,731 @@ +#include +#include "epicsThread.h" +#include +#include +#include +#include +#include + +#include "drvMM4000Asyn.h" +#include "paramLib.h" + +#include "epicsFindSymbol.h" +#include "epicsTime.h" +#include "epicsThread.h" +#include "epicsEvent.h" +#include "epicsString.h" +#include "epicsMutex.h" +#include "ellLib.h" +#include "asynDriver.h" +#include "asynOctetSyncIO.h" + +#include "drvSup.h" +#include "epicsExport.h" +#define DEFINE_MOTOR_PROTOTYPES 1 +#include "motor_interface.h" + +motorAxisDrvSET_t motorMM4000 = + { + 20, + motorAxisReport, /**< Standard EPICS driver report function (optional) */ + motorAxisInit, /**< Standard EPICS dirver initialisation function (optional) */ + motorAxisSetLog, /**< Defines an external logging function (optional) */ + motorAxisSetLogParam, /**< Defines an external logging function user parameter (optional) */ + motorAxisOpen, /**< Driver open function */ + motorAxisClose, /**< Driver close function */ + motorAxisSetCallback, /**< Provides a callback function the driver can call when the status updates */ + motorAxisPrimitive, /**< Passes a controller dependedent string */ + motorAxisSetDouble, /**< Pointer to function to set a double value */ + motorAxisSetInteger, /**< Pointer to function to set an integer value */ + motorAxisGetDouble, /**< Pointer to function to get a double value */ + motorAxisGetInteger, /**< Pointer to function to get an integer value */ + motorAxisHome, /**< Pointer to function to execute a more to reference or home */ + motorAxisMove, /**< Pointer to function to execute a position move */ + motorAxisVelocityMove, /**< Pointer to function to execute a velocity mode move */ + motorAxisStop /**< Pointer to function to stop motion */ + }; + +epicsExportAddress(drvet, motorMM4000); + +typedef enum { + MM4000, + MM4005 +} MM_model; + +typedef struct { + epicsMutexId MM4000Lock; + asynUser *pasynUser; + int numAxes; + char firmwareVersion[100]; + MM_model model; + double movingPollPeriod; + double idlePollPeriod; + epicsEventId pollEventId; + AXIS_HDL pAxis; /* array of axes */ +} MM4000Controller; + +typedef struct motorAxisHandle +{ + MM4000Controller *pController; + PARAMS params; + double currentPosition; + double stepSize; + double highLimit; + double lowLimit; + double homePreset; + int closedLoop; + int axisStatus; + int card; + int axis; + int maxDigits; + void *logParam; + epicsMutexId mutexId; +} motorAxis; + +typedef struct +{ + AXIS_HDL pFirst; + epicsThreadId motorThread; + motorAxisLogFunc print; + epicsTimeStamp now; +} motorMM4000_t; + + +static int motorMM4000LogMsg(void * param, const motorAxisLogMask_t logMask, const char *pFormat, ...); +static int sendOnly(MM4000Controller *pController, char *outputString); +static int sendAndReceive(MM4000Controller *pController, char *outputString, char *inputString, int inputSize); + +#define PRINT (drv.print) +#define FLOW motorAxisTraceFlow +#define ERROR motorAxisTraceError +#define IODRIVER motorAxisTraceIODriver + +#define MM4000_MAX_AXES 8 +#define BUFFER_SIZE 100 /* Size of input and output buffers */ +#define TIMEOUT 2.0 /* Timeout for I/O in seconds */ + +#define MM4000_HOME 0x20 /* Home LS. */ +#define MM4000_LOW_LIMIT 0x10 /* Minus Travel Limit. */ +#define MM4000_HIGH_LIMIT 0x08 /* Plus Travel Limit. */ +#define MM4000_DIRECTION 0x04 /* Motor direction: 0 - minus; 1 - plus. */ +#define MM4000_POWER_ON 0x02 /* Motor power 0 - ON; 1 - OFF. */ +#define MM4000_MOVING 0x01 /* In-motion indicator. */ + + +#define TCP_TIMEOUT 2.0 +static motorMM4000_t drv={ NULL, NULL, motorMM4000LogMsg, { 0, 0 } }; +static int numMM4000Controllers; +/* Pointer to array of controller strutures */ +static MM4000Controller *pMM4000Controller=NULL; + +#define MAX(a,b) ((a)>(b)? (a): (b)) +#define MIN(a,b) ((a)<(b)? (a): (b)) + +static char* getMM4000Error(AXIS_HDL pAxis, int status, char *buffer); + +static void motorAxisReportAxis(AXIS_HDL pAxis, int level) +{ + if (level > 0) + { + printf("Axis %d\n", pAxis->axis); + printf(" axisStatus: 0x%x\n", pAxis->axisStatus); + printf(" high limit: %f\n", pAxis->highLimit); + printf(" low limit: %f\n", pAxis->lowLimit); + printf(" home preset: %f\n", pAxis->homePreset); + printf(" step size: %f\n", pAxis->stepSize); + printf(" max digits: %d\n", pAxis->maxDigits); + } +} + +static void motorAxisReport(int level) +{ + int i, j; + + for(i=0; ilogParam = param; + } + return MOTOR_AXIS_OK; +} + +static AXIS_HDL motorAxisOpen(int card, int axis, char * param) +{ + AXIS_HDL pAxis; + + if (card > numMM4000Controllers) return(NULL); + if (axis > pMM4000Controller[card].numAxes) return(NULL); + pAxis = &pMM4000Controller[card].pAxis[axis]; + return pAxis; +} + +static int motorAxisClose(AXIS_HDL pAxis) +{ + return MOTOR_AXIS_OK; +} + +static int motorAxisGetInteger(AXIS_HDL pAxis, motorAxisParam_t function, int * value) +{ + if (pAxis == NULL) return MOTOR_AXIS_ERROR; + else + { + return motorParam->getInteger(pAxis->params, (paramIndex) function, value); + } +} + +static int motorAxisGetDouble(AXIS_HDL pAxis, motorAxisParam_t function, double * value) +{ + if (pAxis == NULL) return MOTOR_AXIS_ERROR; + else + { + return motorParam->getDouble(pAxis->params, (paramIndex) function, value); + } +} + +static int motorAxisSetCallback(AXIS_HDL pAxis, motorAxisCallbackFunc callback, void * param) +{ + if (pAxis == NULL) return MOTOR_AXIS_ERROR; + else + { + return motorParam->setCallback(pAxis->params, callback, param); + } +} + +static int motorAxisPrimitive(AXIS_HDL pAxis, int length, char * string) +{ + return MOTOR_AXIS_OK; +} + +static int motorAxisSetDouble(AXIS_HDL pAxis, motorAxisParam_t function, double value) +{ + int ret_status = MOTOR_AXIS_ERROR; + int status; + double deviceValue; + char buff[100]; + + if (pAxis == NULL) return MOTOR_AXIS_ERROR; + else + { + switch (function) + { + case motorAxisPosition: + { + PRINT(pAxis->logParam, ERROR, "motorAxisSetDouble: MM4000 does not support setting position\n"); + break; + } + case motorAxisEncoderRatio: + { + PRINT(pAxis->logParam, ERROR, "motorAxisSetDouble: MM4000 does not support setting encoder ratio\n"); + break; + } + case motorAxisResolution: + { + PRINT(pAxis->logParam, ERROR, "motorAxisSetDouble: MM4000 does not support setting resolution\n"); + break; + } + case motorAxisLowLimit: + { + deviceValue = value*pAxis->stepSize; + sprintf(buff, "%dSR%.*f", pAxis->axis+1, pAxis->maxDigits, deviceValue); + ret_status = sendOnly(pAxis->pController, buff); + break; + } + case motorAxisHighLimit: + { + deviceValue = value*pAxis->stepSize; + sprintf(buff, "%dSL%.*f", pAxis->axis+1, pAxis->maxDigits, deviceValue); + ret_status = sendOnly(pAxis->pController, buff); + break; + } + case motorAxisPGain: + { + PRINT(pAxis->logParam, ERROR, "MM4000 does not support setting proportional gain\n"); + break; + } + case motorAxisIGain: + { + PRINT(pAxis->logParam, ERROR, "MM4000 does not support setting integral gain\n"); + break; + } + case motorAxisDGain: + { + PRINT(pAxis->logParam, ERROR, "MM4000 does not support setting derivative gain\n"); + break; + } + case motorAxisClosedLoop: + { + PRINT(pAxis->logParam, ERROR, "MM4000 does not support changing closed loop or torque\n"); + break; + } + default: + PRINT(pAxis->logParam, ERROR, "motorAxisSetDouble: unknown function %d\n", function); + break; + } + } + if (ret_status != MOTOR_AXIS_ERROR) status = motorParam->setDouble(pAxis->params, function, value); + return ret_status; +} + +static int motorAxisSetInteger(AXIS_HDL pAxis, motorAxisParam_t function, int value) +{ + int ret_status = MOTOR_AXIS_ERROR; + int status; + + if (pAxis == NULL) return MOTOR_AXIS_ERROR; + + switch (function) { + case motorAxisClosedLoop: + if (value) { + /* The MM4000 only allows turning on and off ALL motors (MO and MF commands), not individual axes */ + /* Don't implement */ + ret_status = MOTOR_AXIS_OK; + } else { + ret_status = MOTOR_AXIS_OK; + } + break; + default: + PRINT(pAxis->logParam, ERROR, "motorAxisSetInteger: unknown function %d\n", function); + break; + } + if (ret_status != MOTOR_AXIS_ERROR) status = motorParam->setInteger(pAxis->params, function, value); + return ret_status; +} + + +static int motorAxisMove(AXIS_HDL pAxis, double position, int relative, + double min_velocity, double max_velocity, double acceleration) +{ + int status; + char buff[100]; + char *moveCommand; + + if (pAxis == NULL) return MOTOR_AXIS_ERROR; + + PRINT(pAxis->logParam, FLOW, "Set card %d, axis %d move to %f, min vel=%f, max_vel=%f, accel=%f\n", + pAxis->card, pAxis->axis, position, min_velocity, max_velocity, acceleration); + + if (relative) { + moveCommand = "PR"; + } else { + moveCommand = "PA"; + } + sprintf(buff, "%dAC%.*f;%dVA%.*f;%d%s%.*f;", + pAxis->axis+1, pAxis->maxDigits, acceleration * pAxis->stepSize, + pAxis->axis+1, pAxis->maxDigits, max_velocity * pAxis->stepSize, + pAxis->axis+1, moveCommand, pAxis->maxDigits, position * pAxis->stepSize); + status = sendOnly(pAxis->pController, buff); + if (status) return MOTOR_AXIS_ERROR; + + /* Send a signal to the poller task which will make it do a poll, and switch to the moving poll rate */ + epicsEventSignal(pAxis->pController->pollEventId); + + return MOTOR_AXIS_OK; +} + +static int motorAxisHome(AXIS_HDL pAxis, double min_velocity, double max_velocity, double acceleration, int forwards) +{ + int status; + char buff[100]; + + if (pAxis == NULL) return MOTOR_AXIS_ERROR; + + PRINT(pAxis->logParam, FLOW, "motorAxisHome: set card %d, axis %d to home\n", + pAxis->card, pAxis->axis); + + sprintf(buff, "%dAC%.*f; %dVA%.*f;%dOR;", + pAxis->axis+1, pAxis->maxDigits, acceleration * pAxis->stepSize, + pAxis->axis+1, pAxis->maxDigits, max_velocity * pAxis->stepSize, + pAxis->axis+1); + status = sendOnly(pAxis->pController, buff); + if (status) return(MOTOR_AXIS_ERROR); + + /* Send a signal to the poller task which will make it do a poll, and switch to the moving poll rate */ + epicsEventSignal(pAxis->pController->pollEventId); + return MOTOR_AXIS_OK; +} + + +static int motorAxisVelocityMove(AXIS_HDL pAxis, double min_velocity, double velocity, double acceleration) +{ + int status; + double position; + + if (pAxis == NULL) return(MOTOR_AXIS_ERROR); + + /* MM4000 does not have a jog command. Simulate with move absolute + * to the appropriate software limit. We can move to MM4000 soft limits. + * If the record soft limits are set tighter than the MM4000 limits + * the record will prevent JOG motion beyond its soft limits + */ + if (velocity >= 0) position = pAxis->highLimit/pAxis->stepSize; + else position = pAxis->lowLimit/pAxis->stepSize; + status = motorAxisMove(pAxis, position, 0, min_velocity, velocity, acceleration); + + return status; +} + +static int motorAxisProfileMove(AXIS_HDL pAxis, int npoints, double positions[], double times[], int relative, int trigger) +{ + return MOTOR_AXIS_ERROR; +} + +static int motorAxisTriggerProfile(AXIS_HDL pAxis) +{ + return MOTOR_AXIS_ERROR; +} + +static int motorAxisStop(AXIS_HDL pAxis, double acceleration) +{ + int status; + char buff[100]; + + if (pAxis == NULL) return MOTOR_AXIS_ERROR; + + PRINT(pAxis->logParam, FLOW, "Set card %d, axis %d to stop with accel=%f\n", + pAxis->card, pAxis->axis, acceleration); + + sprintf(buff, "%dAC%.*f;%dST;", + pAxis->axis+1, pAxis->maxDigits, acceleration * pAxis->stepSize, + pAxis->axis+1); + status = sendOnly(pAxis->pController, buff); + if (status) return MOTOR_AXIS_ERROR; + return MOTOR_AXIS_OK; +} + + +static void MM4000Poller(MM4000Controller *pController) +{ + /* This is the task that polls the MM4000 */ + double timeout; + AXIS_HDL pAxis; + int status; + int i, j; + int axisDone; + int offset; + int anyMoving; + int comStatus; + int forcedFastPolls=0; + char *p, *tokSave; + char statusAllString[100]; + char positionAllString[100]; + char buff[100]; + + timeout = pController->idlePollPeriod; + epicsEventSignal(pController->pollEventId); /* Force on poll at startup */ + + while(1) { + if (timeout != 0.) status = epicsEventWaitWithTimeout(pController->pollEventId, timeout); + else status = epicsEventWait(pController->pollEventId); + if (status == epicsEventWaitOK) { + /* We got an event, rather than a timeout. This is because other software + * knows that an axis should have changed state (started moving, etc.). + * Force a minimum number of fast polls, because the controller status + * might not have changed the first few polls + */ + forcedFastPolls = 10; + } + + anyMoving = 0; + comStatus = sendAndReceive(pController, "MS;", statusAllString, sizeof(statusAllString)); + if (comStatus == 0) comStatus = sendAndReceive(pController, "TP;", + positionAllString, sizeof(positionAllString)); + for (i=0; inumAxes; i++) { + pAxis = &pController->pAxis[i]; + if (!pAxis->mutexId) break; + epicsMutexLock(pAxis->mutexId); + if (comStatus != 0) { + PRINT(pAxis->logParam, ERROR, "MM4000Poller: error reading status=%d\n", comStatus); + motorParam->setInteger(pAxis->params, motorAxisCommError, 1); + } else { + motorParam->setInteger(pAxis->params, motorAxisCommError, 0); + /* + * Parse the status string + * Status string format: 1MSx,2MSy,3MSz,... where x, y and z are the status + * bytes for the motors + */ + offset = pAxis->axis*5 + 3; /* Offset in status string */ + pAxis->axisStatus = statusAllString[offset]; + if (pAxis->axisStatus & MM4000_MOVING) { + axisDone = 0; + anyMoving = 1; + } else { + axisDone = 1; + } + motorParam->setInteger(pAxis->params, motorAxisDone, axisDone); + if (pAxis->axisStatus & MM4000_HOME) { + motorParam->setInteger(pAxis->params, motorAxisHomeSignal, 1); + } else { + motorParam->setInteger(pAxis->params, motorAxisHomeSignal, 0); + } + if (pAxis->axisStatus & MM4000_HIGH_LIMIT) { + motorParam->setInteger(pAxis->params, motorAxisHighHardLimit, 1); + } else { + motorParam->setInteger(pAxis->params, motorAxisHighHardLimit, 0); + } + if (pAxis->axisStatus & MM4000_LOW_LIMIT) { + motorParam->setInteger(pAxis->params, motorAxisLowHardLimit, 1); + } else { + motorParam->setInteger(pAxis->params, motorAxisLowHardLimit, 0); + } + /* + * Parse motor position + * Position string format: 1TP5.012,2TP1.123,3TP-100.567,... + * Skip to substring for this motor, convert to double + */ + + strcpy(buff, positionAllString); + tokSave = NULL; + p = epicsStrtok_r(buff, ",", &tokSave); + for (j=0; j < pAxis->axis; j++) + p = epicsStrtok_r(NULL, ",", &tokSave); + pAxis->currentPosition = atof(p+3); + motorParam->setDouble(pAxis->params, motorAxisPosition, (pAxis->currentPosition/pAxis->stepSize)); + motorParam->setDouble(pAxis->params, motorAxisEncoderPosn, (pAxis->currentPosition/pAxis->stepSize)); + PRINT(pAxis->logParam, IODRIVER, "MM4000Poller: axis %d axisStatus=%x, position=%f\n", + pAxis->axis, pAxis->axisStatus, pAxis->currentPosition); + + /* We would like a way to query the actual velocity, but this is not possible. If we could we could + * set the direction, and Moving flags */ + } + + motorParam->callCallback(pAxis->params); + epicsMutexUnlock(pAxis->mutexId); + + } /* Next axis */ + if (forcedFastPolls > 0) { + timeout = pController->movingPollPeriod; + forcedFastPolls--; + } else if (anyMoving) { + timeout = pController->movingPollPeriod; + } else { + timeout = pController->idlePollPeriod; + } + } /* End while */ +} + +static int motorMM4000LogMsg(void * param, const motorAxisLogMask_t mask, const char *pFormat, ...) +{ + + va_list pvar; + int nchar; + + va_start(pvar, pFormat); + nchar = vfprintf(stdout,pFormat,pvar); + va_end (pvar); + printf("\n"); + return(nchar); +} + + +int MM4000AsynSetup(int num_controllers) /* number of MM4000 controllers in system. */ +{ + + if (num_controllers < 1) { + printf("MM4000Setup, num_controllers must be > 0\n"); + return MOTOR_AXIS_ERROR; + } + numMM4000Controllers = num_controllers; + pMM4000Controller = (MM4000Controller *)calloc(numMM4000Controllers, sizeof(MM4000Controller)); + return MOTOR_AXIS_OK; +} + + +int MM4000AsynConfig(int card, /* Controller number */ + const char *portName, /* asyn port name of serial or GPIB port */ + int asynAddress, /* asyn subaddress for GPIB */ + int numAxes, /* Number of axes this controller supports */ + int movingPollPeriod, /* Time to poll (msec) when an axis is in motion */ + int idlePollPeriod) /* Time to poll (msec) when an axis is idle. 0 for no polling */ + +{ + AXIS_HDL pAxis; + int axis; + MM4000Controller *pController; + char threadName[20]; + int status; + int totalAxes; + int loopState; + int digits; + int modelNum; + char *p, *tokSave; + char inputBuff[BUFFER_SIZE]; + char outputBuff[BUFFER_SIZE]; + + if (numMM4000Controllers < 1) { + printf("MM4000Config: no MM4000 controllers allocated, call MM4000Setup first\n"); + return MOTOR_AXIS_ERROR; + } + if ((card < 0) || (card >= numMM4000Controllers)) { + printf("MM4000Config: card must in range 0 to %d\n", numMM4000Controllers-1); + return MOTOR_AXIS_ERROR; + } + if ((numAxes < 1) || (numAxes > MM4000_MAX_AXES)) { + printf("MM4000Config: numAxes must in range 1 to %d\n", MM4000_MAX_AXES); + return MOTOR_AXIS_ERROR; + } + + pController = &pMM4000Controller[card]; + pController->pAxis = (AXIS_HDL) calloc(numAxes, sizeof(motorAxis)); + pController->numAxes = numAxes; + pController->movingPollPeriod = movingPollPeriod/1000.; + pController->idlePollPeriod = idlePollPeriod/1000.; + + status = pasynOctetSyncIO->connect(portName, asynAddress, &pController->pasynUser, NULL); + + if (status != asynSuccess) { + printf("MM4000AsynConfig: cannot connect to asyn port %s\n", portName); + return MOTOR_AXIS_ERROR; + } + + sendAndReceive(pController, "VE;", inputBuff, sizeof(inputBuff)); + strcpy(pController->firmwareVersion, &inputBuff[2]); /* Skip "VE" */ + + /* Set Motion Master model indicator. */ + p = strstr(pController->firmwareVersion, "MM"); + if (p == NULL) { + printf("MM4000AsynConfig: invalid model = %s\n", pController->firmwareVersion); + return MOTOR_AXIS_ERROR; + } + modelNum = atoi(p+2); + if (modelNum == 4000) + pController->model = MM4000; + else if (modelNum == 4005 || modelNum == 4006) + pController->model = MM4005; + else { + printf("MM4000AsynConfig: invalid model = %s\n", pController->firmwareVersion); + return MOTOR_AXIS_ERROR; + } + + sendAndReceive(pController, "TP;", inputBuff, sizeof(inputBuff)); + + /* The return string will tell us how many axes this controller has */ + for (totalAxes = 0, tokSave = NULL, p = epicsStrtok_r(inputBuff, ",", &tokSave); + p != 0; p = epicsStrtok_r(NULL, ",", &tokSave), totalAxes++) + ; + + if (totalAxes < numAxes) { + printf("MM4000AsynConfig: actual number of axes=%d < numAxes=%d\n", totalAxes, numAxes); + return MOTOR_AXIS_ERROR; + } + + for (axis=0; axispAxis[axis]; + pAxis->pController = pController; + pAxis->card = card; + pAxis->axis = axis; + pAxis->mutexId = epicsMutexMustCreate(); + pAxis->params = motorParam->create(0, MOTOR_AXIS_NUM_PARAMS); + + /* Determine if encoder present based on open/closed loop mode. */ + sprintf(outputBuff, "%dTC", axis+1); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + loopState = atoi(&inputBuff[3]); /* Skip first 3 characters */ + if (loopState != 0) { + pAxis->closedLoop = 1; + } + + /* Determine drive resolution. */ + sprintf(outputBuff, "%dTU", axis+1); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + pAxis->stepSize = atof(&inputBuff[3]); + digits = (int) -log10(pAxis->stepSize) + 2; + if (digits < 1) digits = 1; + pAxis->maxDigits = digits; + + /* Save home preset position. */ + sprintf(outputBuff, "%dXH", axis+1); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + pAxis->homePreset = atof(&inputBuff[3]); + + /* Determine low limit */ + sprintf(outputBuff, "%dTL", axis+1); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + pAxis->lowLimit = atof(&inputBuff[3]); + + /* Determine high limit */ + sprintf(outputBuff, "%dTR", axis+1); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + pAxis->highLimit = atof(&inputBuff[3]); + } + + pController->pollEventId = epicsEventMustCreate(epicsEventEmpty); + + /* Create the poller thread for this controller */ + epicsSnprintf(threadName, sizeof(threadName), "MM4000:%d", card); + epicsThreadCreate(threadName, + epicsThreadPriorityMedium, + epicsThreadGetStackSize(epicsThreadStackMedium), + (EPICSTHREADFUNC) MM4000Poller, (void *) pController); + + return MOTOR_AXIS_OK; +} + +int sendOnly(MM4000Controller *pController, char *outputBuff) +{ + int nRequested=strlen(outputBuff); + int nActual; + asynStatus status; + + status = pasynOctetSyncIO->write(pController->pasynUser, outputBuff, + nRequested, TIMEOUT, &nActual); + if (nActual != nRequested) status = asynError; + if (status != asynSuccess) { + asynPrint(pController->pasynUser, ASYN_TRACE_ERROR, + "drvMM4000Asyn:sendOnly: error sending command %d, sent=%d, status=%d\n", + outputBuff, nActual, status); + } + return(status); +} + + +int sendAndReceive(MM4000Controller *pController, char *outputBuff, char *inputBuff, int inputSize) +{ + int nWriteRequested=strlen(outputBuff); + int nWrite; + int nRead; + int eomReason; + asynStatus status; + + status = pasynOctetSyncIO->writeRead(pController->pasynUser, + outputBuff, nWriteRequested, + inputBuff, inputSize, + TIMEOUT, &nWrite, &nRead, &eomReason); + if (nWrite != nWriteRequested) status = asynError; + if (status != asynSuccess) { + asynPrint(pController->pasynUser, ASYN_TRACE_ERROR, + "drvMM4000Asyn:sendAndReceive error calling writeRead, output=%s status=%d, error=%s\n", + outputBuff, status, pController->pasynUser->errorMessage); + } + return(status); +} + diff --git a/motorApp/NewportSrc/drvMM4000Asyn.h b/motorApp/NewportSrc/drvMM4000Asyn.h new file mode 100644 index 00000000..d2086024 --- /dev/null +++ b/motorApp/NewportSrc/drvMM4000Asyn.h @@ -0,0 +1,20 @@ +#ifndef DRV_MOTOR_MM4000_ASYN_H +#define DRV_MOTOR_MM4000_ASYN_H + +#ifdef __cplusplus +extern "C" { +#endif + +int MM4000AsynSetup(int numControllers); /* number of XPS controllers in system. */ + +int MM4000AsynConfig(int card, /* Controller number */ + const char *portName, /* asyn port name of serial or GPIB port */ + int asynAddress, /* asyn subaddress for GPIB */ + int numAxes, /* Number of axes this controller supports */ + int movingPollPeriod, /* Time to poll (msec) when an axis is in motion */ + int idlePollPeriod); /* Time to poll (msec) when an axis is idle. 0 for no polling */ + +#ifdef __cplusplus +} +#endif +#endif