A first sort of working version of a asyn driver for the Nanotoec SMCI
motors. Homing still needs more testing
This commit is contained in:
@ -23,7 +23,8 @@ CHECK_RELEASE = YES
|
||||
|
||||
# To install files into a location other than $(TOP) define
|
||||
# INSTALL_LOCATION here.
|
||||
INSTALL_LOCATION=/usr/local/epics/sinqApp
|
||||
#INSTALL_LOCATION=/usr/local/epics/sinqApp
|
||||
INSTALL_LOCATION=/afs/psi.ch/project/sinqdev/sinqepicsapp
|
||||
|
||||
# Set this when your IOC and the host use different paths
|
||||
# to access the application. This will be needed to boot
|
||||
|
6
iocBoot/iocsinqEPICS/envPaths
Normal file
6
iocBoot/iocsinqEPICS/envPaths
Normal file
@ -0,0 +1,6 @@
|
||||
epicsEnvSet("ARCH","linux-x86-debug")
|
||||
epicsEnvSet("IOC","iocsinqEPICS")
|
||||
epicsEnvSet("TOP","/afs/psi.ch/project/sinqdev/sinqepicsapp")
|
||||
epicsEnvSet("EPICS_BASE","/usr/local/epics")
|
||||
epicsEnvSet("ASYN","/usr/local/epics/support/asyn-4-18")
|
||||
epicsEnvSet("MOTOR","/usr/local/epics/support/motor-6-7")
|
8
iocBoot/iocsinqEPICS/motor.substitutions.nanotec
Normal file
8
iocBoot/iocsinqEPICS/motor.substitutions.nanotec
Normal file
@ -0,0 +1,8 @@
|
||||
file "$(MOTOR)/db/basic_asyn_motor.db"
|
||||
{
|
||||
pattern
|
||||
{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT}
|
||||
{KM36:nano:, 1, "m$(N)", "asynMotor", nano, 1, "m1", mm, Pos, 2.0, 0.1, .2, 0, 1, .2, .0001, 3, 30, -30, "1"}
|
||||
{KM36:nano:, 2, "m$(N)", "asynMotor", nano, 2, "m2", mm, Pos, 2.0, 0.1, .2, 0, 1, .2, .0001, 3, 60, -60, "10"}
|
||||
{KM36:nano:, 3, "m$(N)", "asynMotor", nano, 3, "m3", mm, Pos, 2.0, 0.1, .2, 0, 1, .2, .0001, 3, 100, -100, "9"}
|
||||
}
|
37
iocBoot/iocsinqEPICS/nanotest.cmd
Executable file
37
iocBoot/iocsinqEPICS/nanotest.cmd
Executable file
@ -0,0 +1,37 @@
|
||||
#!../../bin/linux-x86-debug/sinqEPICS
|
||||
|
||||
|
||||
## You may have to change sinqEPICS to something else
|
||||
## everywhere it appears in this file
|
||||
|
||||
< envPaths
|
||||
|
||||
cd ${TOP}
|
||||
|
||||
## Register all support components
|
||||
dbLoadDatabase "dbd/sinqEPICS.dbd"
|
||||
#dbLoadDatabase "dbd/sinq.dbd"
|
||||
sinqEPICS_registerRecordDeviceDriver pdbbase
|
||||
|
||||
## Load record instances
|
||||
#dbLoadRecords("db/xxx.db","user=koenneckeHost")
|
||||
|
||||
|
||||
#---------- load Nanotec motor controller
|
||||
#drvAsynIPPortConfigure("serial1", "narziss-ts:3002",0,0,0)
|
||||
drvAsynIPPortConfigure("serial1", "localhost:2020",0,0,0)
|
||||
NanotecCreateController("nano","serial1",3,"1,10,9");
|
||||
|
||||
### Motors
|
||||
|
||||
dbLoadRecords("$(ASYN)/db/asynRecord.db","P=KM36:,R=serial1,PORT=serial1,ADDR=0,OMAX=80,IMAX=80")
|
||||
|
||||
|
||||
cd ${TOP}/iocBoot/${IOC}
|
||||
dbLoadTemplate "motor.substitutions.nanotec"
|
||||
|
||||
|
||||
iocInit
|
||||
|
||||
## Start any sequence programs
|
||||
#seq sncxxx,"user=koenneckeHost"
|
@ -26,6 +26,7 @@ sinqEPICS_LIBS += motor asyn std anc350 anc350AsynMotor
|
||||
sinqEPICS_SRCS += sinqEPICS_registerRecordDeviceDriver.cpp
|
||||
sinqEPICS_SRCS += EL734Driver.cpp devScalerEL737.c pmacAsynIPPort.c
|
||||
sinqEPICS_SRCS += pmacController.cpp pmacAxis.cpp
|
||||
sinqEPICS_SRCS += NanotecDriver.cpp stptok.cpp
|
||||
|
||||
|
||||
# Build the main IOC entry point on workstation OSs.
|
||||
|
451
sinqEPICSApp/src/NanotecDriver.cpp
Normal file
451
sinqEPICSApp/src/NanotecDriver.cpp
Normal file
@ -0,0 +1,451 @@
|
||||
/*
|
||||
FILENAME... NanotecDriver.cpp
|
||||
USAGE... Motor driver support for the Nanotec SMCI controllers
|
||||
connected to a RS-485 bus.
|
||||
|
||||
Mark Koennecke
|
||||
July 2015
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <iocsh.h>
|
||||
#include <epicsThread.h>
|
||||
#include <errlog.h>
|
||||
|
||||
#include <asynOctetSyncIO.h>
|
||||
|
||||
#include "stptok.h"
|
||||
#include "NanotecDriver.h"
|
||||
#include <epicsExport.h>
|
||||
|
||||
#define IDLEPOLL 60
|
||||
|
||||
|
||||
/** Creates a new NanotecController object.
|
||||
* \param[in] portName The name of the asyn port that will be created for this driver
|
||||
* \param[in] NanotecPortName The name of the drvAsynSerialPort that was created previously to connect to the Nanotec controller
|
||||
*/
|
||||
NanotecController::NanotecController(const char *portName, const char *NanotecPortName, int motCount, const char *bus)
|
||||
: asynMotorController(portName, motCount+1, 0,
|
||||
0, // No additional interfaces beyond those in base class
|
||||
0, // No additional callback interfaces beyond those in base class
|
||||
ASYN_CANBLOCK | ASYN_MULTIDEVICE,
|
||||
1, // autoconnect
|
||||
0, 0) // Default priority and stack size
|
||||
{
|
||||
int axis, busAddress;
|
||||
asynStatus status;
|
||||
NanotecAxis *pAxis;
|
||||
static const char *functionName = "NanotecController::NanotecController";
|
||||
char *pPtr, busNoString[20];
|
||||
|
||||
|
||||
/* Connect to Nanotec controller */
|
||||
status = pasynOctetSyncIO->connect(NanotecPortName, 0, &pasynUserController_, NULL);
|
||||
if (status) {
|
||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||
"%s: cannot connect to Nanotec controller\n",
|
||||
functionName);
|
||||
}
|
||||
pasynOctetSyncIO->setOutputEos(pasynUserController_,"\r",strlen("\r"));
|
||||
pasynOctetSyncIO->setInputEos(pasynUserController_,"\r",strlen("\r"));
|
||||
|
||||
axis = 1;
|
||||
pPtr = (char *)bus;
|
||||
while((pPtr = stptok(pPtr,busNoString,sizeof(busNoString),",")) != NULL){
|
||||
busAddress = atoi(busNoString);
|
||||
pAxis = new NanotecAxis(this, axis,busAddress);
|
||||
errlogPrintf("Axis %d, busAddress = %d\n", axis, busAddress);
|
||||
axis++;
|
||||
}
|
||||
|
||||
startPoller(1000./1000., IDLEPOLL, 2);
|
||||
}
|
||||
|
||||
|
||||
/** Creates a new NanotecController object.
|
||||
* Configuration command, called directly or from iocsh
|
||||
* \param[in] portName The name of the asyn port that will be created for this driver
|
||||
* \param[in] NanotecPortName The name of the drvAsynIPPPort that was created previously to connect to the Nanotec controller
|
||||
*/
|
||||
extern "C" int NanotecCreateController(const char *portName, const char *NanotecPortName, int numMot, const char *busAddresses)
|
||||
{
|
||||
NanotecController *pNanotecController
|
||||
= new NanotecController(portName, NanotecPortName,numMot,busAddresses);
|
||||
pNanotecController = NULL;
|
||||
return(asynSuccess);
|
||||
}
|
||||
|
||||
/** Reports on status of the driver
|
||||
* \param[in] fp The file pointer on which report information will be written
|
||||
* \param[in] level The level of report detail desired
|
||||
*
|
||||
* If details > 0 then information is printed about each axis.
|
||||
* After printing controller-specific information it calls asynMotorController::report()
|
||||
*/
|
||||
void NanotecController::report(FILE *fp, int level)
|
||||
{
|
||||
fprintf(fp, "Nanotec motor driver %s, numAxes=%d\n",
|
||||
this->portName, numAxes_);
|
||||
|
||||
// Call the base class method
|
||||
asynMotorController::report(fp, level);
|
||||
}
|
||||
|
||||
/** Returns a pointer to an NanotecAxis object.
|
||||
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
||||
* \param[in] pasynUser asynUser structure that encodes the axis index number. */
|
||||
NanotecAxis* NanotecController::getAxis(asynUser *pasynUser)
|
||||
{
|
||||
return static_cast<NanotecAxis*>(asynMotorController::getAxis(pasynUser));
|
||||
}
|
||||
|
||||
/** Returns a pointer to an NanotecAxis object.
|
||||
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
||||
* \param[in] axisNo Axis index number. */
|
||||
NanotecAxis* NanotecController::getAxis(int axisNo)
|
||||
{
|
||||
return static_cast<NanotecAxis*>(asynMotorController::getAxis(axisNo));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// These are the NanotecAxis methods
|
||||
|
||||
/** Creates a new NanotecAxis object.
|
||||
* \param[in] pC Pointer to the NanotecController to which this axis belongs.
|
||||
* \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1.
|
||||
*
|
||||
* Initializes register numbers, etc.
|
||||
*/
|
||||
NanotecAxis::NanotecAxis(NanotecController *pC, int axisNo, int busAddress)
|
||||
: asynMotorAxis(pC, axisNo),
|
||||
pC_(pC)
|
||||
{
|
||||
this->busAddress = busAddress;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Reports on status of the axis
|
||||
* \param[in] fp The file pointer on which report information will be written
|
||||
* \param[in] level The level of report detail desired
|
||||
*
|
||||
* After printing device-specific information calls asynMotorAxis::report()
|
||||
*/
|
||||
void NanotecAxis::report(FILE *fp, int level)
|
||||
{
|
||||
if (level > 0) {
|
||||
fprintf(fp, " axis %d\n",
|
||||
axisNo_);
|
||||
}
|
||||
|
||||
// Call the base class method
|
||||
//asynMotorAxis::report(fp, level);
|
||||
}
|
||||
|
||||
asynStatus NanotecController::transactController(char command[COMLEN], char reply[COMLEN])
|
||||
{
|
||||
asynStatus status;
|
||||
size_t in, out;
|
||||
int reason;
|
||||
|
||||
pasynOctetSyncIO->flush(pasynUserController_);
|
||||
|
||||
status = pasynOctetSyncIO->writeRead(pasynUserController_, command, strlen(command),
|
||||
reply,COMLEN, 1.,&out,&in,&reason);
|
||||
if(status != asynSuccess){
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
check for Nanotec errors
|
||||
*/
|
||||
if(strstr(reply,"?") != NULL){
|
||||
errlogSevPrintf(errlogMajor, "Bad command %s", command);
|
||||
return asynError;
|
||||
}
|
||||
|
||||
if(strlen(reply) < 1) {
|
||||
errlogSevPrintf(errlogMajor, "No reply received for %s", command);
|
||||
return asynError;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus NanotecAxis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration)
|
||||
{
|
||||
asynStatus status;
|
||||
//static const char *functionName = "NanotecAxis::move";
|
||||
char command[COMLEN], reply[COMLEN];
|
||||
size_t in, out;
|
||||
int reason;
|
||||
|
||||
// status = sendAccelAndVelocity(acceleration, maxVelocity);
|
||||
|
||||
if (relative) {
|
||||
position += this->position;
|
||||
}
|
||||
|
||||
homing = 0;
|
||||
|
||||
/*
|
||||
set mode
|
||||
*/
|
||||
snprintf(command,sizeof(command),"#%dp2",busAddress);
|
||||
status = pC_->transactController(command,reply);
|
||||
if(status != asynSuccess){
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
set target
|
||||
*/
|
||||
snprintf(command,sizeof(command),"#%ds%d",busAddress, (int)position);
|
||||
status = pC_->transactController(command,reply);
|
||||
if(status != asynSuccess){
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
and start..
|
||||
*/
|
||||
snprintf(command,sizeof(command),"#%dA",busAddress);
|
||||
status = pC_->transactController(command,reply);
|
||||
if(status != asynSuccess){
|
||||
return status;
|
||||
}
|
||||
|
||||
next_poll = -1;
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus NanotecAxis::home(double minVelocity, double maxVelocity, double acceleration, int forwards)
|
||||
{
|
||||
asynStatus status;
|
||||
//static const char *functionName = "NanotecAxis::home";
|
||||
char command[COMLEN], reply[COMLEN];
|
||||
|
||||
/*
|
||||
set mode
|
||||
*/
|
||||
snprintf(command,sizeof(command),"#%dp4",busAddress);
|
||||
status = pC_->transactController(command,reply);
|
||||
if(status != asynSuccess){
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
reset positioning errors
|
||||
*/
|
||||
snprintf(command,sizeof(command),"#%dD",busAddress);
|
||||
status = pC_->transactController(command,reply);
|
||||
if(status != asynSuccess){
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
set direction
|
||||
*/
|
||||
snprintf(command,sizeof(command),"#%dd0",busAddress);
|
||||
status = pC_->transactController(command,reply);
|
||||
if(status != asynSuccess){
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
and start..
|
||||
*/
|
||||
snprintf(command,sizeof(command),"#%dA",busAddress);
|
||||
status = pC_->transactController(command,reply);
|
||||
if(status != asynSuccess){
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
homing = 1;
|
||||
next_poll= -1;
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus NanotecAxis::moveVelocity(double minVelocity, double maxVelocity, double acceleration)
|
||||
{
|
||||
asynStatus status;
|
||||
//static const char *functionName = "NanotecAxis::moveVelocity";
|
||||
double target;
|
||||
|
||||
// asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
||||
// "%s: minVelocity=%f, maxVelocity=%f, acceleration=%f\n",
|
||||
// functionName, minVelocity, maxVelocity, acceleration);
|
||||
|
||||
|
||||
|
||||
if (maxVelocity > 0.) {
|
||||
/* This is a positive move */
|
||||
pC_->getDoubleParam(axisNo_,pC_->motorHighLimit_,&target);
|
||||
} else {
|
||||
/* This is a negative move */
|
||||
pC_->getDoubleParam(axisNo_,pC_->motorLowLimit_,&target);
|
||||
}
|
||||
|
||||
status = move(target,0,0,0,0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus NanotecAxis::stop(double acceleration )
|
||||
{
|
||||
asynStatus status;
|
||||
//static const char *functionName = "NanotecAxis::stop";
|
||||
char command[COMLEN], reply[COMLEN];
|
||||
|
||||
sprintf(command, "#%dS1", busAddress);
|
||||
status = pC_->transactController(command,reply);
|
||||
errlogPrintf("Sent STOP on Axis %d\n", axisNo_);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus NanotecAxis::setPosition(double position)
|
||||
{
|
||||
asynStatus status;
|
||||
//static const char *functionName = "NanotecAxis::setPosition";
|
||||
char command[COMLEN], reply[COMLEN];
|
||||
|
||||
sprintf(command, "#%dD%d", busAddress, (int)position);
|
||||
status = pC_->transactController(command,reply);
|
||||
next_poll = -1;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus NanotecAxis::setClosedLoop(bool closedLoop)
|
||||
{
|
||||
//static const char *functionName = "NanotecAxis::setClosedLoop";
|
||||
|
||||
/*
|
||||
This belongs into the Kingdom of Electronics.
|
||||
We do not do this.
|
||||
*/
|
||||
|
||||
return asynError;
|
||||
}
|
||||
|
||||
/** Polls the axis.
|
||||
* This function reads the motor position, the limit status, the home status, the moving status,
|
||||
* and the drive power-on status.
|
||||
* It calls setIntegerParam() and setDoubleParam() for each item that it polls,
|
||||
* and then calls callParamCallbacks() at the end.
|
||||
* \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false). */
|
||||
asynStatus NanotecAxis::poll(bool *moving)
|
||||
{
|
||||
asynStatus comStatus;
|
||||
char command[COMLEN], reply[COMLEN];
|
||||
char *pPtr;
|
||||
int posVal, statVal;
|
||||
|
||||
|
||||
// protect against excessive polling
|
||||
if(time(NULL) < next_poll){
|
||||
*moving = false;
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
// Read the current motor position
|
||||
sprintf(command,"#%dC", busAddress);
|
||||
comStatus = pC_->transactController(command,reply);
|
||||
if(comStatus) goto skip;
|
||||
|
||||
pPtr = strchr(reply,'C');
|
||||
pPtr++;
|
||||
posVal = atoi(pPtr);
|
||||
|
||||
errlogPrintf("Axis %d, reply %s, position %d\n", axisNo_, reply, posVal);
|
||||
setDoubleParam(pC_->motorPosition_, (double)posVal);
|
||||
//setDoubleParam(pC_->motorEncoderPosition_, position);
|
||||
|
||||
|
||||
// Read the moving status of this motor
|
||||
sprintf(command,"#%d$",busAddress);
|
||||
comStatus = pC_->transactController(command,reply);
|
||||
if(comStatus) goto skip;
|
||||
|
||||
pPtr = strchr(reply,'$');
|
||||
pPtr++;
|
||||
statVal = atoi(pPtr);
|
||||
errlogPrintf("Axis %d, reply %s, statVal = %d\n",
|
||||
axisNo_, reply, statVal);
|
||||
|
||||
setIntegerParam(pC_->motorStatusDone_, false);
|
||||
*moving = true;
|
||||
if(homing){
|
||||
switch(statVal) {
|
||||
case 164:
|
||||
setPosition(.0);
|
||||
break;
|
||||
case 163:
|
||||
case 161:
|
||||
*moving = false;
|
||||
setIntegerParam(pC_->motorStatusAtHome_, true);
|
||||
setIntegerParam(pC_->motorStatusDone_, true);
|
||||
break;
|
||||
default :
|
||||
if(statVal & 1) {
|
||||
*moving = false;
|
||||
setIntegerParam(pC_->motorStatusAtHome_, true);
|
||||
setIntegerParam(pC_->motorStatusDone_, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(statVal & 1) {
|
||||
*moving = false;
|
||||
setIntegerParam(pC_->motorStatusDone_, true);
|
||||
}
|
||||
}
|
||||
|
||||
if(*moving == true){
|
||||
next_poll = -1;
|
||||
}
|
||||
|
||||
skip:
|
||||
setIntegerParam(pC_->motorStatusProblem_, comStatus ? 1:0);
|
||||
callParamCallbacks();
|
||||
return comStatus ? asynError : asynSuccess;
|
||||
}
|
||||
|
||||
/** Code for iocsh registration */
|
||||
static const iocshArg NanotecCreateControllerArg0 = {"Port name", iocshArgString};
|
||||
static const iocshArg NanotecCreateControllerArg1 = {"Nanotec port name", iocshArgString};
|
||||
static const iocshArg NanotecCreateControllerArg2 = {"Number of axes", iocshArgInt};
|
||||
static const iocshArg NanotecCreateControllerArg3 = {"Komma separated list of bus addresses", iocshArgString};
|
||||
static const iocshArg * const NanotecCreateControllerArgs[] = {&NanotecCreateControllerArg0,
|
||||
&NanotecCreateControllerArg1,
|
||||
&NanotecCreateControllerArg2,
|
||||
&NanotecCreateControllerArg3
|
||||
};
|
||||
static const iocshFuncDef NanotecCreateControllerDef = {"NanotecCreateController", 4, NanotecCreateControllerArgs};
|
||||
static void NanotecCreateContollerCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
NanotecCreateController(args[0].sval, args[1].sval, args[2].ival,args[3].sval);
|
||||
}
|
||||
|
||||
static void NanotecRegister(void)
|
||||
{
|
||||
iocshRegister(&NanotecCreateControllerDef, NanotecCreateContollerCallFunc);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
epicsExportRegistrar(NanotecRegister);
|
||||
}
|
57
sinqEPICSApp/src/NanotecDriver.h
Normal file
57
sinqEPICSApp/src/NanotecDriver.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
FILENAME... NanotecDriver.h
|
||||
USAGE... Motor driver support for the Nanotec SMCI controller.
|
||||
|
||||
Mark Koennecke
|
||||
July 2015
|
||||
|
||||
*/
|
||||
|
||||
#include "asynMotorController.h"
|
||||
#include "asynMotorAxis.h"
|
||||
|
||||
#define COMLEN 80
|
||||
#define MAXMOT 99
|
||||
|
||||
class NanotecAxis : public asynMotorAxis
|
||||
{
|
||||
public:
|
||||
/* These are the methods we override from the base class */
|
||||
NanotecAxis(class NanotecController *pC, int axis, int busAddress);
|
||||
void report(FILE *fp, int level);
|
||||
asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration);
|
||||
asynStatus moveVelocity(double min_velocity, double max_velocity, double acceleration);
|
||||
asynStatus home(double min_velocity, double max_velocity, double acceleration, int forwards);
|
||||
asynStatus stop(double acceleration);
|
||||
asynStatus poll(bool *moving);
|
||||
asynStatus setPosition(double position);
|
||||
asynStatus setClosedLoop(bool closedLoop);
|
||||
|
||||
private:
|
||||
NanotecController *pC_; /**< Pointer to the asynMotorController to which this axis belongs.
|
||||
* Abbreviated because it is used very frequently */
|
||||
double position;
|
||||
int homing;
|
||||
time_t next_poll;
|
||||
int busAddress;
|
||||
|
||||
friend class NanotecController;
|
||||
};
|
||||
|
||||
class NanotecController : public asynMotorController {
|
||||
public:
|
||||
NanotecController(const char *portName, const char *NanotecPortName, int numMot, const char *busAddresses);
|
||||
|
||||
void report(FILE *fp, int level);
|
||||
NanotecAxis* getAxis(asynUser *pasynUser);
|
||||
NanotecAxis* getAxis(int axisNo);
|
||||
|
||||
friend class NanotecAxis;
|
||||
private:
|
||||
asynUser *pasynUserController_;
|
||||
|
||||
asynStatus transactController(char command[COMLEN], char reply[COMLEN]);
|
||||
|
||||
|
||||
|
||||
};
|
@ -2,6 +2,7 @@
|
||||
# SINQ specific DB definitions
|
||||
#---------------------------------------------
|
||||
registrar(EL734Register)
|
||||
registrar(NanotecRegister)
|
||||
addpath "/usr/local/epics/support/asyn-4-18/dbd"
|
||||
addpath "/usr/local/epics/dbd"
|
||||
addpath "/usr/local/epics/support/motor-6-7/dbd"
|
||||
@ -14,3 +15,4 @@ include "anc350AsynMotor.dbd"
|
||||
|
||||
include "scalerRecord.dbd"
|
||||
device(scaler,INST_IO,devScalerEL737,"asynScalerEL737")
|
||||
|
||||
|
50
sinqEPICSApp/src/stptok.cpp
Normal file
50
sinqEPICSApp/src/stptok.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
** stptok() -- public domain by Ray Gardner, modified by Bob Stout
|
||||
**
|
||||
** You pass this function a string to parse, a buffer to receive the
|
||||
** "token" that gets scanned, the length of the buffer, and a string of
|
||||
** "break" characters that stop the scan. It will copy the string into
|
||||
** the buffer up to any of the break characters, or until the buffer is
|
||||
** full, and will always leave the buffer null-terminated. It will
|
||||
** return a pointer to the first non-breaking character after the one
|
||||
** that stopped the scan.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
char *stptok(char *s, char *tok, size_t toklen, char *brk)
|
||||
{
|
||||
char *lim, *b;
|
||||
|
||||
if (!*s)
|
||||
return NULL;
|
||||
|
||||
lim = tok + toklen - 1;
|
||||
while (*s && tok < lim) {
|
||||
for (b = brk; *b; b++) {
|
||||
if (*s == *b) {
|
||||
*tok = 0;
|
||||
return (char *) (s + 1);
|
||||
}
|
||||
}
|
||||
*tok++ = *s++;
|
||||
}
|
||||
*tok = 0;
|
||||
return (char *) s;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
char *SkipSpace(char *pText)
|
||||
{
|
||||
char *pRes;
|
||||
|
||||
pRes = pText;
|
||||
while (*pRes) {
|
||||
if ((*pRes != ' ') && (*pRes != '\t') && (*pRes != '\r')) {
|
||||
return pRes;
|
||||
}
|
||||
pRes++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
16
sinqEPICSApp/src/stptok.h
Normal file
16
sinqEPICSApp/src/stptok.h
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
** stptok() -- public domain by Ray Gardner, modified by Bob Stout
|
||||
**
|
||||
** You pass this function a string to parse, a buffer to receive the
|
||||
** "token" that gets scanned, the length of the buffer, and a string of
|
||||
** "break" characters that stop the scan. It will copy the string into
|
||||
** the buffer up to any of the break characters, or until the buffer is
|
||||
** full, and will always leave the buffer null-terminated. It will
|
||||
** return a pointer to the first non-breaking character after the one
|
||||
** that stopped the scan.
|
||||
*/
|
||||
#ifndef STPSTPTOK
|
||||
#define STPSTPTOK
|
||||
char *stptok(char *s, char *tok, size_t toklen, char *brk);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user