Removed OmsAsynSrc; Added motorOmsAsyn submodule

This commit is contained in:
kpetersn
2019-04-10 15:11:11 -05:00
parent 4fd59be3c4
commit 09fd304443
19 changed files with 5 additions and 3196 deletions
+3
View File
@@ -61,3 +61,6 @@
[submodule "modules/motorIms"]
path = modules/motorIms
url = https://github.com/epics-motor/motorIms.git
[submodule "modules/motorOmsAsyn"]
path = modules/motorOmsAsyn
url = https://github.com/epics-motor/motorOmsAsyn.git
+1
View File
@@ -21,6 +21,7 @@ SUBMODULES += motorMicroMo
SUBMODULES += motorMicronix
SUBMODULES += motorNewFocus
SUBMODULES += motorNPoint
SUBMODULES += motorOmsAsyn
SUBMODULES += motorOriel
SUBMODULES += motorPiJena
SUBMODULES += motorPi
-20
View File
@@ -1,20 +0,0 @@
#
record(stringout,"$(type):$(host)$(subAddr)omsSend") {
field(DESC, "Oms String Send")
field(DTYP, "asynOctetWrite")
field(OUT, "@asyn($(asynPort),0,1)OMS_STRING_SEND")
}
record(stringout,"$(type):$(host)$(subAddr)omsSendRecv") {
field(DESC, "Oms String Send Receive")
field(DTYP, "asynOctetWrite")
field(OUT, "@asyn($(asynPort),0,1)OMS_STRING_SENDRECV")
}
record(stringin,"$(type):$(host)$(subAddr)omsRecv") {
field(DESC, "Oms String Receive")
field(DTYP, "asynOctetRead")
field(INP, "@asyn($(asynPort),0,1)OMS_STRING_RECV")
field(SCAN, "I/O Intr")
}
-3
View File
@@ -15,9 +15,6 @@ SoftMotorSrc_DEPEND_DIRS = MotorSrc
# All the following modules require ASYN.
ifdef ASYN
DIRS += OmsAsynSrc
OmsAsynSrc_DEPEND_DIRS = MotorSrc
DIRS += MotorSimSrc
MotorSimSrc_DEPEND_DIRS = MotorSrc
-26
View File
@@ -1,26 +0,0 @@
# Makefile
TOP = ../..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
#
#USR_CXXFLAGS += -DDEBUG
DBD += omsAsynSupport.dbd
LIBRARY_IOC_DEFAULT += omsAsyn
SRCS += omsBaseAxis.cpp
SRCS += omsBaseController.cpp
SRCS += omsMAXnet.cpp
SRCS += omsMAXv.cpp
#SRCS += omsMAXvEncFunc.cpp
omsAsyn_LIBS += motor
omsAsyn_LIBS += asyn
omsAsyn_LIBS += $(EPICS_BASE_IOC_LIBS)
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE
-31
View File
@@ -1,31 +0,0 @@
Please note:
- The MAXnet IP-stack is very basic. It doesn't know anything about routing,
which means, you can only use it from hosts in the same subnet.
If IP packets get lost, the controller will ignore retransmission requests and
the connection will not recover. The driver tries to reset the connection in this case.
It is recommended to operate the controller in a separate network.
- MAXnet cards with firmware versions older than 1.33.4 shouldn't be used
with the ethernet port. They abort communication, if they detect a tcp packet
with checksum 0xffff.
- Input EOS defaults to "\n\r", output EOS defaults to "\n".
Since this may not fit every combination of firmware version and serial/IP selection,
it can be set by calling asynOctetSet[In|Out]putEos prior to calling omsMAXnetConfig()
add this to st.cmd if using the ethernet port:
drvAsynIPPortConfigure("MAXNET","maxnet-ip-address:23",0,0,0)
add this to st.cmd if using the serial port:
drvAsynSerialPortConfigure("MAXNET","/your/serial/device",0,0,0)
asynSetOption("MAXNET",0,"baud","115200")
asynSetOption("MAXNET",0,"bits","8")
asynSetOption("MAXNET",0,"parity","none")
asynSetOption("MAXNET",0,"crtscts","Y")
set the input/output EOS based on the MAXnet firmware version:
### Uncomment one of the following two lines:
#asynOctetSetInputEos("MAXNET",0,"\n\r")
#asynOctetSetInputEos("MAXNET",0,"\n")
asynOctetSetOutputEos("MAXNET",0,"\n")
-53
View File
@@ -1,53 +0,0 @@
To build for the MAXv, you will need omsBase and omsMAXv and you may
comment out omsMaxnet and omsMAXvEncFunc in the Makefile.
omsMAXvEncFunc is derived from omsMAXv and uses a very specific feature
(two encoders for one motor), which might not be of interest for anybody else.
It is possible to mix the older (drvMAXv) driver and this driver in the
same IOCs if you have more than one card.
There are two alternatives to configure the driver in the startup script
1. "traditional"
omsMAXvSetup(1, 16, 0x0000, 190, 5, 10)
omsMAXvConfig(a,b,c,d,e,f)
a: "number of card"
b: "asyn motor port name"
c: "number of axes"
d: "moving poll rate"
e: "idle poll rate"
f: "initstring"
e.g.
omsMAXvSetup(1, 16, 0x0000, 190, 5, 10)
MAXvConfig(0,"MAXv0", 8, 100, 500, "AX LH PSO;")
2. "new"
if you need more flexibility (nonconsecutive board addresses possible) use this
command once for every card:
omsMAXvConfig2(a,b,c,d,e,f,g,h,i,j,k,l)
a "Slot number", any unique number for this card, e.g. use the VME slot number
b "Address type: A16,A24,A32" (string)
c "Board Address on 4K (0x1000) boundary"
d "Interrupt Vector: noninterrupting(0), (64-255)"
e "Interrupt level (1-6)"
f "Asyn motor port name"
g "Number of axes"
h "Task priority: 0 => medium"
i "Stack size: 0 => medium"
j "Moving poll rate"
k "Idle poll rate"
l "Initstring"
e.g.
omsMAXvConfig2(2, "A16", 0x1000, 191, 5, "MAXv2", 8, 0, 0, 100, 500, "AX LH PSO;")
omsMAXvConfig2(3, "A16", 0x4000, 192, 5, "MAXv3", 8, 0, 0, 100, 500, "AX LH PSO;")
omsMAXvConfig2(4, "A16", 0x6000, 193, 5, "MAXv4", 8, 0, 0, 100, 500, "AX LH PSO;")
It is possible to send command strings to the controller and receive the answer.
Use the omsAsynString.template to generate appropriate PVs in the database.
-9
View File
@@ -1,9 +0,0 @@
registrar(OmsMAXnetAsynRegister)
registrar(OmsMAXvAsynRegister)
#registrar(omsMAXvEncFuncAsynRegister)
#variable(motorMAXvdebug)
#variable(motorOMSBASEdebug)
#variable(motorMAXvEncFuncdebug)
#variable(motorMAXnetdebug)
-243
View File
@@ -1,243 +0,0 @@
/*
FILENAME... omsBaseAxis.cpp
USAGE... Pro-Dex OMS asyn motor base axes support
*/
/*
* Created on: 6/2012
* Author: eden
*
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "omsBaseAxis.h"
#include "omsBaseController.h"
static const char *driverName = "omsBaseAxisDriver";
omsBaseAxis::omsBaseAxis(omsBaseController *pController, int axis, char axisChar)
: asynMotorAxis(pController, axis), axisChar(axisChar)
{
pC_ = pController;
stepper = 1;
invertLimit = 0;
lastminvelo = 0;
encoderRatio = 1.0;
}
asynStatus omsBaseAxis::move(double position, int relative, double min_velocity, double max_velocity, double acceleration)
{
// omsBaseAxis *pAxis = this->getAxis(pasynUser);
static const char *functionName = "moveAxis";
asynStatus status = asynError;
char buff[100];
char encoderPositionResponse[64];
int hasEncoder = 0;
if (pC_->getIntegerParam(axisNo_, pC_->motorStatusHasEncoder_, &hasEncoder) == asynError)
{
return asynError;
}
if (hasEncoder != 0)
{
sprintf(buff, "A%1c;RE;", axisChar);
status = pC_->sendReceiveLock(buff, encoderPositionResponse, 64);
if (status == asynError)
{
return status;
}
int motorPosition = static_cast<int>(atoi(encoderPositionResponse) / encoderRatio);
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
"%s:%s: Set driver %s motor position %d from encoder position %s\n",
driverName, functionName, pC_->portName, motorPosition, encoderPositionResponse);
sprintf(buff, "A%1c;LO%d;", axisChar, motorPosition);
status = pC_->sendOnlyLock(buff);
}
epicsInt32 minvelo, velo, acc, rela, pos;
char *relabs[2] = {(char *) "MA", (char *) "MR"};
if (relative)
rela = 1;
else
rela = 0;
if ( position < 0.0)
pos = (epicsInt32) (position - 0.5);
else
pos = (epicsInt32) (position + 0.5);
if (abs(pos) > 67000000){
asynPrint(pasynUser_, ASYN_TRACE_ERROR,
"%s:%s:%s axis %d position out of range %f\n",
driverName, functionName, pC_->portName, axisNo_, position);
return status;
}
velo = (epicsInt32) (max_velocity + 0.5);
if (velo < 1) velo = 1;
else if (velo > 4000000) velo = 4000000;
minvelo = (epicsInt32) (min_velocity + 0.5);
if (minvelo < 0) minvelo = 0;
else if (minvelo >= velo) minvelo = velo - 1;
acc = abs((epicsInt32) acceleration);
if (acc > 8000000)
acc = 8000000;
else if (acc < 1)
acc = 1;
/* move to the specified position */
if (velo < lastminvelo)
sprintf(buff, "A%1c;AC%d;VB%d;VL%d;%s%d;GO;ID;", axisChar, acc, minvelo, velo, relabs[rela], pos);
else
sprintf(buff, "A%1c;AC%d;VL%d;VB%d;%s%d;GO;ID;", axisChar, acc, velo, minvelo, relabs[rela], pos);
lastminvelo = minvelo;
status = pC_->sendOnlyLock(buff);
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
"%s:%s: Set driver %s, axis %d move to %f, min vel=%f, max_vel=%f, accel=%f\n",
driverName, functionName, pC_->portName, axisNo_, position, min_velocity, max_velocity, acceleration );
return status;
}
asynStatus omsBaseAxis::home(double min_velocity, double max_velocity, double acceleration, int forwards )
{
static const char *functionName = "homeAxis";
asynStatus status = asynError;
char buff[60];
char *direction[2] = {(char*) "HR", (char*) "HM"};
epicsInt32 minvelo, velo, acc, fw = 0;
if (forwards) fw = 1;
velo = (epicsInt32) max_velocity;
if (velo < 1) velo = 1;
else if (velo > 1000000) velo = 1000000;
minvelo = (epicsInt32) (min_velocity + 0.5);
if (minvelo < 0) minvelo = 0;
else if (minvelo >= velo) minvelo = velo - 1;
acc = abs((epicsInt32) acceleration);
if (acc > 8000000)
acc = 8000000;
else if (acc < 1)
acc = 1;
/* do a home run and move to the home position */
if (velo < lastminvelo)
sprintf(buff, "A%1c;AC%d;VB%d;VL%d;%s;MA0;GO;ID;", axisChar, acc, minvelo, velo, direction[forwards]);
else
sprintf(buff, "A%1c;AC%d;VL%d;VB%d;%s;MA0;GO;ID;", axisChar, acc, velo, minvelo, direction[forwards]);
lastminvelo = minvelo;
status = pC_->sendOnlyLock(buff);
homing = 1;
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
"%s:%s: Set driver %s, axis %d to home %s, min vel=%f, max_vel=%f, accel=%f\n",
driverName, functionName, pC_->portName, axisNo_, (forwards?"FORWARDS":"REVERSE"), min_velocity, max_velocity, acceleration );
return status;
}
asynStatus omsBaseAxis::doMoveToHome()
{
static const char *functionName = "doMoveToHome";
asynPrint(pasynUser_, ASYN_TRACE_ERROR,
"%s:%s: This function is not yet implemented for axis %d\n",
driverName, functionName, axisNo_);
return asynError;
}
asynStatus omsBaseAxis::moveVelocity(double minVelocity, double maxVelocity, double acceleration )
{
asynStatus status = asynError;
static const char *functionName = "moveVelocityAxis";
char buff[100];
epicsInt32 velo, acc;
acc = (epicsInt32) acceleration;
if (acc < 1) acc = 1;
else if (acc > 8000000) acc = 8000000;
velo = (epicsInt32) maxVelocity;
if (velo > 4000000) velo = 4000000;
else if (velo < -4000000) velo = -4000000;
sprintf(buff, "A%1c AC%d; JG%d;", axisChar, acc, velo);
status = pC_->sendOnlyLock(buff);
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
"%s:%s: Set port %s, axis %d move with velocity of %f, acceleration=%f",
driverName, functionName, pC_->portName, axisNo_, maxVelocity, acceleration );
/* Send a signal to the poller task which will make it do a poll, and switch to the moving poll rate */
return status;
}
asynStatus omsBaseAxis::stop(double acceleration )
{
asynStatus status = asynError;
static const char *functionName = "stopAxis";
int acc;
char buff[50];
acc = (int)(fabs(acceleration)+0.5);
if (acc > 8000000) acc=8000000;
if (acc < 1) acc = 200000;
sprintf(buff, "A%1c AC%d; ST ID;", axisChar, acc);
status = pC_->sendOnlyLock(buff);
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
"%s:%s: port %s, set axis %d to stop with accel=%f\n",
driverName, functionName, pC_->portName, axisNo_, acceleration );
return status;
}
/** Set the current position of the motor.
* \param[in] position The new absolute motor position that should be set in the hardware. Units=steps.
*/
asynStatus omsBaseAxis::setPosition(double position)
{
static const char *functionName = "setPosition";
asynStatus status = asynError;
char buff[20];
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
"%s:%s:%s axis %d set position to %f\n",
driverName, functionName, pC_->portName, axisNo_, position);
sprintf(buff,"A%1c LP%d;", axisChar, (int)(position));
status = pC_->sendOnlyLock(buff);
return status;
}
/** we need to implement this, because we need to use the motorUpdateStatus_ function
* in asynMotorController, because we cannot access statusChanged_ (shouldn't be private)
* ignore moving flag, since we have our own poller.
*/
asynStatus omsBaseAxis::poll(bool *moving)
{
epicsEventSignal(pC_->pollEventId_);
return asynSuccess;
}
-54
View File
@@ -1,54 +0,0 @@
/*
FILENAME... omsBaseAxis.h
USAGE... Pro-Dex OMS asyn motor base axes support
*/
/*
* Created on: 06/2012
* Author: eden
*/
#ifndef OMSBASEAXIS_H_
#define OMSBASEAXIS_H_
#include "asynMotorController.h"
#include "asynMotorAxis.h"
class omsBaseController;
class omsBaseAxis : public asynMotorAxis
{
public:
omsBaseAxis(class omsBaseController *, int, char );
virtual asynStatus move(double position, int relative, double minVelocity, double maxVelocity, double acceleration);
virtual asynStatus moveVelocity(double minVelocity, double maxVelocity, double acceleration);
virtual asynStatus home(double minVelocity, double maxVelocity, double acceleration, int forwards);
virtual asynStatus stop(double acceleration);
virtual asynStatus doMoveToHome();
virtual asynStatus setPosition(double position);
virtual asynStatus poll(bool *moving);
int getAxis(){return axisNo_;}
int isStepper(){return stepper;}
void setStepper(int val){stepper=val;}
int getLimitInvert(){return invertLimit;}
void setLimitInvert(int val){invertLimit=val;}
virtual asynStatus setEncoderRatio(double ratio){encoderRatio=ratio; return asynSuccess;}
int card;
int moveDelay;
char axisChar;
bool homing;
private:
omsBaseController *pC_;
int stepper;
int invertLimit;
epicsInt32 lastminvelo;
double encoderRatio;
friend class omsBaseController;
};
#endif /* OMSBASEAXIS_H_ */
File diff suppressed because it is too large Load Diff
-101
View File
@@ -1,101 +0,0 @@
/*
FILENAME... omsBaseController.h
USAGE... Pro-Dex OMS asyn motor base controller support
*/
/*
* Created on: 06/2012
* Author: eden
*/
#ifndef OMSBASECONTROLLER_H_
#define OMSBASECONTROLLER_H_
#include <epicsTime.h>
#include <epicsThread.h>
#include <epicsString.h>
#include <epicsMutex.h>
#include <ellLib.h>
#include <iocsh.h>
#include <errlog.h>
#include "asynMotorController.h"
#include "omsBaseAxis.h"
#include <epicsExport.h>
#define OMS_MAX_AXES 10
#define OMSBASE_MAXNUMBERLEN 12
#define OMSINPUTBUFFERLEN OMSBASE_MAXNUMBERLEN * OMS_MAX_AXES + 2
class omsBaseController : public asynMotorController {
public:
omsBaseController(const char *portName, int numAxes, int priority, int stackSize, int extMotorParams);
virtual asynStatus readInt32(asynUser *pasynUser, epicsInt32 *value);
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value);
virtual void report(FILE *fp, int level);
virtual asynStatus sendReceive(const char*, char*, unsigned int ) = 0;
virtual asynStatus sendOnly(const char *outputBuff) = 0;
void omsPoller();
virtual asynStatus startPoller(double movingPollPeriod, double idlePollPeriod, int forcedFastPolls);
static void callPoller(void*);
static void callShutdown(void *ptr){((omsBaseController*)ptr)->shutdown();};
void shutdown();
protected:
virtual asynStatus writeOctet(asynUser *, const char *, size_t, size_t *);
virtual asynStatus getFirmwareVersion();
virtual asynStatus Init(const char*, int);
virtual asynStatus sanityCheck();
asynStatus sendReceiveLock(const char*, char*, unsigned int );
asynStatus sendOnlyLock(const char *);
virtual omsBaseAxis* getAxis(asynUser *pasynUser);
virtual omsBaseAxis* getAxis(int);
asynStatus getAxesArray(char*, int positions[OMS_MAX_AXES]);
virtual asynStatus getAxesPositions(int positions[OMS_MAX_AXES]);
virtual asynStatus getAxesStatus(char *, int, bool *);
virtual asynStatus getEncoderPositions(epicsInt32 encPosArr[OMS_MAX_AXES]);
virtual asynStatus getClosedLoopStatus(int clstatus[OMS_MAX_AXES]);
virtual epicsEventWaitStatus waitInterruptible(double timeout);
virtual bool watchdogOK();
virtual bool resetConnection(){return false;};
char* getPortName(){return portName;};
bool firmwareMin(int, int, int);
static omsBaseController* findController(const char*);
static ELLLIST omsControllerList;
static int omsTotalControllerNumber;
char* controllerType;
int fwMajor, fwMinor, fwRevision;
epicsTimeStamp now;
char* portName;
bool useWatchdog;
bool enabled;
int numAxes;
private:
asynStatus sendReplace(omsBaseAxis*, char*);
asynStatus sendReceiveReplace(omsBaseAxis*, char *, char *, int);
asynStatus getSubstring(unsigned int , char* , char *, unsigned int);
int sanityCounter;
epicsThreadId motorThread;
char inputBuffer[OMSINPUTBUFFERLEN];
char pollInputBuffer[OMSINPUTBUFFERLEN];
omsBaseAxis** pAxes;
int controllerNumber;
epicsMutex *baseMutex;
int sendReceiveIndex;
int sendIndex;
int receiveIndex;
int pollIndex;
int priority, stackSize;
friend class omsBaseAxis;
};
typedef struct omsBaseNode {
ELLNODE node;
const char *portName;
omsBaseController* pController;
} omsBaseNode;
#endif /* OMSBASE_H_ */
-395
View File
@@ -1,395 +0,0 @@
/*
FILENAME... omsMAXnet.cpp
USAGE... Pro-Dex OMS MAXnet asyn motor controller support
*/
/*
* Created on: 10/2010
* Author: eden
*/
#include <string.h>
#include "asynOctetSyncIO.h"
#include "omsMAXnet.h"
#ifdef __GNUG__
#ifdef DEBUG
#define Debug(l, f, args...) {if (l & motorMAXnetdebug) \
errlogPrintf(f, ## args);}
#else
#define Debug(l, f, args...)
#endif
#else
#define Debug
#endif
static const char *driverName = "omsMAXnetDriver";
volatile int motorMAXnetdebug = 0;
extern "C" {epicsExportAddress(int, motorMAXnetdebug);}
#define MAXnet_MAX_BUFFERLENGTH 250
static void connectCallback(asynUser *pasynUser, asynException exception)
{
asynStatus status;
int connected = 0;
omsMAXnet* pController = (omsMAXnet*)pasynUser->userPvt;
if (exception == asynExceptionConnect) {
status = pasynManager->isConnected(pasynUser, &connected);
if (connected){
if (motorMAXnetdebug & 8) asynPrint(pasynUser, ASYN_TRACE_FLOW,
"MAXnet connectCallback: TCP-Port connected\n");
pController->portConnected = 1;
}
else {
if (motorMAXnetdebug & 4) asynPrint(pasynUser, ASYN_TRACE_FLOW,
"MAXnet connectCallback: TCP-Port disconnected\n");
pController->portConnected = 0;
}
}
}
void omsMAXnet::asynCallback(void *drvPvt, asynUser *pasynUser, char *data, size_t len, int eomReason)
{
omsMAXnet* pController = (omsMAXnet*)drvPvt;
/* If the string has a "%", it is a notification, increment counter and
* send a signal to the poller task which will trigger a poll */
if ((len >= 1) && (strchr(data, '%') != NULL)){
char* pos = strchr(data, '%');
epicsEventSignal(pController->pollEventId_);
while (pos != NULL){
Debug(2, "omsMAXnet::asynCallback: %s (%d)\n", data, len);
pController->notificationMutex->lock();
++pController->notificationCounter;
pController->notificationMutex->unlock();
++pos;
pos = strchr(pos, '%');
}
}
}
omsMAXnet::omsMAXnet(const char* portName, int numAxes, const char* serialPortName, const char* initString, int priority, int stackSize)
: omsBaseController(portName, numAxes, priority, stackSize, 0){
asynStatus status;
asynInterface *pasynInterface;
controllerType = epicsStrDup("MAXnet");
notificationMutex = new epicsMutex();
notificationCounter = 0;
useWatchdog = true;
char eosstring[5];
int eoslen=0;
serialPortName = epicsStrDup(serialPortName);
pasynUserSerial = pasynManager->createAsynUser(0,0);
pasynUserSerial->userPvt = this;
status = pasynManager->connectDevice(pasynUserSerial,serialPortName,0);
if(status != asynSuccess){
printf("MAXnetConfig: can't connect to port %s: %s\n",serialPortName,pasynUserSerial->errorMessage);
return;
}
status = pasynManager->exceptionCallbackAdd(pasynUserSerial, connectCallback);
if(status != asynSuccess){
printf("MAXnetConfig: can't set exceptionCallback for %s: %s\n",serialPortName,pasynUserSerial->errorMessage);
return;
}
/* set the connect flag */
pasynManager->isConnected(pasynUserSerial, &portConnected);
pasynInterface = pasynManager->findInterface(pasynUserSerial,asynOctetType,1);
if( pasynInterface == NULL) {
printf("MAXnetConfig: %s driver not supported\n", asynOctetType);
return;
}
pasynOctetSerial = (asynOctet*)pasynInterface->pinterface;
octetPvtSerial = pasynInterface->drvPvt;
status = pasynOctetSyncIO->connect(serialPortName, 0, &pasynUserSyncIOSerial, NULL);
if(status != asynSuccess){
printf("MAXnetConfig: can't connect pasynOctetSyncIO %s: %s\n",serialPortName,pasynUserSyncIOSerial->errorMessage);
return;
}
/* flush any junk at input port - should be no data available */
pasynOctetSyncIO->flush(pasynUserSyncIOSerial);
timeout = 2.0;
pasynUserSerial->timeout = 0.0;
// to override default setting, set input and output EOS in st.cmd
if (pasynOctetSyncIO->getInputEos(pasynUserSyncIOSerial, eosstring, 5, &eoslen) == asynSuccess) {
if (eoslen == 0)
if (pasynOctetSyncIO->setInputEos(pasynUserSyncIOSerial, "\n\r", 2) != asynSuccess)
printf("MAXnetConfig: unable to set InputEOS %s: %s\n", serialPortName, pasynUserSyncIOSerial->errorMessage);
}
if (pasynOctetSyncIO->getOutputEos(pasynUserSyncIOSerial, eosstring, 5, &eoslen) == asynSuccess) {
if (eoslen == 0)
if (pasynOctetSyncIO->setOutputEos(pasynUserSyncIOSerial, "\n", 1) != asynSuccess)
printf("MAXnetConfig: unable to set OutputEOS %s: %s\n", serialPortName, pasynUserSyncIOSerial->errorMessage);
}
void* registrarPvt= NULL;
status = pasynOctetSerial->registerInterruptUser(octetPvtSerial, pasynUserSerial, omsMAXnet::asynCallback, this, &registrarPvt);
if(status != asynSuccess) {
printf("MAXnetConfig: registerInterruptUser failed - %s: %s\n",serialPortName,pasynUserSerial->errorMessage);
return;
}
/* get FirmwareVersion */
if(getFirmwareVersion() != asynSuccess) {
printf("MAXnetConfig: unable to talk to controller at %s: %s\n",serialPortName,pasynUserSyncIOSerial->errorMessage);
return;
}
if (fwMinor < 30 ){
printf("This Controllers Firmware Version %d.%d is not supported, version 1.30 or higher is mandatory\n", fwMajor, fwMinor);
}
if( Init(initString, 0) != asynSuccess) {
printf("MAXnetConfig: unable to talk to controller at %s: %s\n",serialPortName,pasynUserSyncIOSerial->errorMessage);
return;
}
}
// poll the serial port for notification messages while waiting
epicsEventWaitStatus omsMAXnet::waitInterruptible(double timeout)
{
double pollWait, timeToWait = timeout;
asynStatus status;
size_t nRead;
char inputBuff[1];
int eomReason = 0;
epicsTimeStamp starttime;
epicsEventWaitStatus waitStatus = epicsEventWaitTimeout;
epicsTimeGetCurrent(&starttime);
if (timeout == idlePollPeriod_)
pollWait = idlePollPeriod_ / 5.0;
else
pollWait = movingPollPeriod_ / 20.0;
pasynManager->lockPort(pasynUserSerial);
pasynOctetSerial->flush(octetPvtSerial, pasynUserSerial);
pasynManager->unlockPort(pasynUserSerial);
while ( timeToWait > 0){
/* reading with bufferlength 0 and timeout 0.0 triggers a callback and
* poll event, if a notification is outstanding. One character will be read. */
if (enabled) {
pasynManager->lockPort(pasynUserSerial);
status = pasynOctetSerial->read(octetPvtSerial, pasynUserSerial, inputBuff,
0, &nRead, &eomReason);
pasynManager->unlockPort(pasynUserSerial);
}
if (epicsEventWaitWithTimeout(pollEventId_, pollWait) == epicsEventWaitOK) {
waitStatus = epicsEventWaitOK;
break;
}
epicsTimeGetCurrent(&now);
timeToWait = timeout - epicsTimeDiffInSeconds(&now, &starttime);
}
return waitStatus;
}
asynStatus omsMAXnet::sendOnly(const char *outputBuff)
{
size_t nActual = 0;
asynStatus status;
if (!enabled) return asynError;
status = pasynOctetSyncIO->write(pasynUserSyncIOSerial, outputBuff,
strlen(outputBuff), timeout, &nActual);
if (status != asynSuccess) {
asynPrint(pasynUserSyncIOSerial, ASYN_TRACE_ERROR,
"drvMAXnetAsyn:sendOnly: error sending command %s, sent=%d, status=%d\n",
outputBuff, nActual, status);
}
Debug(4, "omsMAXnet::sendOnly: wrote: %s \n", outputBuff);
return(status);
}
asynStatus omsMAXnet::sendReceive(const char *outputBuff, char *inputBuff, unsigned int inputSize)
{
char localBuffer[MAXnet_MAX_BUFFERLENGTH + 1] = "";
size_t nRead=0, nReadnext=0, nWrite=0;
size_t bufferSize = MAXnet_MAX_BUFFERLENGTH;
int eomReason = 0;
asynStatus status = asynSuccess;
char *outString = localBuffer;
int errorCount = 10;
if (!enabled) return asynError;
/*
* read the notification from input buffer
*/
while ((notificationCounter > 0) && errorCount){
status = pasynOctetSyncIO->read(pasynUserSyncIOSerial, localBuffer, bufferSize, 0.001, &nRead, &eomReason);
while ((status == asynSuccess) && !(eomReason & ASYN_EOM_EOS)) {
status = pasynOctetSyncIO->read(pasynUserSyncIOSerial, localBuffer+nRead,
bufferSize-nRead, timeout, &nReadnext, &eomReason);
nRead += nReadnext;
}
localBuffer[nRead] = '\0';
outString = localBuffer;
while (*outString == 6) ++outString;
if (status == asynSuccess) {
if (isNotification(outString) && (notificationCounter > 0)) {
--notificationCounter;
}
}
else if (status == asynTimeout) {
notificationCounter = 0;
}
else {
--errorCount;
}
}
Debug(4, "omsMAXnet::sendReceive: write: %s \n", outputBuff);
nRead=0;
nReadnext=0;
status = pasynOctetSyncIO->writeRead(pasynUserSyncIOSerial, outputBuff, strlen(outputBuff), localBuffer,
bufferSize, timeout, &nWrite, &nRead, &eomReason);
while ((status == asynSuccess) && !(eomReason & ASYN_EOM_EOS)) {
status = pasynOctetSyncIO->read(pasynUserSyncIOSerial, localBuffer+nRead,
bufferSize-nRead, timeout, &nReadnext, &eomReason);
nRead += nReadnext;
}
localBuffer[nRead] = '\0';
// cut off a leading CR, NL, /006
outString = localBuffer;
while ((*outString == 6)||(*outString == 13)||(*outString == 10)) ++outString;
// if input data is a notification read until expected data arrived
while ((status == asynSuccess) && isNotification(outString)) {
nRead=0;
nReadnext=0;
status = pasynOctetSyncIO->read(pasynUserSyncIOSerial, localBuffer,
bufferSize, timeout, &nRead, &eomReason);
while ((status == asynSuccess) && !(eomReason & ASYN_EOM_EOS)) {
status = pasynOctetSyncIO->read(pasynUserSyncIOSerial, localBuffer+nRead,
bufferSize-nRead, timeout, &nReadnext, &eomReason);
nRead += nReadnext;
}
localBuffer[nRead] = '\0';
// cut off a leading CR, NL, /006
outString = localBuffer;
while ((*outString == 6)||(*outString == 13)||(*outString == 10)) ++outString;
if (notificationCounter > 0) --notificationCounter;
}
// copy into inputBuffer
strncpy(inputBuff, outString, inputSize);
inputBuff[inputSize-1] = '\0';
Debug(4, "omsMAXnet::sendReceive: read: %s \n", inputBuff);
return status;
}
/*
* check if buffer is a notification messages with 13 chars ("%000 SSSSSSSS")
* (first character may miss
*/
int omsMAXnet::isNotification (char *buffer) {
const char* functionName="isNotification";
char *inString;
if ((inString = strstr(buffer, "000 0")) != NULL){
if ((inString = strstr(buffer, "000 01")) != NULL){
printf("%s:%s:%s: CMD_ERR_FLAG received\n", driverName, functionName, portName);
}
else {
Debug(2,"%s:%s:%s: Interrupt notification: %s\n",
driverName, functionName, portName, buffer);
epicsEventSignal(pollEventId_);
}
return 1;
}
else
return 0;
}
/*
* disconnect and reconnect the serial / IP connection
*/
bool omsMAXnet::resetConnection(){
asynStatus status;
int autoConnect;
asynInterface *pasynInterface = pasynManager->findInterface(pasynUserSerial,asynCommonType,1);
if( pasynInterface == NULL) return false;
asynCommon* pasynCommonIntf = (asynCommon*)pasynInterface->pinterface;
pasynManager->isAutoConnect(pasynUserSerial, &autoConnect);
errlogPrintf("*** disconnect and reconnect serial/IP connection ****\n");
status = pasynCommonIntf->disconnect(pasynInterface->drvPvt, pasynUserSerial);
if (!autoConnect) status = pasynCommonIntf->connect(pasynInterface->drvPvt, pasynUserSerial);
epicsThreadSleep(0.1);
if (portConnected) errlogPrintf("*** reconnect done ****\n");
return true;
}
extern "C" int omsMAXnetConfig(
const char *portName, /* MAXnet Motor Asyn Port name */
int numAxes, /* Number of axes this controller supports */
const char *serialPortName,/* MAXnet Serial Asyn Port name */
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 */
{
// for now priority and stacksize are hardcoded here, should they be configurable in omsMAXnetConfig?
int priority = epicsThreadPriorityMedium;
int stackSize = epicsThreadGetStackSize(epicsThreadStackMedium);
omsMAXnet *pController = new omsMAXnet(portName, numAxes, serialPortName, initString, priority, stackSize);
pController->startPoller((double)movingPollPeriod, (double)idlePollPeriod, 10);
return(asynSuccess);
}
/* Code for iocsh registration */
extern "C"
{
/* omsMAXnetConfig */
static const iocshArg omsMAXnetConfigArg0 = {"asyn motor port name", iocshArgString};
static const iocshArg omsMAXnetConfigArg1 = {"number of axes", iocshArgInt};
static const iocshArg omsMAXnetConfigArg2 = {"asyn serial/tcp port name", iocshArgString};
static const iocshArg omsMAXnetConfigArg3 = {"moving poll rate", iocshArgInt};
static const iocshArg omsMAXnetConfigArg4 = {"idle poll rate", iocshArgInt};
static const iocshArg omsMAXnetConfigArg5 = {"initstring", iocshArgString};
static const iocshArg * const omsMAXnetConfigArgs[6] = {&omsMAXnetConfigArg0,
&omsMAXnetConfigArg1,
&omsMAXnetConfigArg2,
&omsMAXnetConfigArg3,
&omsMAXnetConfigArg4,
&omsMAXnetConfigArg5 };
static const iocshFuncDef configOmsMAXnet = {"omsMAXnetConfig", 6, omsMAXnetConfigArgs};
static void configOmsMAXnetCallFunc(const iocshArgBuf *args)
{
omsMAXnetConfig(args[0].sval, args[1].ival, args[2].sval, args[3].ival, args[4].ival, args[5].sval);
}
static void OmsMAXnetAsynRegister(void)
{
iocshRegister(&configOmsMAXnet, configOmsMAXnetCallFunc);
}
epicsExportRegistrar(OmsMAXnetAsynRegister);
}
-39
View File
@@ -1,39 +0,0 @@
/*
FILENAME... omsMAXnet.h
USAGE... Pro-Dex OMS MAXnet asyn motor controller support
*/
/*
* Created on: 10/2010
* Author: eden
*/
#ifndef OMSMAXNET_H_
#define OMSMAXNET_H_
#include "omsBaseController.h"
class omsMAXnet : public omsBaseController {
public:
omsMAXnet(const char* , int , const char*, const char*, int , int );
static void asynCallback(void*, asynUser*, char *, size_t, int);
int portConnected;
int notificationCounter;
epicsMutex* notificationMutex;
epicsEventWaitStatus waitInterruptible(double);
asynStatus sendReceive(const char *, char *, unsigned int );
asynStatus sendOnly(const char *);
virtual bool resetConnection();
private:
int isNotification (char *);
asynUser* pasynUserSerial;
asynUser* pasynUserSyncIOSerial;
asynOctet *pasynOctetSerial;
void* octetPvtSerial;
char* serialPortName;
double timeout;
};
#endif /* OMSMAXNET_H_ */
-656
View File
@@ -1,656 +0,0 @@
/*
FILENAME... omsMAXv.cpp
USAGE... Pro-Dex OMS MAXv asyn motor controller support
*/
/*
* based on drvMAXv.cc written by Ron Sluiter
*
* Created on: 10/2010
* Author: eden
*/
#include <string.h>
#include <stdio.h>
#include "asynOctetSyncIO.h"
#include <epicsInterrupt.h>
#include <epicsExit.h>
#include "omsMAXv.h"
static const char *driverName = "omsMAXvAsyn";
#define MIN(a,b) ((a)<(b)? (a): (b))
#ifdef __GNUG__
#ifdef DEBUG
#define Debug(l, f, args...) {if (l & motorMAXvdebug) \
errlogPrintf(f, ## args);}
#else
#define Debug(l, f, args...)
#endif
#else
#define Debug
#endif
volatile int motorMAXvdebug = 0;
extern "C" {epicsExportAddress(int, motorMAXvdebug);}
char* omsMAXv::baseAddress = 0x0;
int omsMAXv::numCards = 0;
epicsUInt32 omsMAXv::baseInterruptVector = OMS_INT_VECTOR;
epicsUInt8 omsMAXv::interruptLevel = OMS_INT_LEVEL;
epicsAddressType omsMAXv::addrType = atVMEA16;
void omsMAXv::InterruptHandler( void * param )
{
omsMAXv* pController = (omsMAXv*) param;
volatile struct MAXv_motor *pmotor = (MAXv_motor*) pController->getCardAddress();;
STATUS1 status1_flag;
static char errmsg[65];
status1_flag.All = pmotor->status1_flag.All;
/* Motion done handling */
if (status1_flag.Bits.done != 0) epicsEventSignal(pController->pollEventId_);
if (status1_flag.Bits.cmndError)
{
strcpy(errmsg, "\nomsMAXv::InterruptHandler: command error - Port: ");
strncat(errmsg, pController->getPortName(), sizeof(errmsg)-strlen(errmsg)-2);
strcat(errmsg,"\n");
epicsInterruptContextMessage(errmsg);
}
/* unset this bit to not clear the text_response bit */
if (status1_flag.Bits.text_response != 0) status1_flag.Bits.text_response = 0;
/* Release IRQ's. Clear bits by writing a 1 */
pmotor->status1_flag.All = status1_flag.All;
/* do a dummy read to ensure that all previous writes, which may
* have been queued in the VME bridge chip get processed
*/
status1_flag.All = pmotor->status1_flag.All;
}
omsMAXv::omsMAXv(const char* portName, int numAxes, int cardNo, const char* initString,
int priority, int stackSize, int addParams)
: omsBaseController(portName, numAxes, priority, stackSize, addParams)
{
int vector = 0;
if (baseInterruptVector != 0)
vector = baseInterruptVector + cardNo;
initialize(portName, numAxes, cardNo, initString, priority, stackSize, 1, vector, interruptLevel, addrType, addParams);
}
omsMAXv::omsMAXv(const char* portName, int numAxes, int slotNo, const char* initString, int priority,
int stackSize, unsigned int vmeAddr, int vector, int intlevel, const char* addressType, int addParams)
: omsBaseController(portName, numAxes, priority, stackSize, addParams)
{
const char* functionName = "omsMAXv";
epicsAddressType vmeAddrType = atVMEA16;
if (vmeAddr < 0) {
errlogPrintf("%s: invalid VME address: 0\n", functionName);
return;
}
if (!strncmp(addressType, "A16",3)){
vmeAddrType = atVMEA16;
if (vmeAddr & 0xFFFF0FFF) {
errlogPrintf("%s: invalid %s address: 0x%X.\n", functionName, addressType, vmeAddr);
return;
}
}
else if (!strncmp(addressType, "A24",3)){
vmeAddrType = atVMEA24;
if (vmeAddr & 0xFF00FFFF) {
errlogPrintf("%s: invalid %s address: 0x%X.\n", functionName, addressType, vmeAddr);
return;
}
}
else if (!strncmp(addressType, "A32",3)){
vmeAddrType = atVMEA32;
if (vmeAddr & 0x00FFFFFF) {
errlogPrintf("%s: invalid %s address: 0x%X.\n", functionName, addressType, vmeAddr);
return;
}
}
else if (strncmp(addressType, "CSR",3)){
errlogPrintf("%s: VME CSR not supported\n", functionName);
return;
}
else {
errlogPrintf("%s: invalid address type, Please specify one of A16,A24,A32\n", functionName);
}
if (intlevel < 1 || intlevel > 6) {
errlogPrintf("%s: invalid interrupt level %d, Please specify a value between 1 and 6\n", functionName, intlevel);
return;
}
initialize(portName, numAxes, 0, initString, priority, stackSize, vmeAddr, vector, intlevel, vmeAddrType, addParams);
}
void omsMAXv::initialize(const char* portName, int numAxes, int cardNo, const char* initString, int prio,
int stackSz, unsigned int vmeAddr, int intrVector, int level, epicsAddressType vmeAddrType, int paramCount)
{
const char* functionName = "initialize";
long status;
void* probeAddr;
Debug(32, "omsMAXv::initialize: start initialize\n" );
controllerType = epicsStrDup("MAXv");
// TODO check if cardNo has already been used
this->cardNo = cardNo;
if(cardNo < 0 || cardNo >= MAXv_NUM_CARDS){
printf("invalid cardNo: %d", cardNo);
return;
}
epicsUInt8 *startAddr;
epicsUInt8 *endAddr;
epicsUInt32 boardAddrSize = 0;
if (vmeAddrType == atVMEA16)
boardAddrSize = 0x1000;
else if (vmeAddrType == atVMEA24)
boardAddrSize = 0x10000;
else if (vmeAddrType == atVMEA32)
boardAddrSize = 0x1000000;
// if vmeAddr == 1 Setup/Config is used and not Config2
if (vmeAddr == 1)
probeAddr = baseAddress + (cardNo * boardAddrSize);
else
probeAddr = (void*) vmeAddr;
startAddr = (epicsUInt8 *) probeAddr;
endAddr = startAddr + boardAddrSize;
Debug(64, "motor_init: devNoResponseProbe() on addr %p\n", probeAddr);
/* Scan memory space to assure card id */
while (startAddr < endAddr) {
status = devNoResponseProbe(vmeAddrType, (size_t) startAddr, 2);
if (status != S_dev_addressOverlap) {
errlogPrintf("%s:%s:%s: Card NOT found in specified address range! \n",
driverName, functionName, portName);
enabled = false;
return;
}
startAddr += (boardAddrSize / 10);
}
status = devRegisterAddress(controllerType, vmeAddrType,
(size_t) probeAddr, boardAddrSize,
(volatile void **) &pmotor);
Debug(64, "motor_init: devRegisterAddress() status = %d\n", (int) status);
if (status) {
errlogPrintf("%s:%s:%s: Can't register address 0x%lx \n",
driverName, functionName, portName, (long unsigned int) probeAddr);
return;
}
Debug(64, "motor_init: pmotor = %p\n", pmotor);
int loopCount=15;
while (loopCount && (pmotor->firmware_status.Bits.initializing == 1)){
Debug(1, "MAXv port %s still initializing; status = 0x%x\n",
portName, (unsigned int) pmotor->firmware_status.All);
epicsThreadSleep(0.2);
--loopCount;
}
Debug(64, "motor_init: check if card is ready\n");
if (pmotor->firmware_status.Bits.running == 0)
errlogPrintf("MAXv port %s is NOT running; status = 0x%x\n",
portName, (unsigned int) pmotor->firmware_status.All);
Debug(64, "motor_init: init card\n");
FIRMWARE_STATUS fwStatus;
fwStatus.All = pmotor->firmware_status.All;
Debug(64, "motor_init: firmware status register: 0x%x\n", fwStatus.All);
pmotor->IACK_vector = intrVector;
pmotor->status1_flag.All = 0xFFFFFFFF;
pmotor->status2_flag = 0xFFFFFFFF;
/* Disable all interrupts */
pmotor->status1_irq_enable.All = 0;
pmotor->status2_irq_enable = 0;
Debug(64, "motor_init: clear all interrupt\n");
//sendOnly("IC");
Debug(64, "motor_init: firmware version\n");
/* get FirmwareVersion */
if(getFirmwareVersion() != asynSuccess) {
errlogPrintf("%s:%s:%s: unable to talk to controller card %d\n",
driverName, functionName, portName, cardNo);
return;
}
if (fwMinor < 30 ){
errlogPrintf("%s:%s:%s: This Controllers Firmware Version %d.%d is not supported, version 1.30 or higher is mandatory\n",
driverName, functionName, portName, fwMajor, fwMinor);
}
Debug(64, "motor_init: send init string\n");
if( Init(initString, 1) != asynSuccess) {
errlogPrintf("%s:%s:%s: unable to send initstring to controller card %d\n",
driverName, functionName, portName, cardNo);
return;
}
useWatchdog = true;
if (watchdogOK()) {
Debug(64, "motor_init: enable interrupts ( vector=%d, level=%d) \n", intrVector, level);
/* Enable interrupt-when-done if selected */
if (intrVector) motorIsrSetup((unsigned int)intrVector, level);
}
else
return;
if (epicsAtExit(&omsMAXv::resetOnExit, this))
errlogPrintf("%s:%s:%s: card %d, unable to register exit function\n",
driverName, functionName, portName, cardNo);
return;
}
void omsMAXv::resetIntr()
{
enabled=false;
pmotor->status1_irq_enable.All = 0;
}
asynStatus omsMAXv::sendOnly(const char *outputBuff)
{
STATUS1 flag1;
const char* functionName = "sendOnly";
int len = strlen(outputBuff);
double timeout = 0.01;
epicsUInt16 getIndex, putIndex;
if (!enabled) return asynError;
Debug(16, "omsMAXv::send: sending: %s \n", outputBuff);
if (len > (BUFFER_SIZE-1))
{
errlogPrintf("%s:%s:%s: message too long: %d character\n",
driverName, functionName, portName, len);
return asynError;
}
/* see if junk at input port - should not be any data available */
int flushTime = 0;
while (((epicsUInt16) pmotor->inGetIndex != (epicsUInt16) pmotor->inPutIndex) && (flushTime < 100))
{
// flush cards response Buffer
#ifdef DEBUG
int deltaIndex = ((epicsUInt16)pmotor->inPutIndex) - ((epicsUInt16)pmotor->inGetIndex);
Debug(32, "%s:%s:%s: flushing %d characters\n",
driverName, functionName, portName, (((deltaIndex < 0) ? BUFFER_SIZE +
deltaIndex : deltaIndex)));
#endif
putIndex = (epicsUInt16) pmotor->inPutIndex;
pmotor->inGetIndex = putIndex;
pmotor->status1_flag.Bits.text_response = 0;
flag1.All = pmotor->status1_flag.All;
pmotor->status1_flag.All = flag1.All;
pmotor->msg_semaphore=0;
epicsThreadSleep(timeout);
flushTime++;
if (flushTime == 100 ) {
Debug(1, "%s:%s:%s: unable to flush more than 100 strings\n", driverName, functionName, portName);
return asynError;
}
}
putIndex = (epicsUInt16) pmotor->outPutIndex;
getIndex = (epicsUInt16) pmotor->outGetIndex;
for (int i = 0; (i < len); i++) {
pmotor->outBuffer[putIndex++]= outputBuff[i];
if (putIndex >= BUFFER_SIZE) putIndex = 0;
}
pmotor->outPutIndex = putIndex; /* Message Sent */
int count = 0, prevdeltaIndex = 0, index = 0;
int maxcount = (int)(0.1 / epicsThreadSleepQuantum());
// skip busy-waiting for small epicsThreadSleepQuantum
if (epicsThreadSleepQuantum() <= 0.01) index = 100;
int deltaIndex = ((epicsUInt16)pmotor->outPutIndex) - ((epicsUInt16)pmotor->outGetIndex);
while ((deltaIndex != 0) && (count <= maxcount))
{
deltaIndex = ((epicsUInt16)pmotor->outPutIndex) - ((epicsUInt16)pmotor->outGetIndex);
// do busy-waiting but not more than 100 times
while ((index < 100) && (deltaIndex != 0)){
deltaIndex = ((epicsUInt16)pmotor->outPutIndex) - ((epicsUInt16)pmotor->outGetIndex);
++index;
}
if ((index >= 100) && (deltaIndex != 0)) epicsThreadSleep(timeout);
if (deltaIndex == prevdeltaIndex)
++count;
else
count = 0;
prevdeltaIndex = deltaIndex;
};
if (deltaIndex != 0) {
Debug(1, "%s:%s:%s: Timeout\n", driverName, functionName, portName);
return asynTimeout;
}
Debug(64, "omsMAXv::send: done\n");
return asynSuccess;
}
/**
* read just one line of input
*/
asynStatus omsMAXv::sendReceive(const char *outputBuff, char *inputBuff, unsigned int inputSize)
{
static const char* functionName = "sendReceive";
STATUS1 flag1;
epicsUInt16 getIndex, putIndex;
size_t bufsize;
size_t usedSpace = 0;
char *start, *end;
int itera = 0;
asynStatus status;
if (!enabled) return asynError;
status = sendOnly(outputBuff);
if (status != asynSuccess) return status;
if (inputSize <= 0) return status;
*inputBuff = '\0';
double time = 0.0;
double timeout = 0.1;
// skip busy-waiting for small epicsThreadSleepQuantum
if (epicsThreadSleepQuantum() <= 0.01) itera = 2001;
while ((pmotor->status1_flag.Bits.text_response == 0) && (time < timeout)){
Debug(32, "%s:%s:%s: Waiting for reponse, itera:%d\n",
driverName, functionName, portName, itera);
// busy-waiting but not more than 2000 times
if (itera > 2000){
time += epicsThreadSleepQuantum();
epicsThreadSleep(epicsThreadSleepQuantum());
}
itera++;
}
if (pmotor->status1_flag.Bits.text_response == 0)
{
Debug(1, "%s:%s:%s: Timeout occurred , %s\n",
driverName, functionName, portName, outputBuff);
return asynTimeout;
}
getIndex = (epicsUInt16) pmotor->inGetIndex;
putIndex = (epicsUInt16) pmotor->inPutIndex;
bufsize = putIndex - getIndex;
start = (char *) &pmotor->inBuffer[getIndex];
end = (char *) &pmotor->inBuffer[putIndex];
if (start < end) { /* Test for message wraparound in buffer. */
usedSpace = MIN(bufsize, inputSize);
memcpy(inputBuff, start, usedSpace);
}
else
{
bufsize += BUFFER_SIZE;
size_t firstPart = ((char *) &pmotor->inBuffer[BUFFER_SIZE]) - start;
usedSpace = MIN(firstPart, inputSize);
memcpy(inputBuff, start, usedSpace);
size_t copySize = MIN(bufsize - firstPart, inputSize - usedSpace);
memcpy((inputBuff + usedSpace), (const char *) &pmotor->inBuffer[0], copySize);
usedSpace += copySize;
}
inputBuff[usedSpace - 1]= '\0';
getIndex += bufsize;
if (getIndex >= BUFFER_SIZE)
getIndex -= BUFFER_SIZE;
while (getIndex != (epicsUInt16)pmotor->inPutIndex)
{
Debug(2, "readbuf(): flushed - %d\n", pmotor->inBuffer[getIndex]);
if (++getIndex > BUFFER_SIZE)
getIndex = 0;
}
pmotor->status1_flag.Bits.text_response = 0;
pmotor->inGetIndex = (epicsUInt32) getIndex;
flag1.All = pmotor->status1_flag.All;
pmotor->status1_flag.All = flag1.All;
pmotor->msg_semaphore=0;
Debug(16, "omsMAXv::sendReceive: received %s\n", inputBuff);
return asynSuccess;
}
void omsMAXv::motorIsrSetup(volatile unsigned int vector, volatile epicsUInt8 level)
{
const char* functionName = "motorIsrSetup";
STATUS1 status1_irq;
long status;
Debug(64, "omsMAXv::isrSetup: start\n");
status = pdevLibVirtualOS->pDevConnectInterruptVME( vector, &omsMAXv::InterruptHandler, this);
if (status) {
errlogPrintf("%s:%s:%s: Can't connect to interrupt vector %d\n",
driverName, functionName, portName, vector);
return;
}
Debug(64, "omsMAXv::isrSetup: set level\n");
status = devEnableInterruptLevel(intVME, level);
if (status) {
errlogPrintf("%s:%s:%s: Can't enable interrupt level %d\n",
driverName, functionName, portName, level);
return;
}
/* Setup card for interrupt-on-done */
status1_irq.All = 0;
status1_irq.Bits.done = 0xFF;
status1_irq.Bits.cmndError = 1;
pmotor->status1_irq_enable.All = status1_irq.All; /* Enable interrupts. */
pmotor->status2_irq_enable = 0x0;
Debug(64, "omsMAXv::isrSetup: done\n");
return;
}
extern "C" int omsMAXvSetup(
int num_cards, /* maximum number of cards in rack */
int addr_type, /* VME address type; 16 -> A16, 24 -> A24 or 32 -> A32. */
unsigned int addrs, /* Base Address. */
unsigned int vector, /* noninterrupting(0), valid vectors(64-255) */
int int_level) /* interrupt level (1-6) */
{
const char* functionName = "omsMAXvSetup";
if (num_cards < 1 || num_cards > MAXv_NUM_CARDS)
{
errlogPrintf("\n%s: number of cards specified = %d but must be 1 <= number <= %d\n",
functionName, num_cards, MAXv_NUM_CARDS);
epicsThreadSleep(5.0);
return 1;
}
omsMAXv::numCards = num_cards;
omsMAXv::baseAddress = (char *) addrs;
switch (addr_type)
{
case 16:
omsMAXv::addrType = atVMEA16;
if ((epicsUInt32) addrs & 0xFFFF0FFF) {
errlogPrintf("%s: invalid A%d address: 0x%X.\n", functionName, addr_type, (epicsUInt32) addrs);
return 1;
}
break;
case 24:
omsMAXv::addrType = atVMEA24;
if ((epicsUInt32) addrs & 0xFF00FFFF) {
errlogPrintf("%s: invalid A%d address: 0x%X.\n", functionName, addr_type, (epicsUInt32) addrs);
return 1;
}
break;
case 32:
omsMAXv::addrType = atVMEA32;
if ((epicsUInt32) addrs & 0x00FFFFFF) {
errlogPrintf("%s: invalid A%d address: 0x%X.\n", functionName, addr_type, (epicsUInt32) addrs);
return 1;
}
break;
default:
errlogPrintf("%s: invalid address type, Please specify one of 16/24/32 for VME A16/A24/A32\n", functionName);
return 1;
break;
}
if ((vector != 0) && (vector < 64 || vector > 255)) {
errlogPrintf("%s: invalid address type, Please specify a value between 64 and 255\n", functionName);
epicsThreadSleep(5.0);
return 1;
}
omsMAXv::baseInterruptVector = vector;
if (int_level < 1 || int_level > 6) {
errlogPrintf("%s: invalid interrupt level, Please specify a value between 1 and 6\n", functionName);
epicsThreadSleep(5.0);
return 1;
}
omsMAXv::interruptLevel = int_level;
return 0;
}
extern "C" int omsMAXvConfig(
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 */
{
omsMAXv *pController = new omsMAXv(portName, numAxes, cardNo, initString, 0, 0, 0);
pController->startPoller((double)movingPollPeriod, (double)idlePollPeriod, 10);
return 0;
}
/*
* extended MAXv configuration, which may be used instead of omsMAXvConfig,
* if more details need to be specified.
* omsMAXvConfig2 does not need and ignores omsMAXvSetup
*/
extern "C" int omsMAXvConfig2(
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 */
{
omsMAXv *pController = new omsMAXv(portName, numAxes, slotNo, initString, priority,
stackSize, addrs, vector, int_level, addr_type, 0);
pController->startPoller((double)movingPollPeriod, (double)idlePollPeriod, 10);
return 0;
}
/* Code for iocsh registration */
extern "C"
{
/* omsMAXvSetup */
static const iocshArg setupArg0 = {"Max. controller count", iocshArgInt};
static const iocshArg setupArg1 = {"VME address type", iocshArgInt};
static const iocshArg setupArg2 = {"Base Address on 4K (0x1000) boundary", iocshArgInt};
static const iocshArg setupArg3 = {"noninterrupting(0), valid vectors(64-255)", iocshArgInt};
static const iocshArg setupArg4 = {"interrupt level (1-6)", iocshArgInt};
static const iocshArg * const OmsSetupArgs[5] = { &setupArg0, &setupArg1, &setupArg2,
&setupArg3, &setupArg4};
static const iocshFuncDef setupMAXv = {"omsMAXvSetup", 5, OmsSetupArgs};
static void setupMAXvCallFunc(const iocshArgBuf *args)
{
omsMAXvSetup(args[0].ival, args[1].ival, args[2].ival, args[3].ival, args[4].ival);
}
/* omsMAXvConfig */
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 = {"omsMAXvConfig", 6, configArgs};
static void configMAXvCallFunc(const iocshArgBuf *args)
{
omsMAXvConfig(args[0].ival, args[1].sval, args[2].ival, args[3].ival, args[4].ival, args[5].sval);
}
/* omsMAXvConfig2 */
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 = {"omsMAXvConfig2", 12, config2Args};
static void config2MAXvCallFunc(const iocshArgBuf *args)
{
omsMAXvConfig2(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 OmsMAXvAsynRegister(void)
{
iocshRegister(&setupMAXv, setupMAXvCallFunc);
iocshRegister(&configMAXv, configMAXvCallFunc);
iocshRegister(&config2MAXv, config2MAXvCallFunc);
}
epicsExportRegistrar(OmsMAXvAsynRegister);
}
-172
View File
@@ -1,172 +0,0 @@
/*
FILENAME... omsMAXv.h
USAGE... Pro-Dex OMS MAXv asyn motor controller support
*/
/*
* Created on: 10/2010
* Author: eden
*/
#ifndef OMSMAXV_H_
#define OMSMAXV_H_
#include <devLib.h>
#include "omsBaseController.h"
#define BUFFER_SIZE 1024
#define MAXv_NUM_CARDS 15 /* maximum number of cards */
#define OMS_INT_VECTOR 180 /* default interrupt vector (64-255) */
#define OMS_INT_LEVEL 5 /* default interrupt level (1-6) */
/* Limit Switch Status - Offset = 0x40 */
typedef union
{
epicsUInt32 All;
struct
{
unsigned int s_minus :1;
unsigned int r_minus :1;
unsigned int v_minus :1;
unsigned int u_minus :1;
unsigned int t_minus :1;
unsigned int z_minus :1;
unsigned int y_minus :1;
unsigned int x_minus :1;
unsigned int s_plus :1;
unsigned int r_plus :1;
unsigned int v_plus :1;
unsigned int u_plus :1;
unsigned int t_plus :1;
unsigned int z_plus :1;
unsigned int y_plus :1;
unsigned int x_plus :1;
} Bits;
} LIMIT_SWITCH;
/* Home Switch Status - Offset = 0x44 */
typedef union
{
epicsUInt32 All;
struct
{
unsigned int home_s :1; /* status of S axis */
unsigned int home_r :1; /* status of R axis */
unsigned int home_v :1; /* status of V axis */
unsigned int home_u :1; /* status of U axis */
unsigned int home_t :1; /* status of T axis */
unsigned int home_z :1; /* status of Z axis */
unsigned int home_y :1; /* status of Y axis */
unsigned int home_x :1; /* status of X axis */
} Bits;
} HOME_SWITCH;
/* Firmware status - Offset = 0x48 */
typedef union
{
epicsUInt32 All;
struct
{
unsigned int na19 :13; /* N/A bits 19-31 */
unsigned int factoryparm_loaded :1;
unsigned int altparm_loaded :1;
unsigned int defaultparm_loaded :1;
unsigned int altprgm_err :1;
unsigned int altparm_chksum_err :1;
unsigned int prgm_err :1;
unsigned int parm_chksum_err :1;
unsigned int na10 :2; /* N/A bits 10-11 */
unsigned int program_error :1;
unsigned int flash_chksum_err :1;
unsigned int na3 :5; /* N/A bits 3-7 */
unsigned int running :1;
unsigned int initializing :1;
unsigned int not_downloaded :1;
} Bits;
} FIRMWARE_STATUS;
/* Status#1 - Offset = 0xFC0 */
typedef union
{
epicsUInt32 All;
struct
{
unsigned int na3 :5; /* N/A bits 27-31. */
unsigned int data_avail :1;
unsigned int text_response :1;
unsigned int cmndError :1; /* Command error dectect */
unsigned int slip :8;
unsigned int overtravel :8;
unsigned int done :8;
} Bits;
} STATUS1;
/* OMS MAXv VME dual port memory map */
struct MAXv_motor
{
epicsUInt32 cmndPos[8];
epicsUInt32 encPos[8];
LIMIT_SWITCH limit_switch;
HOME_SWITCH home_switch;
FIRMWARE_STATUS firmware_status;
epicsUInt32 direct_cmnd_mbox;
epicsUInt32 position_req_mbox;
epicsUInt32 coherent_cmndPos[8];
epicsUInt32 coherent_encPos[8];
epicsUInt32 msg_semaphore;
epicsUInt32 queue_flush_mbox;
epicsUInt32 gpio;
epicsUInt32 naA0[19]; /* N/A byte offset 0xA0 - 0xEB. */
epicsUInt32 flash_pgm_ptr;
epicsUInt32 outPutIndex;
epicsUInt32 outGetIndex;
epicsUInt32 inPutIndex;
epicsUInt32 inGetIndex;
epicsUInt8 outBuffer[BUFFER_SIZE];
epicsUInt8 inBuffer[BUFFER_SIZE];
epicsUInt8 utility[BUFFER_SIZE];
epicsUInt32 naD00[176]; /* N/A byte offset 0xD00 - 0xFBF. */
STATUS1 status1_flag;
STATUS1 status1_irq_enable;
epicsUInt32 status2_flag;
epicsUInt32 status2_irq_enable;
epicsUInt32 IACK_vector;
epicsUInt32 config_switch;
epicsUInt32 AM_register;
epicsUInt32 naFDC[7];
epicsUInt32 FIFO_status_cntrl;
epicsUInt32 FIFO_date;
};
class omsMAXv : public omsBaseController {
public:
omsMAXv(const char*, int, int, const char*, int, int, unsigned int, int, int, const char*, int);
omsMAXv(const char*, int, int, const char*, int, int, int );
asynStatus sendReceive(const char *, char *, unsigned int );
asynStatus sendOnly(const char *);
static char* baseAddress;
static epicsAddressType addrType;
static int numCards;
static epicsUInt32 baseInterruptVector;
static epicsUInt8 interruptLevel;
static void InterruptHandler( void * param );
void* getCardAddress(){return (void*) pmotor;};
static void resetOnExit(void* param){((omsMAXv*)param)->resetIntr();};
void resetIntr();
int getCardNo(){return cardNo;};
protected:
virtual void initialize(const char*, int, int, const char*, int, int, unsigned int, int, int, epicsAddressType, int );
private:
void motorIsrSetup(volatile unsigned int, volatile epicsUInt8);
int cardNo;
volatile struct MAXv_motor *pmotor;
char readBuffer[BUFFER_SIZE];
};
#endif /* OMSMAXV_H_ */
-219
View File
@@ -1,219 +0,0 @@
/*
FILENAME... omsMAXvEncFunc.cpp
USAGE... Pro-Dex OMS MAXv encoder asyn motor support
*/
/*
* 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);
-47
View File
@@ -1,47 +0,0 @@
/*
FILENAME... omsMAXvEncFunc.h
USAGE... Pro-Dex OMS MAXv encoder asyn motor support
*/
/*
* Created on: 10/2010
* Author: eden
*/
#ifndef OMSMAXVENCFUNC_H_
#define OMSMAXVENCFUNC_H_
#include "omsMAXv.h"
#define ENCFUNCTION_FUNCTMASK 0xFF00 /* 8 function bits */
#define ENCFUNCTION_ENC_MASK 0x00F0 /* 4 encoder bits (encoder 0 - 15) */
#define ENCFUNCTION_AXISMASK 0x000F /* 4 axis bits (axis 0 - 15) */
#define ENCFUNCTION_NONE 0x00 /* no encoder functions */
#define ENCFUNCTION_READ 0x01 /* read (auxiliary) encoder */
#define ENCFUNCTION_REPLACE 0x02 /* replace encoder of axis axismask with encoder encodermask */
#define ENCFUNCTION_AVERAGE 0x03 /* read (auxiliary) encoder */
#define ENCFUNCTION_AUXENC_0 0x0E /* aux encoder 0 is defined as encoder 14) */
#define ENCFUNCTION_AUXENC_1 0x0F /* aux encoder 1 is defined as encoder 15) */
#define MAXENCFUNC 8
class omsMAXvEncFunc : public omsMAXv {
public:
omsMAXvEncFunc(const char*, int, int, const char*, int, int, unsigned int, int, int, const char* );
omsMAXvEncFunc(const char*, int, int, const char*, int, int );
virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
virtual asynStatus getEncoderPositions(epicsInt32 encPosArr[OMS_MAX_AXES]);
private:
void initialize();
int averageChannel[MAXENCFUNC];
int encFuncIndex[MAXENCFUNC];
int encRawPosIndex[MAXENCFUNC];
int encPosIndex[2];
};
#endif /* OMSMAXVENCFUNC_H_ */