Files
motorBase/motorApp/OmsAsynSrc/omsMAXvEncFunc.cpp
T

224 lines
10 KiB
C++

/*
FILENAME... omsMAXvEncFunc.cpp
USAGE... Pro-Dex OMS MAXv encoder asyn motor support
Version: $Revision$
Modified By: $Author$
Last Modified: $Date$
HeadURL: $URL$
*/
/*
* Created on: 10/2011
* Author: eden
*/
#include <string.h>
#include <stdio.h>
#include "omsMAXvEncFunc.h"
static const char *driverName = "omsMAXvEncFuncDriver";
#ifdef __GNUG__
#ifdef DEBUG
#define Debug(l, f, args...) {if (l <= motorMAXvEncFuncdebug) \
errlogPrintf(f, ## args);}
#else
#define Debug(l, f, args...)
#endif
#else
#define Debug
#endif
volatile int motorMAXvEncFuncdebug = 0;
extern "C" {epicsExportAddress(int, motorMAXvEncFuncdebug);}
/* define additional Parameters to use special encoder functions and auxiliary encoders of the MAXv */
#define NUM_ADDITIONALPARAMS 18
#define motorEncoderFunctionString "ENCODER_FUNCTION"
#define motorAuxEncoderPositionString "AUX_ENC_POSITION"
#define motorEncoderRawPosString "RAW_ENC_POSITION"
omsMAXvEncFunc::omsMAXvEncFunc(const char* portName, int numAxes, int cardNo,
const char* initString, int priority, int stackSize)
: omsMAXv(portName, numAxes, cardNo, initString, priority, stackSize, NUM_ADDITIONALPARAMS)
{
initialize();
}
omsMAXvEncFunc::omsMAXvEncFunc(const char* portName, int numAxes, int cardNo, const char* initString, int priority,
int stackSize, unsigned int vmeAddr, int vector, int intlevel, const char* addressType)
: omsMAXv(portName, numAxes, cardNo, initString, priority, stackSize, vmeAddr,
vector, intlevel, addressType, NUM_ADDITIONALPARAMS)
{
initialize();
}
void omsMAXvEncFunc::initialize()
{
const char* functionName = "initialize";
Debug(5, "omsMAXvEncFunc::initialize: start initialize\n" );
int encIndex = numAxes;
if (encIndex > MAXENCFUNC) encIndex = MAXENCFUNC;
/* auxiliary encoders */
for (int i=0; i < encIndex; ++i){
if (createParam(i, motorEncoderFunctionString, asynParamInt32, &encFuncIndex[i]) != asynSuccess)
errlogPrintf("%s:%s:%s: unable to create param motorEncoderFunctionString, index %d\n",
driverName, functionName, portName, i);
if (createParam(i, motorEncoderRawPosString, asynParamFloat64, &encRawPosIndex[i]) != asynSuccess)
errlogPrintf("%s:%s:%s: unable to create param motorEncoderRawPosString, index %d\n",
driverName, functionName, portName, i);
}
createParam(0, motorAuxEncoderPositionString, asynParamFloat64, &encPosIndex[0]);
createParam(1, motorAuxEncoderPositionString, asynParamFloat64, &encPosIndex[1]);
Debug(3, "omsMAXvEncFunc::initialize: auxiliary encoder 0 position index %d\n", encPosIndex[0] );
Debug(3, "omsMAXvEncFunc::initialize: auxiliary encoder 1 position index %d\n", encPosIndex[1] );
for (int i=0; i < encIndex; ++i) Debug(3, "omsMAXvEncFunc::initialize: encFuncIndex %d => %d\n", i, encFuncIndex[i] );
lock();
for (int i=0; i < encIndex; ++i){
setIntegerParam(i, encFuncIndex[i], 0);
setDoubleParam(i, encRawPosIndex[i], 0.0);
}
setDoubleParam(0, encPosIndex[0], 0.0);
setDoubleParam(1, encPosIndex[1], 0.0);
for (int i=0; i < encIndex; ++i) {
callParamCallbacks(i, i);
}
unlock();
}
asynStatus omsMAXvEncFunc::writeInt32(asynUser *pasynUser, epicsInt32 value)
{
int function = pasynUser->reason;
asynStatus status = asynSuccess;
omsBaseAxis *pAxis = (omsBaseAxis *)this->getAxis(pasynUser);
static const char *functionName = "writeInt32";
if ((pAxis->getAxis() < MAXENCFUNC) && (function == encFuncIndex[pAxis->getAxis()])) {
Debug(5, "omsMAXvEncFunc::writeInt32: set average axis %d with axis: %d\n", pAxis->getAxis(), value );
if ((value >= 0) && (value < MAXENCFUNC)) averageChannel [pAxis->getAxis()] = value;
asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
"%s:%s: function=%d, value=%d\n",
driverName, functionName, function, value);
}
else {
status=omsMAXv::writeInt32(pasynUser, value);
}
return status;
}
/**
* overrides the base class to add encoder functions and auxiliary encoders
* for now we assume the function is average and averageChannel contains the
* number of the other encoder to compute the average.
*/
asynStatus omsMAXvEncFunc::getEncoderPositions(epicsInt32 encPosArr[OMS_MAX_AXES])
{
// const char* functionName = "getEncoderPositions";
asynStatus status = asynSuccess;
double position;
omsBaseController::getEncoderPositions(encPosArr);
for (int i=0; i < OMS_MAX_AXES; ++i) {
if ((i < MAXENCFUNC) && (averageChannel[i] != i) && (averageChannel[i] > 0) && (averageChannel[i] < OMS_MAX_AXES)){
position = (double) encPosArr[i];
encPosArr[i] = (int) (((double)(encPosArr[averageChannel[i]]) + position)/2.0);
lock();
setDoubleParam(i, encRawPosIndex[i], position);
setDoubleParam(averageChannel[i], encRawPosIndex[averageChannel[i]], (double)encPosArr[averageChannel[i]]);
unlock();
Debug(9, "omsMAXvEncFunc::getEncPos: axis %d other: %d, old: %g, new: %d, other: %d \n", i, averageChannel[i], position, encPosArr[i], encPosArr[averageChannel[i]] );
}
}
return status;
}
extern "C" int omsMAXvEncFuncConfig(
int cardNo, /* card no, starts with 0*/
const char *portName, /* MAXv Motor Asyn Port name */
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 */
const char *initString) /* Init String sent to card */
{
omsMAXvEncFunc *pController = new omsMAXvEncFunc(portName, numAxes, cardNo, initString, 0, 0);
pController->startPoller((double)movingPollPeriod, (double)idlePollPeriod, 10);
return 0;
}
/*
* extended MAXv configuration, which may be used instead of omsMAXvEncFuncConfig,
* if more details need to be specified.
* omsMAXvEncFuncConfig2 does not need and ignores omsMAXvSetup
*/
extern "C" int omsMAXvEncFuncConfig2(
int slotNo, /* VME slot no of MAXv card*/
const char* addr_type, /* VME address type; "A16", "A24" or "A32" */
unsigned int addrs, /* Board Address */
unsigned int vector, /* Interrupt Vector: noninterrupting(0), (64-255) */
int int_level, /* interrupt level (1-6) */
const char *portName, /* MAXv Motor Asyn Port name */
int numAxes, /* Number of axes this controller supports */
int priority, /* priority of PollerTask (0 => epicsThreadPriorityMedium)*/
int stackSize, /* stackSize of PollerTask (0 => epicsThreadStackMedium) */
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 */
const char *initString) /* Init String sent to card */
{
omsMAXvEncFunc *pController = new omsMAXvEncFunc(portName, numAxes, slotNo, initString, priority,
stackSize, addrs, vector, int_level, addr_type);
pController->startPoller((double)movingPollPeriod, (double)idlePollPeriod, 10);
return 0;
}
/* Code for iocsh registration */
/* omsMAXvEncFuncConfig */
static const iocshArg configArg0 = {"number of card", iocshArgInt};
static const iocshArg configArg1 = {"asyn motor port name", iocshArgString};
static const iocshArg configArg2 = {"number of axes", iocshArgInt};
static const iocshArg configArg3 = {"moving poll rate", iocshArgInt};
static const iocshArg configArg4 = {"idle poll rate", iocshArgInt};
static const iocshArg configArg5 = {"initstring", iocshArgString};
static const iocshArg * const configArgs[6] = {&configArg0, &configArg1, &configArg2,
&configArg3, &configArg4, &configArg5 };
static const iocshFuncDef configMAXv = {"omsMAXvEncFuncConfig", 6, configArgs};
static void configMAXvCallFunc(const iocshArgBuf *args)
{
omsMAXvEncFuncConfig(args[0].ival, args[1].sval, args[2].ival, args[3].ival, args[4].ival, args[5].sval);
}
/* omsMAXvEncFuncConfig2 */
static const iocshArg config2Arg0 = {"Slot number", iocshArgInt};
static const iocshArg config2Arg1 = {"Address type: A16,A24,A32", iocshArgString};
static const iocshArg config2Arg2 = {"Board Address on 4K (0x1000) boundary", iocshArgInt};
static const iocshArg config2Arg3 = {"Interrupt Vector: noninterrupting(0), (64-255)", iocshArgInt};
static const iocshArg config2Arg4 = {"Interrupt level (1-6)", iocshArgInt};
static const iocshArg config2Arg5 = {"Asyn motor port name", iocshArgString};
static const iocshArg config2Arg6 = {"Number of axes", iocshArgInt};
static const iocshArg config2Arg7 = {"Task priority: 0 => medium", iocshArgInt};
static const iocshArg config2Arg8 = {"Stack size: 0 => medium", iocshArgInt};
static const iocshArg config2Arg9 = {"Moving poll rate", iocshArgInt};
static const iocshArg config2Arg10 = {"Idle poll rate", iocshArgInt};
static const iocshArg config2Arg11 = {"Initstring", iocshArgString};
static const iocshArg * const config2Args[12] = {&config2Arg0, &config2Arg1, &config2Arg2, &config2Arg3, &config2Arg4,
&config2Arg5, &config2Arg6, &config2Arg7, &config2Arg8, &config2Arg9, &config2Arg10, &config2Arg11};
static const iocshFuncDef config2MAXv = {"omsMAXvEncFuncConfig2", 12, config2Args};
static void config2MAXvCallFunc(const iocshArgBuf *args)
{
omsMAXvEncFuncConfig2(args[0].ival, args[1].sval, args[2].ival, args[3].ival, args[4].ival, args[5].sval,
args[6].ival, args[7].ival, args[8].ival, args[9].ival, args[10].ival, args[11].sval);
}
static void omsMAXvEncFuncAsynRegister(void)
{
iocshRegister(&configMAXv, configMAXvCallFunc);
iocshRegister(&config2MAXv, config2MAXvCallFunc);
}
epicsExportRegistrar(omsMAXvEncFuncAsynRegister);