diff --git a/motorApp/Makefile b/motorApp/Makefile
index 6bb45ffd..69be4627 100644
--- a/motorApp/Makefile
+++ b/motorApp/Makefile
@@ -39,6 +39,9 @@ MclennanSrc_DEPEND_DIRS = MotorSrc
DIRS += PiSrc
PiSrc_DEPEND_DIRS = MotorSrc
+DIRS += PIGCS2Src
+PIGCS2Src_DEPEND_DIRS = MotorSrc
+
DIRS += MicroMoSrc
MicroMoSrc_DEPEND_DIRS = MotorSrc
diff --git a/motorApp/PI_GCS2/.cproject b/motorApp/PI_GCS2/.cproject
new file mode 100755
index 00000000..ab6e2da4
--- /dev/null
+++ b/motorApp/PI_GCS2/.cproject
@@ -0,0 +1,586 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/motorApp/PI_GCS2/.project b/motorApp/PI_GCS2/.project
new file mode 100755
index 00000000..46c24945
--- /dev/null
+++ b/motorApp/PI_GCS2/.project
@@ -0,0 +1,83 @@
+
+
+ PIasynSrcHg
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+ ?name?
+
+
+
+ org.eclipse.cdt.make.core.append_environment
+ true
+
+
+ org.eclipse.cdt.make.core.autoBuildTarget
+ all
+
+
+ org.eclipse.cdt.make.core.buildArguments
+
+
+
+ org.eclipse.cdt.make.core.buildCommand
+ make
+
+
+ org.eclipse.cdt.make.core.buildLocation
+ ${workspace_loc:/PIasynSrcHg}
+
+
+ org.eclipse.cdt.make.core.cleanBuildTarget
+ clean
+
+
+ org.eclipse.cdt.make.core.contents
+ org.eclipse.cdt.make.core.activeConfigSettings
+
+
+ org.eclipse.cdt.make.core.enableAutoBuild
+ false
+
+
+ org.eclipse.cdt.make.core.enableCleanBuild
+ true
+
+
+ org.eclipse.cdt.make.core.enableFullBuild
+ true
+
+
+ org.eclipse.cdt.make.core.fullBuildTarget
+ all
+
+
+ org.eclipse.cdt.make.core.stopOnError
+ true
+
+
+ org.eclipse.cdt.make.core.useDefaultBuildCmd
+ true
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.core.ccnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/Db/Makefile b/motorApp/PI_GCS2/PI_GCS2_App/Db/Makefile
new file mode 100755
index 00000000..2e4b8cb2
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/Db/Makefile
@@ -0,0 +1,23 @@
+TOP=../..
+include $(TOP)/configure/CONFIG
+#----------------------------------------
+# ADD MACRO DEFINITIONS AFTER THIS LINE
+
+#----------------------------------------------------
+# Optimization of db files using dbst (DEFAULT: NO)
+#DB_OPT = YES
+
+#----------------------------------------------------
+# Create and install (or just install) into /db
+# databases, templates, substitutions like this
+DB += PI_Support.db
+DB += PI_SupportCtrl.db
+
+#----------------------------------------------------
+# If .db template is not named *.template add
+# _template =
+
+include $(TOP)/configure/RULES
+#----------------------------------------
+# ADD RULES AFTER THIS LINE
+
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/Makefile b/motorApp/PI_GCS2/PI_GCS2_App/Makefile
new file mode 100755
index 00000000..8a9f763d
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/Makefile
@@ -0,0 +1,7 @@
+TOP = ..
+include $(TOP)/configure/CONFIG
+DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *src*))
+DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *Src*))
+DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *db*))
+DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *Db*))
+include $(TOP)/configure/RULES_DIRS
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/Makefile b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/Makefile
new file mode 100755
index 00000000..c0560cfb
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/Makefile
@@ -0,0 +1,36 @@
+TOP=../..
+
+include $(TOP)/configure/CONFIG
+#----------------------------------------
+# ADD MACRO DEFINITIONS AFTER THIS LINE
+#=============================
+
+#==================================================
+# Build an IOC support library
+
+LIBRARY_IOC += PI_GCS2Support
+
+# motorRecord.h will be created from motorRecord.dbd
+# install devMotorSoft.dbd into /dbd
+DBD += PI_GCS2Support.dbd
+
+# The following are compiled and added to the Support library
+PI_GCS2Support_SRCS += PIasynController.cpp
+PI_GCS2Support_SRCS += PIasynAxis.cpp
+PI_GCS2Support_SRCS += PIGCSController.cpp
+PI_GCS2Support_SRCS += PIGCSMotorController.cpp
+PI_GCS2Support_SRCS += PIGCSPiezoController.cpp
+PI_GCS2Support_SRCS += PIE517Controller.cpp
+PI_GCS2Support_SRCS += PIE755Controller.cpp
+PI_GCS2Support_SRCS += PIHexapodController.cpp
+PI_GCS2Support_SRCS += PIC702Controller.cpp
+PI_GCS2Support_SRCS += translateerror.c
+
+PI_GCS2Support_LIBS += motor
+PI_GCS2Support_LIBS += asyn
+PI_GCS2Support_LIBS += $(EPICS_BASE_IOC_LIBS)
+
+include $(TOP)/configure/RULES
+#----------------------------------------
+# ADD RULES AFTER THIS LINE
+
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIC702Controller.cpp b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIC702Controller.cpp
new file mode 100755
index 00000000..102ab904
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIC702Controller.cpp
@@ -0,0 +1,187 @@
+/*
+ * PIC702Controller
+ *
+ * Author: sra
+ */
+
+#include "PIC702Controller.h"
+#include "PIasynAxis.h"
+#include
+#include
+
+
+//#undef asynPrint
+//#define asynPrint(user,reason,format...) 0
+
+
+asynStatus PIC702Controller::getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl)
+{
+ int busy;
+
+ epicsTimeStamp now;
+ epicsTimeGetCurrent(&now);
+ if(epicsTimeDiffInSeconds(&now,&m_timeREFstarted) < 1.0)
+ {
+ homing = 1;
+ moving = 1;
+ return asynSuccess;
+ }
+
+
+ asynStatus status = getBusy(pAxis, busy);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+
+ negLimit = 0;
+ posLimit = 0;
+ homing = busy;
+ if (busy)
+ {
+ moving = busy;
+ return status;
+ }
+
+ status = getMoving(pAxis, moving);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+
+ return status;
+}
+
+asynStatus PIC702Controller::findConnectedAxes()
+{
+ // GCS! - axes are not separated by LineFeeds
+ // axis identifier is only one single char, all axes returned as single "word"
+ m_nrFoundAxes = 0;
+ for (size_t i=0; im_maxAcceleration = maxAcc;
+ }
+ else
+ {
+ pAxis->m_maxAcceleration = maxDec;
+ }
+ return status;
+}
+
+asynStatus PIC702Controller::hasReferenceSensor(PIasynAxis* pAxis)
+{
+ double hasref;
+ asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_HAT_REF, hasref);
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+ pAxis->m_bHasReference = hasref > 0.1;
+
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
+ "PIC702Controller::hasReferenceSwitch() axis has %sreference sensor\n",
+ pAxis->m_bHasReference?"":"no ");
+ return status;
+}
+
+asynStatus PIC702Controller::getReferencedState(PIasynAxis* pAxis)
+{
+ double isref;
+ asynStatus status = getGCSParameter(pAxis, PI_PARA_C702_REFERENCED, isref);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ pAxis->m_homed = (isref > 0.1)?1:0;
+
+ return status;
+}
+
+asynStatus PIC702Controller::referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards)
+{
+ asynStatus status = setServo(pAxis, 1);
+ if (asynSuccess != status)
+ return status;
+
+ status = setVelocityCts(pAxis, velocity);
+ if (asynSuccess != status)
+ return status;
+
+ char cmd[100];
+ if (pAxis->m_bHasReference)
+ {
+ // call REF - find reference
+ sprintf(cmd,"REF %s", pAxis->m_szAxisName);
+ }
+ else if (pAxis->m_bHasLimitSwitches)
+ {
+ if (forwards)
+ {
+ // call MPL - find positive limit switch
+ sprintf(cmd,"MPL %s", pAxis->m_szAxisName);
+ }
+ else
+ {
+ // call MNL - find negative limit switch
+ sprintf(cmd,"MNL %s", pAxis->m_szAxisName);
+ }
+ }
+ else
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR,
+ "PIC702Controller::referenceVelCts() failed - axis has no reference/limit switch\n");
+ epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize,
+ "PIC702Controller::referenceVelCts() failed - axis has no reference/limit switch\n");
+ return asynError;
+ }
+ status = sendOnly(cmd);
+ if (asynSuccess != status)
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR,
+ "PIC702Controller::referenceVelCts() failed\n");
+ return status;
+ }
+ pAxis->m_isHoming = 1;
+ epicsTimeGetCurrent(&m_timeREFstarted);
+
+ return asynSuccess;
+}
+
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIC702Controller.h b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIC702Controller.h
new file mode 100755
index 00000000..f1e20d00
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIC702Controller.h
@@ -0,0 +1,45 @@
+/*
+ * PIC702Controller.h
+ *
+ * Author: sra
+ */
+
+#ifndef PIC702CONTROLLER_H_
+#define PIC702CONTROLLER_H_
+
+#include "PIGCSMotorController.h"
+#include
+
+/**
+ * class representing PI C-702.
+ *
+ */
+class PIC702Controller : public PIGCSMotorController
+{
+public:
+ PIC702Controller(asynUser* pCom, const char* szIDN)
+ : PIGCSMotorController(pCom, szIDN)
+ {
+ }
+ ~PIC702Controller() {}
+
+ virtual asynStatus getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl);
+ virtual asynStatus getMaxAcceleration( PIasynAxis* pAxis );
+ virtual asynStatus hasReferenceSensor(PIasynAxis* pAxis);
+ virtual asynStatus getReferencedState(PIasynAxis* axis);
+ virtual asynStatus referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards);
+
+ virtual bool IsGCS2() { return false; }
+
+protected:
+ virtual asynStatus findConnectedAxes();
+ enum
+ {
+ PI_PARA_C702_REFERENCED = 0x000001CUL
+ };
+
+private:
+ epicsTimeStamp m_timeREFstarted;
+};
+
+#endif /* PIC702CONTROLLER_H_ */
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIE517Controller.cpp b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIE517Controller.cpp
new file mode 100755
index 00000000..22b5b552
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIE517Controller.cpp
@@ -0,0 +1,73 @@
+/*
+ * PIGCSPiezoController
+ *
+ * Created on: 15.12.2010
+ * Author: sra
+ */
+
+#include "PIE517Controller.h"
+#include "PIasynAxis.h"
+#include
+#include
+
+#undef asynPrint
+#define asynPrint(user,reason,format...) 0
+
+
+asynStatus PIE517Controller::init()
+{
+ asynStatus status;
+ status = PIGCSPiezoController::init();
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+
+ // all output channels need to be set "online" before
+ // any commands are accepted over the interface.
+ status = getNrOutputChannels();
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+ for (int ch=1; ch<=m_nrOutputChannels; ch++)
+ {
+ status = setOnline(ch, 1);
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+ }
+
+ return status;
+}
+
+asynStatus PIE517Controller::setOnline(int channel, int onlineState)
+{
+ char cmd[100];
+ sprintf(cmd, "ONL %d %d", channel, onlineState);
+ asynStatus status = sendOnly(cmd);
+ return status;
+}
+
+asynStatus PIE517Controller::getNrOutputChannels()
+{
+ char buf[255];
+ asynStatus status = sendAndReceive("TPC?", buf, 99);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ m_nrOutputChannels = atoi(buf);
+ return status;
+
+}
+
+asynStatus PIE517Controller::initAxis(PIasynAxis* pAxis)
+{
+ pAxis->m_movingStateMask = pow(2.0, pAxis->getAxisNo());
+
+ return setServo(pAxis, 1);
+}
+
+
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIE517Controller.h b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIE517Controller.h
new file mode 100755
index 00000000..f17724f6
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIE517Controller.h
@@ -0,0 +1,42 @@
+/*
+ * PIGCScontroller.h
+ *
+ * Created on: 15.12.2010
+ * Author: sra
+ */
+
+#ifndef PIE517CONTROLLER_H_
+#define PIE517CONTROLLER_H_
+
+#include "PIGCSPiezoController.h"
+
+/**
+ * class representing PI E-517 and E-545 controllers.
+ *
+ * Basically these controllers have the same functionality as a
+ * digital piezo controller. Specialties are "velocity control" mode
+ * and the "online" state. Output channels must be set to "online" mode
+ * before commands are accepted over the interface. This is done in
+ * init()
+ */
+class PIE517Controller : public PIGCSPiezoController
+{
+public:
+ PIE517Controller(asynUser* pCom, const char* szIDN)
+ : PIGCSPiezoController(pCom, szIDN)
+ {
+ }
+ ~PIE517Controller() {}
+
+ virtual asynStatus init(void);
+ virtual asynStatus initAxis(PIasynAxis* pAxis);
+
+private:
+ asynStatus setOnline(int outputChannel, int onlineState);
+ asynStatus getNrOutputChannels();
+
+ int m_nrOutputChannels;
+
+};
+
+#endif /* PIE517CONTROLLER_H_ */
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIE755Controller.cpp b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIE755Controller.cpp
new file mode 100755
index 00000000..725f6a01
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIE755Controller.cpp
@@ -0,0 +1,40 @@
+/*
+ * PIE755Controller
+ *
+ * Author: sra
+ */
+
+#include "PIE755Controller.h"
+#include "PIasynAxis.h"
+#include
+
+#undef asynPrint
+#define asynPrint(user,reason,format...) 0
+
+
+asynStatus PIE755Controller::getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl)
+{
+ int busy;
+ asynStatus status = getBusy(pAxis, busy);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+
+ negLimit = 0;
+ posLimit = 0;
+ homing = busy;
+ if (busy)
+ {
+ moving = busy;
+ return status;
+ }
+
+ status = getMoving(pAxis, moving);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+
+ return status;
+}
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIE755Controller.h b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIE755Controller.h
new file mode 100755
index 00000000..3f0e9687
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIE755Controller.h
@@ -0,0 +1,41 @@
+/*
+ * PIE755Controller.h
+ *
+ * Author: sra
+ */
+
+#ifndef PIE755CONTROLLER_H_
+#define PIE755CONTROLLER_H_
+
+#include "PIGCSMotorController.h"
+
+/**
+ * class representing PI E-755.
+ *
+ * These controllers share most of the parameters with digital piezo controllers.
+ * Encoders for Nexline stages are often only incremental, so they need to be homed.
+ * Homing works with "hard stops" and "Limit switches".
+ * From an EPICS point of view this behaves more like a motor than a piezo controller.
+ */
+class PIE755Controller : public PIGCSMotorController
+{
+public:
+ PIE755Controller(asynUser* pCom, const char* szIDN)
+ : PIGCSMotorController(pCom, szIDN)
+ {
+ }
+ ~PIE755Controller() {}
+
+ virtual asynStatus getResolution(PIasynAxis* pAxis, double& resolution )
+ {
+ return PIGCSController::getResolution(pAxis, resolution);
+ }
+ virtual asynStatus setAccelerationCts( PIasynAxis* pAxis, double acceleration) { return asynSuccess; }
+ virtual asynStatus setAcceleration( PIasynAxis* pAxis, double acceleration) { return asynSuccess; }
+ virtual asynStatus getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl);
+
+private:
+
+};
+
+#endif /* PIE755CONTROLLER_H_ */
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSController.cpp b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSController.cpp
new file mode 100755
index 00000000..80357598
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSController.cpp
@@ -0,0 +1,811 @@
+/*
+ * PIGCSController.cpp
+ *
+ * Created on: 15.12.2010
+ * Author: sra
+ */
+
+#include
+#include
+#include
+#include "PIGCSController.h"
+#include "PIasynAxis.h"
+#include "PIGCSMotorController.h"
+#include "PIGCSPiezoController.h"
+#include "PIE517Controller.h"
+#include "PIE755Controller.h"
+#include "PIHexapodController.h"
+#include "PIC702Controller.h"
+
+
+//#undef asynPrint
+//#define asynPrint(user,reason,format...) 0
+
+
+extern "C" {
+int TranslatePIError(const int error, char* szBuffer, const int maxlen);
+}
+
+double PIGCSController::TIMEOUT = 5.0;
+
+/**
+ * create instance of GCS controller depending on identification (\a szIDN)
+ */
+PIGCSController* PIGCSController::CreateGCSController(asynUser* pInterface, const char* szIDN)
+{
+ if ( strstr(szIDN, "C-663") != NULL
+ || strstr(szIDN, "C-863") != NULL
+ || strstr(szIDN, "C-867") != NULL
+ )
+ {
+ return new PIGCSMotorController(pInterface, szIDN);
+ }
+ else if ( strstr(szIDN, "E-517") != NULL)
+ {
+ return new PIE517Controller(pInterface, szIDN);
+ }
+ else if ( strstr(szIDN, "E-755") != NULL)
+ {
+ return new PIE755Controller(pInterface, szIDN);
+ }
+ else if ( strstr(szIDN, "C-702") != NULL)
+ {
+ return new PIC702Controller(pInterface, szIDN);
+ }
+ else if ( strstr(szIDN, "HEXAPOD") != NULL
+ || strstr(szIDN, "F-HEX") != NULL
+ || strstr(szIDN, "F-206") != NULL
+ || strstr(szIDN, "M-8") != NULL
+ || strstr(szIDN, "C-887") != NULL
+ )
+ {
+ return new PIHexapodController(pInterface, szIDN);
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+asynStatus PIGCSController::sendOnly(asynUser* pInterface, const char *outputBuff, asynUser* logSink)
+{
+ size_t nRequested=strlen(outputBuff);
+ size_t nActual;
+ asynStatus status;
+
+ asynPrint(logSink, ASYN_TRACEIO_DRIVER,
+ "PIGCSController::sendOnly() sending \"%s\"\n", outputBuff);
+ //printf("PIGCSController::sendOnly() sending \"%s\"\n", outputBuff);
+
+ status = pasynOctetSyncIO->write(pInterface, outputBuff,
+ nRequested, TIMEOUT, &nActual);
+ if (nActual != nRequested)
+ status = asynError;
+ status = pasynOctetSyncIO->write(pInterface, "\n",
+ 1, TIMEOUT, &nActual);
+ if (status != asynSuccess)
+ {
+ asynPrint(logSink, ASYN_TRACE_ERROR|ASYN_TRACEIO_DRIVER,
+ "PIGCSController:sendOnly: error sending command %s, sent=%d, status=%d\n",
+ outputBuff, nActual, status);
+ }
+ return(status);
+}
+
+asynStatus PIGCSController::sendOnly(asynUser* pInterface, char c, asynUser* logSink)
+{
+ size_t nActual;
+ asynStatus status;
+
+ asynPrint(logSink, ASYN_TRACEIO_DRIVER,
+ "PIGCSController::sendOnly() sending \"#%d\"\n", int(c));
+ //printf("PIGCSController::sendOnly() sending \"#%d\"\n", int(c));
+
+ status = pasynOctetSyncIO->write(pInterface, &c,
+ 1, TIMEOUT, &nActual);
+ if (nActual != 1)
+ status = asynError;
+ if (status != asynSuccess)
+ {
+ asynPrint(logSink, ASYN_TRACE_ERROR|ASYN_TRACEIO_DRIVER,
+ "PIGCSController:sendOnly: error sending command %d, sent=%d, status=%d\n",
+ int(c), nActual, status);
+ //printf("PIGCSController::sendOnly() sending \"#%d\"\n", int(c));
+ }
+ return(status);
+}
+
+
+asynStatus PIGCSController::sendAndReceive(asynUser* pInterface, const char *outputBuff, char *inputBuff, int inputSize, asynUser* logSink)
+{
+ size_t nWriteRequested=strlen(outputBuff);
+ size_t nWrite, nRead;
+ int eomReason;
+ asynStatus status;
+ size_t pos = 0;
+ asynPrint(logSink, ASYN_TRACEIO_DRIVER,
+ "PIGCSController::sendAndReceive() sending \"%s\"\n", outputBuff);
+// //printf("PIGCSController::sendAndReceive() sending \"%s\"\n", outputBuff);
+
+ status = pasynOctetSyncIO->write(pInterface, outputBuff,
+ nWriteRequested, TIMEOUT, &nWrite);
+ if (nWrite != nWriteRequested)
+ {
+ asynPrint(logSink, ASYN_TRACE_ERROR|ASYN_TRACEIO_DRIVER,
+ "PIGCSController:sendAndReceive error calling write, output=%s status=%d, error=%s\n",
+ outputBuff, status, pInterface->errorMessage);
+ return asynError;
+ }
+
+ status = pasynOctetSyncIO->writeRead(pInterface,
+ "\n", 1,
+ inputBuff, inputSize,
+ TIMEOUT, &nWrite, &nRead, &eomReason);
+ if (nWrite != 1)
+ {
+ asynPrint(logSink, ASYN_TRACE_ERROR|ASYN_TRACEIO_DRIVER,
+ "PIGCSController:sendAndReceive error calling write, output=%s status=%d, error=%s\n",
+ outputBuff, status, pInterface->errorMessage);
+ return asynError;
+ }
+
+ if (status != asynSuccess)
+ {
+ asynPrint(logSink, ASYN_TRACE_ERROR|ASYN_TRACEIO_DRIVER,
+ "PIGCSController:sendAndReceive error calling writeRead, output=%s status=%d, error=%s\n",
+ outputBuff, status, pInterface->errorMessage);
+ }
+ while(inputBuff[strlen(inputBuff)-1] == ' ')
+ {
+ inputBuff[strlen(inputBuff)] = '\n';
+ pos += nRead + 1;
+ status = pasynOctetSyncIO->read(logSink,
+ inputBuff+pos, inputSize-pos,
+ TIMEOUT, &nRead, &eomReason);
+
+ }
+ asynPrint(logSink, ASYN_TRACEIO_DRIVER,
+ "PIGCSController::sendAndReceive() received \"%s\"\n", inputBuff);
+ // //printf("PIGCSController::sendAndReceive() received \"%s\"\n", inputBuff);
+
+ return(status);
+}
+
+asynStatus PIGCSController::sendOnly(const char *outputBuff)
+{
+ asynUser* logSink = m_pCurrentLogSink;
+ if (NULL == logSink)
+ logSink = m_pInterface;
+ m_interfaceMutex.lock();
+ asynStatus status = sendOnly(m_pInterface, outputBuff, logSink);
+ m_interfaceMutex.unlock();
+ return status;
+}
+
+asynStatus PIGCSController::sendOnly(char c)
+{
+ asynUser* logSink = m_pCurrentLogSink;
+ if (NULL == logSink)
+ logSink = m_pInterface;
+ m_interfaceMutex.lock();
+ asynStatus status = sendOnly(m_pInterface, c, logSink);
+ m_interfaceMutex.unlock();
+ return status;
+}
+
+asynStatus PIGCSController::sendAndReceive(char c, char *inputBuff, int inputSize)
+{
+ asynUser* logSink = m_pCurrentLogSink;
+ if (NULL == logSink)
+ logSink = m_pInterface;
+ m_interfaceMutex.lock();
+ asynStatus status = sendAndReceive(m_pInterface, c, inputBuff, inputSize, logSink);
+ m_interfaceMutex.unlock();
+ return status;
+}
+
+asynStatus PIGCSController::sendAndReceive(const char* output, char *inputBuff, int inputSize)
+{
+ asynUser* logSink = m_pCurrentLogSink;
+ if (NULL == logSink)
+ logSink = m_pInterface;
+ m_interfaceMutex.lock();
+ asynStatus status = sendAndReceive(m_pInterface, output, inputBuff, inputSize, logSink);
+ m_interfaceMutex.unlock();
+ return status;
+}
+
+asynStatus PIGCSController::sendAndReceive(asynUser* pInterface, char c, char *inputBuff, int inputSize, asynUser* logSink)
+{
+ size_t nWrite, nRead;
+ int eomReason;
+ asynStatus status;
+ size_t pos = 0;
+
+ asynPrint(logSink, ASYN_TRACEIO_DRIVER,
+ "PIGCSController::sendAndReceive() sending \"#%d\"\n", int(c));
+ //printf("PIGCSController::sendAndReceive() sending \"#%d\"\n", int(c));
+ status = pasynOctetSyncIO->writeRead(pInterface,
+ &c, 1,
+ inputBuff, inputSize,
+ TIMEOUT, &nWrite, &nRead, &eomReason);
+ if (nWrite != 1)
+ status = asynError;
+
+ if (status != asynSuccess)
+ {
+ asynPrint(logSink, ASYN_TRACE_ERROR|ASYN_TRACEIO_DRIVER,
+ "PIGCSController::sendAndReceive error calling writeRead, output=%d status=%d, error=%s\n",
+ int(c), status, pInterface->errorMessage);
+ //printf("PIGCSController::sendAndReceive error calling writeRead, output=%d status=%d, error=%s\n", int(c), status, pInterface->errorMessage);
+ }
+
+ while(inputBuff[strlen(inputBuff)-1] == ' ')
+ {
+ pos += nRead;
+ status = pasynOctetSyncIO->writeRead(logSink,
+ &c, 1,
+ inputBuff+pos, inputSize-pos,
+ TIMEOUT, &nWrite, &nRead, &eomReason);
+//printf("PIGCSController::sendAndReceive(char) in while loop. inputBuff: \"%s\"\n", inputBuff);
+ }
+ asynPrint(logSink, ASYN_TRACEIO_DRIVER,
+ "PIGCSController::sendAndReceive() received \"%s\"\n", inputBuff);
+ //printf("PIGCSController::sendAndReceive() received \"%s\" - (0x%02X)\n", inputBuff, int(inputBuff[0]));
+
+ return(status);
+}
+
+asynStatus PIGCSController::setVelocityCts( PIasynAxis* pAxis, double velocity )
+{
+ char cmd[100];
+ velocity = fabs(velocity) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator;
+ sprintf(cmd,"VEL %s %f", pAxis->m_szAxisName, velocity);
+ asynStatus status = sendOnly(cmd);
+ if (asynSuccess == status)
+ {
+ pAxis->m_velocity = velocity;
+ }
+ return status;
+}
+
+asynStatus PIGCSController::moveCts( PIasynAxis** pAxesArray, int* pTargetCtsArray, int numAxes)
+{
+//TODO: "Use MVE or set vel/acc so axes reach target at the same time""
+
+
+ asynStatus status;
+ char cmd[1000] = "MOV";
+ char subCmd[100];
+ for (int axis = 0; axis m_CPUdenominator / pAxis->m_CPUnumerator;
+ sprintf(subCmd," %s %f", pAxis->m_szAxisName, target);
+ strcat(cmd, subCmd);
+ pAxis->m_lastDirection = (pTargetCtsArray[axis] > pAxis->m_positionCts) ? 1 : 0;
+ }
+ status = sendOnly(cmd);
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+ int errorCode = getGCSError();
+ if (errorCode == 0)
+ return asynSuccess;
+
+ asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
+ "PIGCSController::moveCts(array) failed, GCS error %d\n", errorCode);
+ return asynError;
+}
+
+
+
+asynStatus PIGCSController::moveCts( PIasynAxis* pAxis, int targetCts )
+{
+ asynStatus status;
+ char cmd[100];
+ double target = double(targetCts) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator;
+ asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
+ "PIGCSController::moveCts(, %d) \n", targetCts);
+ return move(pAxis, target);
+}
+
+asynStatus PIGCSController::move( PIasynAxis* pAxis, double target )
+{
+ asynStatus status;
+ char cmd[100];
+ sprintf(cmd,"MOV %s %f", pAxis->m_szAxisName, target);
+ status = sendOnly(cmd);
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+ asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
+ "PIGCSController::move() sent \"%s\"\n", cmd);
+ pAxis->m_lastDirection = (target > pAxis->m_position) ? 1 : 0;
+ int errorCode = getGCSError();
+ if (errorCode == 0)
+ return asynSuccess;
+
+ asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
+ "PIGCSController::move() failed, GCS error %d\n", errorCode);
+ return asynError;
+}
+
+int PIGCSController::getGCSError()
+{
+ char buf[256];
+ asynStatus status = sendAndReceive("ERR?", buf, 255);
+ if (asynTimeout == status)
+ {
+ return COM_TIMEOUT;
+ }
+ else if (asynSuccess != status)
+ {
+ return COM_ERROR;
+ }
+ int errorCode = atoi(buf);
+ if (0 != errorCode)
+ {
+ m_LastError = errorCode;
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "PIGCSController::getGCSError() GCS error code = %d\n",
+ errorCode);
+ char szErrorMsg[1024];
+ if (TranslatePIError(errorCode, szErrorMsg, 1024))
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "PIGCSController::getGCSError() GCS error, %s\n",
+ szErrorMsg);
+
+ }
+ }
+ return errorCode;
+}
+
+asynStatus PIGCSController::haltAxis(PIasynAxis* pAxis)
+{
+ char cmd[100];
+ sprintf(cmd,"HLT %s", pAxis->m_szAxisName);
+ asynStatus status = sendOnly(cmd);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ int err = getGCSError();
+ // controller will set error code to PI_CNTR_STOP (10)
+ if (err != PI_CNTR_STOP)
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
+ "PIGCSController::haltAxis() failed, GCS error %d", err);
+ return asynError;
+ }
+ return status;
+}
+
+/**
+ * get position of axis in physical units (EGU) as defined on the controller
+ */
+asynStatus PIGCSController::getAxisPosition(PIasynAxis* pAxis, double& position)
+{
+ char cmd[100];
+ char buf[255];
+ sprintf(cmd, "POS? %s", pAxis->m_szAxisName);
+ asynStatus status = sendAndReceive(cmd, buf, 99);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ if (!getValue(buf, position))
+ {
+ status = asynError;
+ }
+ return status;
+}
+
+/**
+ * get velocity of axis in physical units (EGU) as defined on the controller
+ * and set PIasynAxis::m_velocity
+ */
+asynStatus PIGCSController::getAxisVelocity(PIasynAxis* pAxis)
+{
+ char cmd[100];
+ char buf[255];
+ sprintf(cmd, "VEL? %s", pAxis->m_szAxisName);
+ asynStatus status = sendAndReceive(cmd, buf, 99);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ if (!getValue(buf, pAxis->m_velocity))
+ {
+ status = asynError;
+ }
+ return status;
+
+}
+
+/**
+ * Find travel range for axis.
+ */
+asynStatus PIGCSController::getTravelLimits(PIasynAxis* pAxis, double& negLimit, double& posLimit)
+{
+ char cmd[100];
+ char buf[255];
+ sprintf(cmd, "TMN? %s", pAxis->m_szAxisName);
+ asynStatus status = sendAndReceive(cmd, buf, 99);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ if (!getValue(buf, negLimit))
+ {
+ return asynError;
+ }
+ sprintf(cmd, "TMX? %s", pAxis->m_szAxisName);
+ status = sendAndReceive(cmd, buf, 99);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ if (!getValue(buf, posLimit))
+ {
+ return asynError;
+ }
+
+ return status;
+}
+
+asynStatus PIGCSController::hasLimitSwitches(PIasynAxis* pAxis)
+{
+ char cmd[100];
+ char buf[255];
+ sprintf(cmd, "LIM? %s", pAxis->m_szAxisName);
+ asynStatus status = sendAndReceive(cmd, buf, 99);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ if (!getValue(buf, pAxis->m_bHasLimitSwitches))
+ {
+ return asynError;
+ }
+ if (!pAxis->m_bHasLimitSwitches)
+ {
+ sprintf(cmd, "HAR? %s", pAxis->m_szAxisName);
+ asynStatus status = sendAndReceive(cmd, buf, 99);
+ if (status == asynSuccess)
+ {
+ if (!getValue(buf, pAxis->m_bHasLimitSwitches))
+ {
+ return asynError;
+ }
+ }
+ else if (status == asynTimeout)
+ {
+ int err = getGCSError();
+ if (err == PI_CNTR_UNKNOWN_COMMAND)
+ {
+ // "HAR?" not known
+ pAxis->m_bHasLimitSwitches = false;
+ }
+ else
+ {
+ return status;
+ }
+ }
+ else
+ {
+ return status;
+ }
+ }
+
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
+ "PIGCSController::hasLimitSwitches() axis has %slimit switches\n",
+ pAxis->m_bHasLimitSwitches?"":"no ");
+ return status;
+}
+
+asynStatus PIGCSController::hasReferenceSensor(PIasynAxis* pAxis)
+{
+ char cmd[100];
+ char buf[255];
+ sprintf(cmd, "TRS? %s", pAxis->m_szAxisName);
+ asynStatus status = sendAndReceive(cmd, buf, 99);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+
+ if (!getValue(buf, pAxis->m_bHasReference))
+ {
+ return asynError;
+ }
+
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
+ "PIGCSController::hasReferenceSwitch() axis has %sreference sensor\n",
+ pAxis->m_bHasReference?"":"no ");
+ return status;
+}
+
+/**
+ * get position of axis in counts as used in EPICS.
+ * getAxisPosition() is called and position is covnerted to counts using the
+ * counts-per-unit (CPU) fraction of the axis.
+ */
+asynStatus PIGCSController::getAxisPositionCts(PIasynAxis* pAxis)
+{
+ double pos;
+ asynStatus status = getAxisPosition(pAxis, pos);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ pAxis->m_position = pos;
+ if (pAxis->m_CPUdenominator==0 || pAxis->m_CPUnumerator==0)
+ {
+ pAxis->m_positionCts = pos;
+ return status;
+ }
+
+ pAxis->m_positionCts = int( (pos * double(pAxis->m_CPUnumerator) / double(pAxis->m_CPUdenominator))+0.5);
+ if (m_pCurrentLogSink != NULL)
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
+ "PIGCSController::getAxisPositionCts() pos:%d\n",
+ pAxis->m_positionCts);
+ }
+ return status;
+}
+
+//void PIGCSController::calcAxisPositionCts();
+
+asynStatus PIGCSController::setServo(PIasynAxis* pAxis, int servoState)
+{
+ char cmd[100];
+ sprintf(cmd, "SVO %s %d", pAxis->m_szAxisName, servoState);
+ asynStatus status = sendOnly(cmd);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ int err = getGCSError();
+ if (COM_NO_ERROR == err)
+ {
+ pAxis->m_bServoControl = (servoState == 1);
+ if (pAxis->m_bProblem && pAxis->m_bServoControl)
+ {
+ pAxis->m_bProblem = false;
+ }
+ return asynSuccess;
+ }
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "Could not set servo state!\n");
+ return asynError;
+
+}
+
+asynStatus PIGCSController::getMoving(PIasynAxis* pAxis, int& moving)
+{
+ char buf[255];
+ asynStatus status = sendAndReceive(char(5), buf, 99);;
+ if (status != asynSuccess)
+ {
+//printf("PIGCSController::getMoving() failed, status %d", status);
+return status;
+ }
+
+ char* pStr;
+ long movingState = strtol(buf, &pStr, 16);
+ moving = (movingState & pAxis->m_movingStateMask) != 0 ? 1 : 0;
+
+ return status;
+}
+
+asynStatus PIGCSController::getBusy(PIasynAxis* pAxis, int& busy)
+{
+ char buf[255];
+ asynStatus status = sendAndReceive(char(7), buf, 99);;
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+
+ unsigned char c = (unsigned char)buf[0];
+ busy = (c==0xB0);
+
+ return status;
+}
+
+asynStatus PIGCSController::setGCSParameter(PIasynAxis* pAxis, unsigned int paramID, double value)
+{
+ char cmd[100];
+ sprintf(cmd, "SPA %s %d %.12g", pAxis->m_szAxisName, paramID, value);
+ asynStatus status = sendOnly(cmd);
+ return status;
+}
+
+asynStatus PIGCSController::getGCSParameter(PIasynAxis* pAxis, unsigned int paramID, double& value)
+{
+ char cmd[100];
+ char buf[255];
+ sprintf(cmd, "SPA? %s %d", pAxis->m_szAxisName, paramID);
+ asynStatus status = sendAndReceive(cmd, buf, 99);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+
+ if (!getValue(buf, value))
+ {
+ return asynError;
+ }
+ return status;
+
+}
+
+PIGCSController::PIGCSController(asynUser* pCom, const char* szIDN)
+: m_pCurrentLogSink(NULL)
+, m_bAnyAxisMoving(false)
+, m_pInterface(pCom)
+, m_nrFoundAxes(0)
+, m_LastError(0)
+{
+ strncpy(szIdentification, szIDN, 199);
+}
+
+PIGCSController::~PIGCSController()
+{
+}
+
+asynStatus PIGCSController::initAxis(PIasynAxis* pAxis)
+{
+ // read stage name - to have it in logfile and find
+ // problems because of mis/non-configured controllers
+ char cmd[100];
+ char buf[255];
+ sprintf(cmd, "CST? %s", pAxis->m_szAxisName);
+ asynStatus status = sendAndReceive(cmd, buf, 99);;
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ if (NULL != m_pCurrentLogSink)
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
+ "PIGCSController::initAxis() stage configuration: %s\n", buf);
+ }
+ pAxis->m_movingStateMask = pow(2.0, pAxis->getAxisNo());
+
+ return setServo(pAxis, 1);
+}
+
+asynStatus PIGCSController::init(void)
+{
+ asynStatus status;
+ status = findConnectedAxes();
+ return status;
+}
+
+asynStatus PIGCSController::findConnectedAxes()
+{
+ m_nrFoundAxes = 0;
+ for (size_t i=0; im_szAxisName);
+ asynStatus status = sendAndReceive(cmd, buf, 99);;
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ if (getValue(buf, pAxis->m_homed))
+ {
+ return asynError;
+ }
+ return status;
+}
+
+asynStatus PIGCSController::getResolution(PIasynAxis* pAxis, double& resolution )
+{
+ resolution = 0.0001;
+ pAxis->m_CPUnumerator = 10000;
+ pAxis->m_CPUdenominator = 1;
+ return asynSuccess;
+}
+
+asynStatus PIGCSController::SetPivotX(double value)
+{
+ if (NULL != m_pCurrentLogSink)
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
+ "PIGCSController::SetPivotX() ignored");
+ }
+ return asynSuccess;
+}
+
+asynStatus PIGCSController::SetPivotY(double value)
+{
+ if (NULL != m_pCurrentLogSink)
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
+ "PIGCSController::SetPivotY() ignored");
+ }
+ return asynSuccess;
+}
+
+asynStatus PIGCSController::SetPivotZ(double value)
+{
+ if (NULL != m_pCurrentLogSink)
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
+ "PIGCSController::SetPivotZ() ignored");
+ }
+ return asynSuccess;
+}
+
+bool PIGCSController::getValue(const char* szMsg, double& value)
+{
+ const char* p = strstr(szMsg, "=");
+ if (p==NULL || *p == '\0')
+ {
+ return false;
+ }
+ value = atof(p+1);
+ return true;
+}
+
+bool PIGCSController::getValue(const char* szMsg, int& value)
+{
+ const char* p = strstr(szMsg, "=");
+ if (p==NULL || *p == '\0')
+ {
+ return false;
+ }
+ value = atoi(p+1);
+ return true;
+}
+
+bool PIGCSController::getValue(const char* szMsg, bool& value)
+{
+ const char* p = strstr(szMsg, "=");
+ if (p==NULL || *p == '\0')
+ {
+ return false;
+ }
+ int ivalue = atoi(p+1);
+ value = (ivalue =! 0);
+ return true;
+}
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSController.h b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSController.h
new file mode 100755
index 00000000..361f91e2
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSController.h
@@ -0,0 +1,114 @@
+/*
+ * PIGCScontroller.h
+ *
+ * Created on: 15.12.2010
+ * Author: sra
+ */
+
+#ifndef PIGCSCONTROLLER_H_
+#define PIGCSCONTROLLER_H_
+
+#include
+#include
+#include
+#include "picontrollererrors.h"
+
+
+class PIasynAxis;
+class asynMotorAxis;
+
+/**
+ * Base class for all PI GCS(2) controllers.
+ *
+ * Most functions will be implemented here, since for basic functionality
+ * GCS commands are always the same.
+ */
+class PIGCSController
+{
+public:
+ PIGCSController(asynUser* pCom, const char* szIDN);
+ virtual ~PIGCSController();
+
+ static PIGCSController* CreateGCSController(asynUser* pCom, const char* szIDN);
+
+ virtual asynStatus init(void);
+ virtual asynStatus initAxis(PIasynAxis* pAxis);
+
+ static asynStatus sendOnly(asynUser* pInterface, char c, asynUser* logSink);
+ static asynStatus sendOnly(asynUser* pInterface, const char *outputBuff, asynUser* logSink);
+ static asynStatus sendAndReceive(asynUser* pInterface, const char *outputBuff, char *inputBuff, int inputSize, asynUser* logSink);
+ static asynStatus sendAndReceive(asynUser* pInterface, char c, char *inputBuff, int inputSize, asynUser* logSink);
+
+ bool getValue(const char* szMsg, double& value);
+ bool getValue(const char* szMsg, int& value);
+ bool getValue(const char* szMsg, bool& value);
+
+ virtual asynStatus setVelocityCts( PIasynAxis* pAxis, double velocity );
+ virtual asynStatus setAccelerationCts( PIasynAxis* pAxis, double acceleration) { return asynSuccess; }
+ virtual asynStatus setAcceleration( PIasynAxis* pAxis, double acceleration) { return asynSuccess; }
+ virtual asynStatus move( PIasynAxis* pAxis, double target);
+ virtual asynStatus moveCts( PIasynAxis* pAxis, int target);
+ virtual asynStatus moveCts( PIasynAxis** pAxesArray, int* pTargetCtsArray, int numAxes);
+ virtual asynStatus referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards) { return asynSuccess; }
+ virtual asynStatus haltAxis(PIasynAxis* pAxis);
+
+ virtual asynStatus getAxisPosition(PIasynAxis* pAxis, double& position);
+ virtual asynStatus getAxisVelocity(PIasynAxis* pAxis);
+ virtual asynStatus getAxisPositionCts(PIasynAxis* pAxis);
+ virtual asynStatus setServo(PIasynAxis* pAxis, int servoState);
+ virtual asynStatus getResolution(PIasynAxis* pAxis, double& resolution );
+ virtual asynStatus getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl) = 0;
+ virtual asynStatus getGlobalState( asynMotorAxis** Axes, int numAxes ) { return asynSuccess; }
+ virtual asynStatus getMoving(PIasynAxis* pAxis, int& homing);
+ virtual asynStatus getBusy(PIasynAxis* pAxis, int& busy);
+ virtual asynStatus getTravelLimits(PIasynAxis* pAxis, double& negLimit, double& posLimit);
+ virtual asynStatus hasLimitSwitches(PIasynAxis* pAxis);
+ virtual asynStatus hasReferenceSensor(PIasynAxis* pAxis);
+ virtual asynStatus getReferencedState(PIasynAxis* axis);
+
+ virtual asynStatus SetPivotX(double value);
+ virtual asynStatus SetPivotY(double value);
+ virtual asynStatus SetPivotZ(double value);
+
+ virtual double GetPivotX() { return 0.0; }
+ virtual double GetPivotY() { return 0.0; }
+ virtual double GetPivotZ() { return 0.0; }
+
+ virtual bool AcceptsNewTarget() { return true; }
+ virtual bool CanCommunicateWhileHoming() { return true; }
+
+ asynStatus sendOnly(const char *outputBuff);
+ asynStatus sendOnly(char c);
+ asynStatus sendAndReceive(const char *outputBuff, char *inputBuff, int inputSize);
+ asynStatus sendAndReceive(char c, char *inputBuff, int inputSize);
+
+ const char* getAxesID(size_t axisIdx) { return m_axesIDs[axisIdx]; }
+ size_t getNrFoundAxes() { return m_nrFoundAxes; }
+
+ virtual bool IsGCS2() { return true; }
+
+ int getGCSError();
+
+ int GetLastError() { return m_LastError; }
+
+ asynUser* m_pCurrentLogSink;
+ static const size_t MAX_NR_AXES = 64;
+ bool m_bAnyAxisMoving;
+protected:
+ asynStatus setGCSParameter(PIasynAxis* pAxis, unsigned int paramID, double value);
+ asynStatus getGCSParameter(PIasynAxis* pAxis, unsigned int paramID, double& value);
+
+ virtual asynStatus findConnectedAxes();
+
+ asynUser* m_pInterface;
+ epicsMutex m_interfaceMutex;
+ static double TIMEOUT;
+ char szIdentification[200];
+ int m_nrAxesOnController;
+ char* m_axesIDs[MAX_NR_AXES];
+ size_t m_nrFoundAxes;
+ char m_allAxesIDs[255];
+ int m_LastError;
+};
+
+#endif /* PIGCSCONTROLLER_H_ */
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSMotorController.cpp b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSMotorController.cpp
new file mode 100755
index 00000000..323bde9f
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSMotorController.cpp
@@ -0,0 +1,189 @@
+/*
+ * PIGCSMotorController.cpp
+ *
+ * Created on: 15.12.2010
+ * Author: sra
+ */
+
+#include "PIGCSMotorController.h"
+#include "PIasynAxis.h"
+#include
+#include
+
+//#undef asynPrint
+//#define asynPrint(user,reason,format...) 0
+
+
+asynStatus PIGCSMotorController::initAxis(PIasynAxis* pAxis)
+{
+ asynStatus status = hasLimitSwitches(pAxis);
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+ status = hasReferenceSensor(pAxis);
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+ return PIGCSController::initAxis(pAxis);
+}
+
+asynStatus PIGCSMotorController::setAccelerationCts( PIasynAxis* pAxis, double accelerationCts)
+{
+ double acceleration = fabs(accelerationCts) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator;
+ if (acceleration == pAxis->m_acceleration)
+ return asynSuccess;
+ if (pAxis->m_maxAcceleration < 0)
+ {
+ getMaxAcceleration(pAxis);
+ }
+ if (acceleration > pAxis->m_maxAcceleration)
+ acceleration = pAxis->m_maxAcceleration;
+
+ return setAcceleration(pAxis, acceleration);
+}
+
+asynStatus PIGCSMotorController::referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards)
+{
+ asynStatus status = setServo(pAxis, 1);
+ if (asynSuccess != status)
+ return status;
+
+ char cmd[100];
+ if (velocity != 0)
+ {
+ velocity = fabs(velocity) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator;
+ sprintf(cmd,"SPA %s 0x50 %f", pAxis->m_szAxisName, velocity);
+ sendOnly(cmd);
+ }
+
+ if (pAxis->m_bHasReference)
+ {
+ // call FRF - find reference
+ sprintf(cmd,"FRF %s", pAxis->m_szAxisName);
+ }
+ else if (pAxis->m_bHasLimitSwitches)
+ {
+ if (forwards)
+ {
+ // call FPL - find positive limit switch
+ sprintf(cmd,"FPL %s", pAxis->m_szAxisName);
+ }
+ else
+ {
+ // call FNL - find negative limit switch
+ sprintf(cmd,"FNL %s", pAxis->m_szAxisName);
+ }
+ }
+ else
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR,
+ "PIGCSMotorController::referenceVelCts() failed - axis has no reference/limit switch\n");
+ epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize,
+ "PIGCSMotorController::referenceVelCts() failed - axis has no reference/limit switch\n");
+ return asynError;
+ }
+ status = sendOnly(cmd);
+ if (asynSuccess != status)
+ return status;
+ int errorCode = getGCSError();
+ if (errorCode == 0)
+ {
+ return asynSuccess;
+ }
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR,
+ "PIGCSMotorController::referenceVelCts() failed\n");
+ epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize,
+ "PIGCSMotorController::referenceVelCts() failed - GCS Error %d\n",errorCode);
+ return asynError;
+
+}
+
+/**
+ * Get encoder resolution from counts-per-unit (CPU) fraction of the axis.
+ */
+asynStatus PIGCSMotorController::getResolution(PIasynAxis* pAxis, double& resolution )
+{
+ // CPU is "Counts Per Unit"
+ // this is stored as two integers in the controller
+ double num, denom;
+ asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_CPU_Z, num);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ status = getGCSParameter(pAxis, PI_PARA_MOT_CPU_N, denom);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ pAxis->m_CPUnumerator = num;
+ pAxis->m_CPUdenominator = denom;
+ resolution = double(pAxis->m_CPUdenominator) / double(pAxis->m_CPUnumerator) ;
+ return status;
+
+}
+
+asynStatus PIGCSMotorController::getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl)
+{
+ char buf[255];
+ asynStatus status = sendAndReceive(char(4), buf, 99);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ // TODO this is for a single axis C-863/867 controller!!!!
+ // TODO a) change it to multi-axis code.
+ // TODO b) support other controllers which do not understand #4 or have different bit masks
+
+ int idx = 2 + pAxis->getAxisNo()*4;
+ buf[idx+4] = '\0';
+ char* szMask = buf+idx;
+ long mask = strtol(szMask, NULL, 16);
+ moving = (mask & 0x2000) ? 1 : 0;
+ homing = (mask & 0x4000) ? 1 : 0;
+ negLimit = (mask & 0x0001) ? 1 : 0;
+ posLimit = (mask & 0x0004) ? 1 : 0;
+ servoControl = (mask & 0x1000) ? 1 : 0;
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
+ "PIGCSMotorController::getStatus() buf:%s moving %d, svo: %d\n",
+ buf, moving, servoControl);
+
+ return status;
+}
+
+asynStatus PIGCSMotorController::getMaxAcceleration(PIasynAxis* pAxis)
+{
+ double maxAcc, maxDec;
+ asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_MAX_ACCEL, maxAcc);
+ if (asynSuccess != status)
+ return status;
+ status = getGCSParameter(pAxis, PI_PARA_MOT_MAX_DECEL, maxDec);
+ if (asynSuccess != status)
+ return status;
+
+ if (maxAcc < maxDec)
+ {
+ pAxis->m_maxAcceleration = maxAcc;
+ }
+ else
+ {
+ pAxis->m_maxAcceleration = maxDec;
+ }
+ return status;
+}
+
+asynStatus PIGCSMotorController::setAcceleration( PIasynAxis* pAxis, double acceleration)
+{
+ asynStatus status = setGCSParameter(pAxis, PI_PARA_MOT_CURR_ACCEL, acceleration);
+ if (asynSuccess != status)
+ return status;
+ status = setGCSParameter(pAxis, PI_PARA_MOT_CURR_DECEL, acceleration);
+ if (asynSuccess != status)
+ return status;
+ pAxis->m_acceleration = acceleration;
+ return status;
+}
+
+
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSMotorController.h b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSMotorController.h
new file mode 100755
index 00000000..be8b7ec6
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSMotorController.h
@@ -0,0 +1,53 @@
+/*
+ * PIGCScontroller.h
+ *
+ * Created on: 15.12.2010
+ * Author: sra
+ */
+
+#ifndef PIGCSMOTORCONTROLLER_H_
+#define PIGCSMOTORCONTROLLER_H_
+
+#include "PIGCSController.h"
+#include
+
+/**
+ * class representing PI GCS2 motor controllers.
+ *
+ * "motor" does not strictly restrict the driving principle to DC stages or
+ * stepper but includes other controller families (e.g. for piezo motors) also.
+ */
+class PIGCSMotorController : public PIGCSController
+{
+public:
+ PIGCSMotorController(asynUser* pCom, const char* szIDN)
+ : PIGCSController(pCom, szIDN)
+ {
+ }
+ ~PIGCSMotorController() {}
+ virtual asynStatus initAxis(PIasynAxis* pAxis);
+
+ virtual asynStatus setAccelerationCts( PIasynAxis* pAxis, double acceleration);
+ virtual asynStatus setAcceleration( PIasynAxis* pAxis, double acceleration);
+ virtual asynStatus getMaxAcceleration( PIasynAxis* pAxis );
+ virtual asynStatus referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards);
+ virtual asynStatus getResolution(PIasynAxis* pAxis, double& resolution );
+ virtual asynStatus getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl);
+
+protected:
+ enum
+ {
+ PI_PARA_MOT_CURR_ACCEL = 0x000000BUL,
+ PI_PARA_MOT_CURR_DECEL = 0x000000CUL,
+ PI_PARA_MOT_CPU_Z = 0x000000EUL,
+ PI_PARA_MOT_CPU_N = 0x000000FUL,
+ PI_PARA_MOT_HAT_REF = 0x0000014UL,
+ PI_PARA_MOT_MAX_ACCEL = 0x000004AUL,
+ PI_PARA_MOT_MAX_DECEL = 0x000004BUL
+ };
+
+private:
+
+};
+
+#endif /* PIGCSMOTORCONTROLLER_H_ */
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSPiezoController.cpp b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSPiezoController.cpp
new file mode 100755
index 00000000..97d2c4d5
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSPiezoController.cpp
@@ -0,0 +1,37 @@
+/*
+ * PIGCSPiezoController
+ *
+ * Created on: 15.12.2010
+ * Author: sra
+ */
+
+#include "PIGCSPiezoController.h"
+#include "PIasynAxis.h"
+#include
+#include
+
+#undef asynPrint
+#define asynPrint(user,reason,format...) 0
+
+
+asynStatus PIGCSPiezoController::getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl)
+{
+ asynStatus status = getMoving(pAxis, moving);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+
+ homing = 0;
+ negLimit = 0;
+ posLimit = 0;
+
+ return status;
+}
+
+asynStatus PIGCSPiezoController::getReferencedState(PIasynAxis* pAxis)
+{
+ pAxis->m_homed = 1;
+ return asynSuccess;
+}
+
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSPiezoController.h b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSPiezoController.h
new file mode 100755
index 00000000..afe09386
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIGCSPiezoController.h
@@ -0,0 +1,38 @@
+/*
+ * PIGCScontroller.h
+ *
+ * Created on: 15.12.2010
+ * Author: sra
+ */
+
+#ifndef PIGCSPIEZOCONTROLLER_H_
+#define PIGCSPIEZOCONTROLLER_H_
+
+#include "PIGCSController.h"
+#include
+
+/**
+ * Class representing PI's GCS2 digital piezo controllers.
+ *
+ * Main difference to motor controllers is the usage of absolute sensors.
+ */
+class PIGCSPiezoController : public PIGCSController
+{
+public:
+ PIGCSPiezoController(asynUser* pCom, const char* szIDN)
+ : PIGCSController(pCom, szIDN)
+ {
+ }
+ ~PIGCSPiezoController() {}
+
+ virtual asynStatus init(void) { return PIGCSController::init(); }
+
+ virtual asynStatus getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl);
+ virtual asynStatus getReferencedState(PIasynAxis* pAxis);
+
+
+private:
+
+};
+
+#endif /* PIGCSPIEZOCONTROLLER_H_ */
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIHexapodController.cpp b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIHexapodController.cpp
new file mode 100755
index 00000000..399a3d8d
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIHexapodController.cpp
@@ -0,0 +1,444 @@
+/*
+ * PIE755Controller
+ *
+ * Author: sra
+ */
+
+#include "PIHexapodController.h"
+#include "PIasynAxis.h"
+#include
+#include
+
+//#undef asynPrint
+//#define asynPrint(user,reason,format...) 0
+
+asynStatus PIHexapodController::init(void)
+{
+ asynStatus status = PIGCSController::init();
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+
+ // Try to find out if #4 is supported
+ char buf[200];
+ status = sendAndReceive(char(4), buf, 199);
+ if (status == asynSuccess)
+ {
+ m_bCanReadStatusWithChar4 = true;
+ }
+ else if (status == asynTimeout)
+ {
+ m_bCanReadStatusWithChar4 = false;
+ getGCSError(); // clear error UNKNOWN COMMAND
+ }
+// status = sendAndReceive(char(3), buf, 199);
+// if (status == asynSuccess)
+// {
+// m_bCanReadPosWithChar3 = true;
+// }
+// else if (status == asynTimeout)
+ {
+ m_bCanReadPosWithChar3 = false;
+ getGCSError(); // clear error UNKNOWN COMMAND
+ }
+
+ m_bHoming = false;
+
+ ReadPivotSettings();
+
+ return status;
+}
+
+
+asynStatus PIHexapodController::getGlobalState(asynMotorAxis** pAxes, int numAxes)
+{
+ // do not call moving here, at least simulation software does return
+ // values != 0 with bit 1 not set (e.g. "2")
+ char buf[255];
+ asynStatus status = sendAndReceive(char(5), buf, 99);;
+ if (status != asynSuccess)
+ {
+printf("PIGCSController::getGlobalState() failed, status %d", status);
+return status;
+ }
+
+ char* pStr;
+ long moving = strtol(buf, &pStr, 16);
+ m_bAnyAxisMoving = (moving != 0);
+ if (m_bHoming && (moving == 0))
+ {
+ m_bHoming = false;
+ }
+ for(int i=0; im_bMoving = (moving != 0);
+ }
+ return asynSuccess;
+
+}
+
+asynStatus PIHexapodController::getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl)
+{
+ negLimit = 0;
+ posLimit = 0;
+ homing = m_bHoming ? 1:0;
+
+ moving = pAxis->m_bMoving || pAxis->deferred_move;
+ return asynSuccess;
+}
+
+asynStatus PIHexapodController::findConnectedAxes()
+{
+ for (size_t i=0; im_movingStateMask = 1;
+ return setServo(pAxis, 1);
+}
+
+asynStatus PIHexapodController::getReferencedState(PIasynAxis* pAxis)
+{
+ if (!m_bCanReadStatusWithChar4)
+ {
+ pAxis->m_homed = 1;
+ return asynSuccess;
+ }
+
+ char buf[255];
+ asynStatus status = sendAndReceive(char(4), buf, 99);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ long mask = strtol(buf, NULL, 10);
+ pAxis->m_homed = (mask & 0x10000) ? 1 : 0;
+ return status;
+}
+
+asynStatus PIHexapodController::moveCts( PIasynAxis* pAxis, int targetCts )
+{
+// printf("PIHexapodController::moveCts(,%d)...\n",targetCts);
+ asynStatus status;
+ char cmd[100];
+ double target = double(targetCts) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator;
+ sprintf(cmd,"MOV %s %f", pAxis->m_szAxisName, target);
+ status = sendOnly(cmd);
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+ epicsThreadSleep( 0.2 ); // TODO test if we do need this
+ asynMotorAxis* pAsynAxis = (asynMotorAxis*)pAxis;
+ status = getGlobalState(&pAsynAxis, 1);
+ if (asynSuccess != status)
+ {
+// printf("PIHexapodController::moveCts(,%d) - getGlobalState() failed, status=%d\n", targetCts, status);
+ return status;
+ }
+ if (!pAxis->m_bMoving)
+ {
+ int errorCode = getGCSError();
+// printf("PIHexapodController::moveCts(,%d) - not moving after MOV() gcserror=%d\n",targetCts, errorCode);
+ if (errorCode != 0)
+ {
+ asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
+ "PIHexapodController::moveCts() failed, GCS error %d\n", errorCode);
+ return asynError;
+ }
+ }
+ m_bAnyAxisMoving = true;
+ pAxis->m_lastDirection = (targetCts > pAxis->m_positionCts) ? 1 : 0;
+ printf("PIHexapodController::moveCts(,%d) - OK!\n",targetCts);
+ return status;
+}
+
+asynStatus PIHexapodController::moveCts( PIasynAxis** pAxesArray, int* pTargetCtsArray, int numAxes)
+{
+ asynStatus status;
+ char cmd[1000] = "MOV";
+ char subCmd[100];
+ for (int axis = 0; axis m_CPUdenominator / pAxis->m_CPUnumerator;
+ sprintf(subCmd," %s %f", pAxis->m_szAxisName, target);
+ strcat(cmd, subCmd);
+ pAxis->m_lastDirection = (pTargetCtsArray[axis] > pAxis->m_positionCts) ? 1 : 0;
+ }
+ status = sendOnly(cmd);
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+ epicsThreadSleep(0.2);
+ status = getGlobalState((asynMotorAxis**)pAxesArray, numAxes);
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+ if (!pAxesArray[0]->m_bMoving)
+ {
+ int errorCode = getGCSError();
+ if (errorCode != 0)
+ {
+ asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
+ "PIHexapodController::moveCts() failed, GCS error %d\n", errorCode);
+ return asynError;
+ }
+ }
+ m_bAnyAxisMoving = true;
+ return status;
+}
+
+
+asynStatus PIHexapodController::getAxisPosition(PIasynAxis* pAxis, double& position)
+{
+ if (!m_bAnyAxisMoving)
+ {
+ return PIGCSController::getAxisPosition(pAxis, position);
+ }
+ if (m_bCanReadPosWithChar3)
+ {
+ char buf[255];
+ asynStatus status = sendAndReceive(char(3), buf, 99);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ char *pStart = buf;
+ for(;;)
+ {
+ bool bEnd = false;
+ while(*pStart == ' ') pStart++;
+ char *pLF = strstr(pStart, "\n");
+ if (pLF != NULL)
+ {
+ *pLF = '\0';
+ }
+ else
+ {
+ bEnd = true;
+ }
+ // single line will look like "X = 1.0 \n"
+ if (pStart[0] == pAxis->m_szAxisName[0] )
+ {
+ double value;
+ if (!getValue(pStart, value))
+ {
+ return asynError;
+ }
+ position = value;
+ return status;
+ }
+ if (bEnd)
+ {
+ break;
+ }
+ pStart = pLF + 1;
+ if (*pStart == '\0')
+ {
+ break;
+ }
+ }
+ // should not come here!
+ return asynError;
+ }
+ // return last position
+ position = double(pAxis->m_positionCts) * double(pAxis->m_CPUdenominator) / double(pAxis->m_CPUnumerator);
+
+ return asynSuccess;
+}
+
+asynStatus PIHexapodController::SetPivotX(double value)
+{
+ if (NULL != m_pCurrentLogSink)
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
+ "PIHexapodController::SetPivotX() value %f", value);
+ }
+ asynStatus status = SetPivot('R', value);
+ if (status== asynSuccess)
+ {
+ m_PivotX = value;
+ }
+ return status;
+}
+
+asynStatus PIHexapodController::SetPivotY(double value)
+{
+ if (NULL != m_pCurrentLogSink)
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
+ "PIHexapodController::SetPivotY() value %f", value);
+ }
+ asynStatus status = SetPivot('S', value);
+ if (status== asynSuccess)
+ {
+ m_PivotY = value;
+ }
+ return status;
+}
+
+asynStatus PIHexapodController::SetPivotZ(double value)
+{
+ if (NULL != m_pCurrentLogSink)
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
+ "PIHexapodController::SetPivotZ() value %f", value);
+ }
+ asynStatus status = SetPivot('T', value);
+ if (status== asynSuccess)
+ {
+ m_PivotZ = value;
+ }
+ return status;
+}
+
+asynStatus PIHexapodController::SetPivot(char cAxis, double value)
+{
+ if (m_bAnyAxisMoving)
+ {
+ if (NULL != m_pCurrentLogSink)
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
+ "PIHexapodController::SetPivot() cannot change pivot point while platform is moving");
+ }
+ return asynError;
+ }
+
+ asynStatus status;
+ char cmd[100];
+ sprintf(cmd,"SPI %c %f", cAxis, value);
+ status = sendOnly(cmd);
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+
+ int errorCode = getGCSError();
+ if (errorCode != 0)
+ {
+ asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
+ "PIHexapodController::SetPivot() failed, GCS error %d\n", errorCode);
+ return asynError;
+ }
+ return status;
+
+}
+
+asynStatus PIHexapodController::ReadPivotSettings()
+{
+ char buf[100];
+ char cmd[] = "SPI? RST";
+ asynStatus status = sendAndReceive(cmd, buf, 99);
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ char* pStart = buf;
+ bool bEnd = false;
+ double px = 0.0;
+ double py = 0.0;
+ double pz = 0.0;
+ for(;;)
+ {
+ while(*pStart == ' ') pStart++;
+ char *pLF = strstr(pStart, "\n");
+ if (pLF != NULL)
+ {
+ *pLF = '\0';
+ }
+ else
+ {
+ bEnd = true;
+ }
+ // single line will look like "R = 1.0 \n"
+ double value;
+ if (!getValue(pStart, value))
+ {
+ return asynError;
+ }
+ switch(pStart[0])
+ {
+ case'R': px = value; break;
+ case'S': py = value; break;
+ case'T': pz = value; break;
+ }
+ if (bEnd)
+ {
+ break;
+ }
+ pStart = pLF + 1;
+ if (*pStart == '\0')
+ {
+ break;
+ }
+ }
+ m_PivotX = px;
+ m_PivotY = py;
+ m_PivotZ = pz;
+
+ return status;
+}
+
+asynStatus PIHexapodController::referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards)
+{
+ asynStatus status = sendOnly("INI X");
+ if (asynSuccess != status)
+ {
+ int errorCode = getGCSError();
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR,
+ "PIHexapodController::referenceVelCts() failed\n");
+ epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize,
+ "PIHexapodController::referenceVelCts() failed - GCS Error %d\n",errorCode);
+ return status;
+ }
+ m_bHoming = true;
+ return asynSuccess;
+}
+
+asynStatus PIHexapodController::haltAxis(PIasynAxis* pAxis)
+{
+ asynStatus status = sendOnly(char(24));
+ if (status != asynSuccess)
+ {
+ return status;
+ }
+ //epicsThreadSleep(0.1); // TODO test value
+ int err = getGCSError();
+ // controller will set error code to PI_CNTR_STOP (10)
+ if (err != PI_CNTR_STOP)
+ {
+ asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
+ "PIGCSController::haltAxis() failed, GCS error %d", err);
+ return asynError;
+ }
+ return status;
+}
+
+
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIHexapodController.h b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIHexapodController.h
new file mode 100755
index 00000000..bcf8ad50
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIHexapodController.h
@@ -0,0 +1,74 @@
+/*
+ * PIE755Controller.h
+ *
+ * Author: sra
+ */
+
+#ifndef PIHEXAPODCONTROLLER_H_
+#define PIHEXAPODCONTROLLER_H_
+
+#include "PIGCSController.h"
+
+/**
+ * class representing PI Hexapods.
+ */
+class PIHexapodController : public PIGCSController
+{
+public:
+ PIHexapodController(asynUser* pCom, const char* szIDN)
+ : PIGCSController(pCom, szIDN)
+ {
+ }
+ ~PIHexapodController() {}
+
+ virtual asynStatus init(void);
+ virtual asynStatus initAxis(PIasynAxis* pAxis);
+
+ virtual asynStatus setAccelerationCts( PIasynAxis* pAxis, double acceleration) { return asynSuccess; }
+ virtual asynStatus setAcceleration( PIasynAxis* pAxis, double acceleration) { return asynSuccess; }
+ virtual asynStatus getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl);
+ virtual asynStatus getGlobalState(asynMotorAxis** Axes, int numAxes);
+ virtual asynStatus getTravelLimits(PIasynAxis* pAxis, double& negLimit, double& posLimit)
+ {
+ negLimit = -100;
+ posLimit = 100;
+ return asynSuccess;
+ }
+ virtual asynStatus getReferencedState(PIasynAxis* pAxis);
+
+ virtual asynStatus haltAxis(PIasynAxis* pAxis);
+
+ virtual bool AcceptsNewTarget() { return !m_bAnyAxisMoving; }
+ virtual bool CanCommunicateWhileHoming() { return false; }
+
+ virtual asynStatus moveCts( PIasynAxis* pAxis, int target);
+ virtual asynStatus moveCts( PIasynAxis** pAxesArray, int* pTargetCtsArray, int numAxes);
+ virtual asynStatus getAxisPosition(PIasynAxis* pAxis, double& position);
+
+ virtual asynStatus SetPivotX(double value);
+ virtual asynStatus SetPivotY(double value);
+ virtual asynStatus SetPivotZ(double value);
+
+ virtual double GetPivotX() { return m_PivotX; }
+ virtual double GetPivotY() { return m_PivotY; }
+ virtual double GetPivotZ() { return m_PivotZ; }
+
+ virtual asynStatus referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards);
+
+protected:
+ virtual asynStatus findConnectedAxes();
+ asynStatus ReadPivotSettings();
+ asynStatus SetPivot(char cAxis, double value);
+
+ double m_PivotX;
+ double m_PivotY;
+ double m_PivotZ;
+
+ bool m_bHoming;
+
+private:
+ bool m_bCanReadStatusWithChar4;
+ bool m_bCanReadPosWithChar3;
+};
+
+#endif /* PIHEXAPODCONTROLLER_H_ */
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PI_GCS2Support.dbd b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PI_GCS2Support.dbd
new file mode 100755
index 00000000..34831af5
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PI_GCS2Support.dbd
@@ -0,0 +1,6 @@
+include "asyn.dbd"
+include "motorRecord.dbd"
+##device(motor,VME_IO,devPIasyn,"PI Motor GCS2")
+##driver(PIasyn)
+registrar(PIasynDriverRegister)
+##registrar(PIasynRegister)
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIasynAxis.cpp b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIasynAxis.cpp
new file mode 100755
index 00000000..a1126636
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIasynAxis.cpp
@@ -0,0 +1,305 @@
+/*
+FILENAME... PIasynController.cpp
+USAGE... Simulated Motor Support.
+
+Based on drvMotorSim.c
+
+Mark Rivers
+December 13, 2009
+
+*/
+
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "PIasynAxis.h"
+#include "PIasynController.h"
+#include "PIGCSController.h"
+
+//#undef asynPrint
+//#define asynPrint(user,reason,format...) 0
+
+static const char *driverName = "PIasynAxis";
+
+PIasynAxis::PIasynAxis(PIasynController *pController, PIGCSController* pGCSController, int axis, const char* szName )
+: asynMotorAxis((asynMotorController*)pController, axis)
+, pController_(pController)
+, m_szAxisName(NULL)
+, m_isHoming(0)
+, m_homed(0)
+, m_acceleration(0.0)
+, m_maxAcceleration(-1.0)
+, m_lastDirection(0)
+, m_CPUnumerator(1000)
+, m_CPUdenominator(1)
+, m_pasynUser(NULL)
+, m_bHasLimitSwitches(false)
+, m_bHasReference(false)
+, m_bProblem(false)
+, m_bServoControl(false)
+, m_bMoving(false)
+, m_pGCSController(pGCSController)
+{
+ if (szName != NULL)
+ {
+ m_szAxisName = new char[strlen(szName)+1];
+ strcpy(m_szAxisName, szName);
+ }
+
+ printf("PIasynAxis::PIasynAxis() %d: %s\n",
+ axis, m_szAxisName);
+}
+
+
+void PIasynAxis::Init(const char *portName)
+{
+ asynUser* logSink = pasynManager->createAsynUser(0,0);
+ asynStatus status = pasynManager->connectDevice(logSink, portName, getAxisNo());
+ if (status != asynSuccess)
+ {
+ asynPrint(logSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
+ "PIasynController::configAxis() - connectDevice() failed\n");
+ return;
+ }
+ m_pGCSController->m_pCurrentLogSink = logSink;
+
+ setIntegerParam(motorAxisHasClosedLoop, 1);
+
+ m_pGCSController->initAxis(this);
+ double resolution;
+ m_pGCSController->getResolution(this, resolution);
+ m_pGCSController->getAxisVelocity(this);
+ m_pGCSController->getAxisPositionCts(this);
+ setDoubleParam(pController_->motorPosition_, m_positionCts);
+ setDoubleParam(pController_->motorMoveAbs_, m_positionCts);
+ m_pGCSController->getTravelLimits(this, negLimit_, posLimit_);
+ setDoubleParam(pController_->motorLowLimit_, negLimit_);
+ setDoubleParam(pController_->motorHighLimit_, posLimit_);
+ m_pGCSController->getReferencedState(this);
+ setIntegerParam( pController_->motorStatusHomed_, m_homed );
+ callParamCallbacks();
+
+ pasynManager->freeAsynUser(logSink);
+
+}
+
+PIasynAxis::~PIasynAxis()
+{
+ if (m_szAxisName != NULL)
+ {
+ delete [] m_szAxisName;
+ }
+}
+
+asynStatus PIasynAxis::poll(bool *returnMoving)
+{
+ int done = 0;
+
+ int moving, negLimit, posLimit, servoControl;
+ int oldHoming = m_isHoming;
+ m_pGCSController->getStatus(this, m_isHoming, moving, negLimit, posLimit, servoControl);
+ if (moving == 0 && m_isHoming == 0)
+ done = 1;
+
+ m_bMoving = (done!=1);
+ if (!m_isHoming || m_pGCSController->CanCommunicateWhileHoming())
+ {
+ if (oldHoming && oldHoming != m_isHoming)
+ {
+ m_pGCSController->getReferencedState(this);
+ asynPrint(pasynUser_, ASYN_TRACE_ERROR, //FIXME: ASYN_TRACE_FLOW,
+ "PIasynAxis::poll() axis %d referencing state changed, homed = %d\n",
+ axisNo_, m_homed );
+ }
+ if (m_bServoControl && servoControl == 0) // servo changed without user interaction!
+ {
+ m_bProblem = true;
+ }
+ if (!m_isHoming || m_pGCSController->IsGCS2())
+ {
+ m_bServoControl = (servoControl == 1);
+ m_pGCSController->getAxisPositionCts(this);
+ double realPosition;
+ m_pGCSController->getAxisPosition(this, realPosition);
+ setDoubleParam(pController_->PI_SUP_POSITION, realPosition );
+ }
+ }
+ if (m_isHoming)
+ {
+ asynPrint(pasynUser_, ASYN_TRACE_FLOW,
+ "PIasynAxis::poll() axis %d referencing ...\n", axisNo_ );
+ }
+ setDoubleParam(pController_->motorPosition_, m_positionCts );
+ setDoubleParam(pController_->motorEncoderPosition_, m_positionCts);
+ setIntegerParam(pController_->motorStatusDirection_, m_lastDirection);
+ setIntegerParam(pController_->motorStatusDone_, done );
+ setIntegerParam(pController_->motorStatusHighLimit_, posLimit);
+ setIntegerParam(pController_->motorStatusHomed_, m_homed );
+ setIntegerParam(pController_->motorStatusMoving_, !done );
+ setIntegerParam(pController_->motorStatusLowLimit_, negLimit);
+ setIntegerParam(pController_->motorStatusGainSupport_, true);
+ setIntegerParam(pController_->motorStatusProblem_, m_bProblem);
+ setIntegerParam(pController_->motorStatusPowerOn_, m_bServoControl);
+ setIntegerParam(pController_->PI_SUP_SERVO, m_bServoControl );
+
+ callParamCallbacks();
+
+ *returnMoving = m_bMoving;
+}
+
+asynStatus PIasynAxis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration)
+{
+ m_pGCSController->m_pCurrentLogSink = pasynUser_;
+ asynStatus status = asynError;
+ static const char *functionName = "moveAxis";
+
+ if (!m_pGCSController->AcceptsNewTarget())
+ {
+ asynPrint(pasynUser_, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "%s:%s: Set port %s, axis %d - controller does not accept new target (busy?)\n",
+ driverName, functionName, pC_->portName, axisNo_ );
+ printf("%s:%s: Set port %s, axis %d - controller does not accept new target (busy?)\n",
+ driverName, functionName, pC_->portName, axisNo_ );
+ return status;
+ }
+
+ if (relative)
+ {
+ //TODO: MVR oder letztes target!
+ //TODO: when is this used?
+ }
+
+ if (pController_->movesDeferred != 0)
+ { /*Deferred moves.*/
+ deferred_position = position;
+ deferred_move = 1;
+ deferred_relative = relative;
+ setIntegerParam(pController_->motorStatusDone_, 0);
+ callParamCallbacks();
+ return asynSuccess;
+ }
+ else
+ {
+ if (maxVelocity != 0)
+ {
+ status = m_pGCSController->setVelocityCts(this, maxVelocity);
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+ }
+ if (acceleration != 0)
+ {
+ status = m_pGCSController->setAccelerationCts(this, acceleration);
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+ }
+
+ setIntegerParam(pController_->motorStatusDone_, 0);
+ callParamCallbacks();
+
+ status = m_pGCSController->moveCts(this, position);
+ }
+ epicsEventSignal(pController_->pollEventId_);
+
+ asynPrint(pasynUser_, ASYN_TRACE_FLOW,
+ "%s:%s: Set driver %s, axis %d move to %f, min vel=%f, max_vel=%f, accel=%f, deffered=%d - status=%d\n",
+ driverName, functionName, pC_->portName, axisNo_, position, minVelocity, maxVelocity, acceleration, pController_->movesDeferred, int(status) );
+ return status;
+}
+
+asynStatus PIasynAxis::moveVelocity(double minVelocity, double maxVelocity, double acceleration)
+{
+ m_pGCSController->m_pCurrentLogSink = pasynUser_;
+ asynStatus status = asynError;
+ static const char *functionName = "moveVelocityAxis";
+
+ if (!m_pGCSController->AcceptsNewTarget())
+ {
+ asynPrint(pasynUser_, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "%s:%s: Set port %s, axis %d - controller does not accept new target (busy?)",
+ driverName, functionName, pController_->portName, axisNo_ );
+ return status;
+ }
+
+
+ setIntegerParam(pController_->motorStatusDone_, 0);
+ callParamCallbacks();
+
+
+ double target = maxVelocity > 0 ? posLimit_ : negLimit_;
+
+ asynPrint(pasynUser_, ASYN_TRACE_FLOW,
+ "%s:%s: Set port %s, axis %d move with velocity of %f, accel=%f / target %f - BEFORE MOV\n",
+ driverName, functionName, pController_->portName, axisNo_, maxVelocity, acceleration, target );
+
+ m_pGCSController->setVelocityCts(this, maxVelocity);
+ m_pGCSController->move(this, target);
+
+ epicsEventSignal(pController_->pollEventId_);
+
+ asynPrint(pasynUser_, ASYN_TRACE_FLOW,
+ "%s:%s: Set port %s, axis %d move with velocity of %f, accel=%f / target %f - AFTER MOV\n",
+ driverName, functionName, pController_->portName, axisNo_, maxVelocity, acceleration, target );
+ return status;
+}
+
+asynStatus PIasynAxis::stop(double acceleration)
+{
+ m_pGCSController->m_pCurrentLogSink = pasynUser_;
+ static const char *functionName = "stopAxis";
+
+ deferred_move = 0;
+
+ m_pGCSController->haltAxis(this);
+
+ epicsEventSignal(pController_->pollEventId_);
+
+ asynPrint(pasynUser_, ASYN_TRACE_FLOW,
+ "%s:%s: Set axis %d to stop with accel=%f",
+ driverName, functionName, axisNo_, acceleration );
+ return asynSuccess;
+}
+
+
+
+asynStatus PIasynAxis::home(double minVelocity, double maxVelocity, double acceleration, int forwards)
+{
+ m_pGCSController->m_pCurrentLogSink = pasynUser_;
+ asynStatus status = asynError;
+ static const char *functionName = "homeAxis";
+
+ m_isHoming = 1;
+ setIntegerParam(pController_->motorStatusDone_, 0 );
+ callParamCallbacks();
+
+ status = m_pGCSController->referenceVelCts(this, maxVelocity, forwards);
+ if (asynSuccess != status)
+ {
+ return status;
+ }
+ setIntegerParam(pController_->motorStatusHomed_, m_homed );
+ epicsEventSignal(pController_->pollEventId_);
+
+ asynPrint(pasynUser_, ASYN_TRACE_FLOW,
+ "%s:%s: Set driver %s, axis %d to home %s, min vel=%f, max_vel=%f, accel=%f",
+ driverName, functionName, pController_->portName, axisNo_, (forwards?"FORWARDS":"REVERSE"), minVelocity, maxVelocity, acceleration );
+ return status;
+}
+
+
+
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIasynAxis.h b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIasynAxis.h
new file mode 100755
index 00000000..bd41b194
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIasynAxis.h
@@ -0,0 +1,74 @@
+/*
+FILENAME... PIasynController.cpp
+USAGE... PI GCS Motor Support.
+
+Based on drvMotorSim.c
+
+Mark Rivers
+December 13, 2009
+
+Steffen Rau,
+January 2011
+*/
+
+
+#include // for asynStatus
+#include
+
+class PIasynController;
+class PIGCSController;
+
+class PIasynAxis : public asynMotorAxis
+{
+public:
+ PIasynAxis(class PIasynController *pController, PIGCSController* pGCSController, int axis, const char* szName);
+ virtual~PIasynAxis();
+
+ void Init(const char *portName);
+
+ class PIasynController *pController_;
+ int getAxisNo() { return axisNo_; }
+
+ virtual asynStatus poll(bool *moving);
+ 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);
+
+
+ char* m_szAxisName; ///< GCS name
+
+ int m_isHoming; ///< if \b TRUE indicating that axis is currently homing/referencing
+ double deferred_position; ///< currently not used
+ int deferred_move; ///< currently not used
+ int deferred_relative; ///< currently not used
+ int m_homed; ///< if \b TRUE axis was homed and absolute positions are correct
+
+ double m_velocity;
+ double m_acceleration;
+ double m_maxAcceleration;
+ int m_positionCts;
+ double m_position;
+ int m_lastDirection;
+
+ int m_CPUnumerator;
+ int m_CPUdenominator;
+
+ asynUser* m_pasynUser;
+
+ bool m_bHasLimitSwitches;
+ bool m_bHasReference;
+ bool m_bProblem;
+ bool m_bServoControl;
+ bool m_bMoving;
+ int m_movingStateMask;
+
+ friend class PIasynController;
+private:
+
+ double negLimit_;
+ double posLimit_;
+ PIGCSController* m_pGCSController;
+
+};
+
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIasynController.cpp b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIasynController.cpp
new file mode 100755
index 00000000..63d60e34
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIasynController.cpp
@@ -0,0 +1,527 @@
+/*
+FILENAME... PIasynController.cpp
+USAGE... PI GCS2 Motor Support.
+
+Based on drvMotorSim.c
+from Mark Rivers, December 13, 2009
+
+Steffen Rau, Physik Instrumente (PI) GmbH & Co KG
+
+*/
+
+
+#include
+#include
+#include
+#include
+
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "PIasynController.h"
+#include "PIGCSController.h"
+#include "PIasynAxis.h"
+
+
+//#undef asynPrint
+//#define asynPrint(user,reason,format...) 0
+
+
+static const char *driverName = "PIasynDriver";
+
+
+static ELLLIST PIasynControllerList;
+static int PIasynControllerListInitialized = 0;
+
+PIasynController::PIasynController(const char *portName, const char* asynPort, int numAxes, int priority, int stackSize, int movingPollPeriod, int idlePollPeriod)
+ : asynMotorController(portName, numAxes, 10,
+ asynInt32Mask | asynFloat64Mask,
+ asynInt32Mask | asynFloat64Mask,
+ ASYN_CANBLOCK | ASYN_MULTIDEVICE,
+ 1, // autoconnect
+ priority, stackSize)
+ , m_pGCSController( NULL )
+{
+ createParam(PI_SUP_POSITION_String, asynParamFloat64, &PI_SUP_POSITION);
+ createParam(PI_SUP_TARGET_String, asynParamFloat64, &PI_SUP_TARGET);
+ createParam(PI_SUP_SERVO_String, asynParamInt32, &PI_SUP_SERVO);
+ createParam(PI_SUP_LAST_ERR_String, asynParamInt32, &PI_SUP_LAST_ERR);
+ createParam(PI_SUP_PIVOT_X_String, asynParamFloat64, &PI_SUP_PIVOT_X);
+ createParam(PI_SUP_PIVOT_Y_String, asynParamFloat64, &PI_SUP_PIVOT_Y);
+ createParam(PI_SUP_PIVOT_Z_String, asynParamFloat64, &PI_SUP_PIVOT_Z);
+ createParam(PI_SUP_RBPIVOT_X_String, asynParamFloat64, &PI_SUP_RBPIVOT_X);
+ createParam(PI_SUP_RBPIVOT_Y_String, asynParamFloat64, &PI_SUP_RBPIVOT_Y);
+ createParam(PI_SUP_RBPIVOT_Z_String, asynParamFloat64, &PI_SUP_RBPIVOT_Z);
+
+ int axis;
+ PIasynAxis *pAxis;
+ PIasynControllerNode *pNode;
+
+ if (!PIasynControllerListInitialized)
+ {
+ PIasynControllerListInitialized = 1;
+ ellInit(&PIasynControllerList);
+ }
+
+ // We should make sure this portName is not already in the list */
+ pNode = (PIasynControllerNode*) calloc(1, sizeof(PIasynControllerNode));
+ pNode->portName = epicsStrDup(portName);
+ pNode->pController = this;
+ ellAdd(&PIasynControllerList, (ELLNODE *)pNode);
+
+
+ asynStatus status;
+ asynUser* pInterface;
+ status = pasynOctetSyncIO->connect(asynPort, 0, &pInterface, NULL);
+ if (status)
+ {
+ asynPrint(pInterface, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "echoHandler: unable to connect to port %s\n",
+ asynPort);
+ return;
+ }
+ status = pasynOctetSyncIO->setInputEos(pInterface, "\n", 1);
+ if (status) {
+ asynPrint(pInterface, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "echoHandler: unable to set input EOS on %s: %s\n",
+ asynPort, pInterface->errorMessage);
+ return;
+ }
+ status = pasynOctetSyncIO->setOutputEos(pInterface, "", 0);
+ if (status) {
+ asynPrint(pInterface, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "echoHandler: unable to set output EOS on %s: %s\n",
+ asynPort, pInterface->errorMessage);
+ return;
+ }
+
+ char inputBuff[256];
+ inputBuff[0] = '\0';
+ status = PIGCSController::sendAndReceive(pInterface, "*IDN?", inputBuff, 255, pInterface);
+ asynPrint(pInterface, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "read from %s: %s\n",
+ asynPort, inputBuff);
+
+ char* p = inputBuff;
+ while (*p != '\0') { *p = toupper(*p); p++; }
+
+ m_pGCSController = PIGCSController::CreateGCSController(pInterface, inputBuff);
+ if (NULL == m_pGCSController)
+ {
+ asynPrint(pInterface, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "PIasynController: unknown controller type %s: %s\n",
+ asynPort, inputBuff);
+ return;
+ }
+
+ m_pGCSController->init();
+
+ if (numAxes < 1 ) numAxes = 1;
+ this->numAxes_ = numAxes;
+
+ if (m_pGCSController->getNrFoundAxes()getNrFoundAxes()));
+ delete m_pGCSController;
+ m_pGCSController = NULL;
+ return;
+ }
+
+ for (axis=0; axisgetAxesID(axis));
+ pAxis->Init(portName);
+ }
+
+ startPoller(double(movingPollPeriod)/1000, double(idlePollPeriod)/1000, 10);
+}
+
+
+
+
+void PIasynController::report(FILE *fp, int level)
+{
+ int axis;
+ PIasynAxis *pAxis;
+
+ fprintf(fp, "Simulation motor driver %s, numAxes=%d\n",
+ this->portName, this->numAxes_);
+
+ for (axis=0; axisnumAxes_; axis++)
+ {
+ pAxis = getPIAxis(axis);
+ fprintf(fp, " axis %d\n",
+ pAxis->axisNo_);
+
+ if (level > 0)
+ {
+ if (pAxis->m_isHoming)
+ {
+ fprintf(fp, " Currently homing axis\n" );
+ }
+ }
+ }
+
+ // Call the base class method
+ asynMotorController::report(fp, level);
+}
+
+//PIasynAxis * PIasynController::getPIAxis(asynUser *pasynUser)
+//{
+// int axis;
+// PIasynAxis *pAxis;
+//
+// getAddress(pasynUser, &axis);
+// pAxis = this->m_pAxes[axis];
+// pAxis->m_pasynUser = pasynUser;
+// return(pAxis);
+//}
+
+
+
+asynStatus PIasynController::processDeferredMoves()
+{
+ asynStatus status = asynError;
+ int axis;
+ PIasynAxis *pAxesArray[PIGCSController::MAX_NR_AXES];
+ int targetsCts[PIGCSController::MAX_NR_AXES];
+
+ int numDeferredAxes = 0;
+ for (axis=0; axisnumAxes_; axis++)
+ {
+ PIasynAxis *pAxis = getPIAxis(axis);
+ if (pAxis->deferred_move)
+ {
+ pAxesArray[numDeferredAxes] = pAxis;
+ targetsCts[numDeferredAxes] = pAxis->deferred_position;
+ pAxis->setIntegerParam(motorStatusDone_, 0);
+ pAxis->callParamCallbacks();
+ numDeferredAxes++;
+ }
+ }
+ if (numDeferredAxes > 0)
+ {
+ status = m_pGCSController->moveCts(pAxesArray, targetsCts, numDeferredAxes);
+ }
+
+ for (axis=0; axisnumAxes_; axis++)
+ {
+ if (getPIAxis(axis)->deferred_move)
+ {
+ getPIAxis(axis)->deferred_move = 0;
+ }
+ }
+ epicsEventSignal(pollEventId_);
+
+ return status;
+}
+
+
+asynStatus PIasynController::writeInt32(asynUser *pasynUser, epicsInt32 value)
+{
+ if (NULL == m_pGCSController)
+ {
+ asynPrint(pasynUser, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "PIasynController::writeInt32() GCS controller not initialized!\n");
+
+ return asynError;
+ }
+ m_pGCSController->m_pCurrentLogSink = pasynUser;
+ int function = pasynUser->reason;
+ asynStatus status = asynSuccess;
+ PIasynAxis *pAxis = (PIasynAxis *)this->getAxis(pasynUser);
+ static const char *functionName = "writeInt32";
+
+ lock();
+ /* Set the parameter and readback in the parameter library. This may be overwritten when we read back the
+ * status at the end, but that's OK */
+ status = pAxis->setIntegerParam(function, value);
+
+ if (function == motorSetClosedLoop_)
+ {
+ asynPrint(pasynUser, ASYN_TRACE_FLOW,
+ "%s:%s: %sing Closed-Loop Control flag on driver %s\n",
+ value != 0.0?"Enabl":"Disabl",
+ driverName, functionName, this->portName);
+ status = m_pGCSController->setServo(pAxis, (value!=0)?1:0);
+
+ }
+ else if (function == motorDeferMoves_)
+ {
+ asynPrint(pasynUser, ASYN_TRACE_FLOW,
+ "%s:%s: %sing Deferred Move flag on driver %s\n",
+ value != 0.0?"Sett":"Clear",
+ driverName, functionName, this->portName);
+ if (value == 0.0 && this->movesDeferred != 0)
+ {
+ processDeferredMoves();
+ }
+ this->movesDeferred = value;
+ } else {
+ /* Call base class call its method (if we have our parameters check this here) */
+ status = asynMotorController::writeInt32(pasynUser, value);
+ }
+ unlock();
+ /* Do callbacks so higher layers see any changes */
+ pAxis->callParamCallbacks();
+ if (status)
+ asynPrint(pasynUser, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "%s:%s: error, status=%d function=%d, value=%d\n",
+ driverName, functionName, status, function, value);
+ else
+ asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
+ "%s:%s: function=%d, value=%d\n",
+ driverName, functionName, function, value);
+ return status;
+}
+
+asynStatus PIasynController::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
+{
+ if (NULL == m_pGCSController)
+ {
+ asynPrint(pasynUser, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "PIasynController::writeFloat64() GCS controller not initialized!\n");
+
+ return asynError;
+ }
+ m_pGCSController->m_pCurrentLogSink = pasynUser;
+ int function = pasynUser->reason;
+ asynStatus status = asynSuccess;
+ PIasynAxis *pAxis = (PIasynAxis *)this->getAxis(pasynUser);
+ static const char *functionName = "writeFloat64";
+
+ /* Set the parameter and readback in the parameter library. This may be overwritten when we read back the
+ * status at the end, but that's OK */
+ status = pAxis->setDoubleParam(function, value);
+
+ if (function == PI_SUP_TARGET)
+ {
+ printf("PI_SUP_TargetAO: %f for axis %d\n", value, pAxis->axisNo_);
+ }
+ else if (function == PI_SUP_PIVOT_X)
+ {
+ status = m_pGCSController->SetPivotX(value);
+ }
+ else if (function == PI_SUP_PIVOT_Y)
+ {
+ status = m_pGCSController->SetPivotY(value);
+ }
+ else if (function == PI_SUP_PIVOT_Z)
+ {
+ status = m_pGCSController->SetPivotZ(value);
+ }
+ else if (function == motorPosition_) // Entspricht das DFH ?
+ {
+ // pAxis->enc_offset = (double) value - pAxis->nextpoint.axis[0].p;
+ asynPrint(pasynUser, ASYN_TRACE_FLOW,
+ "%s:%s: Set axis %d to position %d",
+ driverName, functionName, pAxis->axisNo_, value);
+ }
+ else if (function == motorResolution_ )
+ {
+ /* Call base class call its method (if we have our parameters check this here) */
+ status = asynMotorController::writeFloat64(pasynUser, value);
+ }
+ else if (function == motorEncRatio_ )
+ {
+ /* Call base class call its method (if we have our parameters check this here) */
+ status = asynMotorController::writeFloat64(pasynUser, value);
+ }
+ else
+ {
+ /* Call base class call its method (if we have our parameters check this here) */
+ status = asynMotorController::writeFloat64(pasynUser, value);
+ }
+ /* Do callbacks so higher layers see any changes */
+ pAxis->callParamCallbacks();
+ if (status)
+ asynPrint(pasynUser, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
+ "%s:%s: error, status=%d function=%d, value=%f\n",
+ driverName, functionName, status, function, value);
+ else
+ asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
+ "%s:%s: function=%d, value=%f\n",
+ driverName, functionName, function, value);
+ return status;
+}
+
+
+
+
+asynStatus PIasynController::profileMove(asynUser *pasynUser, int npoints, double positions[], double times[], int relative, int trigger )
+{
+ asynPrint(pasynUser, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
+ "PIasynController::profileMove() - not implemented\n");
+ return asynError;
+}
+
+asynStatus PIasynController::triggerProfile(asynUser *pasynUser)
+{
+ asynPrint(pasynUser, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
+ "PIasynController::profileMove() - not implemented\n");
+ return asynError;
+}
+
+asynStatus PIasynController::configAxis(PIasynAxis *pAxis)
+{
+ asynUser* logSink = pasynManager->createAsynUser(0,0);
+ asynStatus status = pasynManager->connectDevice(logSink, portName, pAxis->getAxisNo());
+ if (status != asynSuccess)
+ {
+ asynPrint(logSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
+ "PIasynController::configAxis() - connectDevice() failed\n");
+ return status;
+ }
+ m_pGCSController->m_pCurrentLogSink = logSink;
+
+ pAxis->setIntegerParam(motorAxisHasClosedLoop, 1);
+ pAxis->callParamCallbacks();
+
+ m_pGCSController->initAxis(pAxis);
+ double resolution;
+ m_pGCSController->getResolution(pAxis, resolution);
+ m_pGCSController->getAxisVelocity(pAxis);
+ m_pGCSController->getAxisPositionCts(pAxis);
+ pAxis->setDoubleParam(this->motorPosition_, pAxis->m_positionCts);
+ pAxis->setDoubleParam(this->motorMoveAbs_, pAxis->m_positionCts);
+ double negLimit, posLimit;
+ m_pGCSController->getTravelLimits(pAxis, negLimit, posLimit);
+ pAxis->setDoubleParam(this->motorLowLimit_, negLimit);
+ pAxis->setDoubleParam(this->motorHighLimit_, posLimit);
+ m_pGCSController->getReferencedState(pAxis);
+ pAxis->setIntegerParam( this->motorStatusHomed_, pAxis->m_homed );
+
+ pasynManager->freeAsynUser(logSink);
+
+ /* Send a signal to the poller task which will make it do a poll,
+ * updating values for this axis to use the new resolution (stepSize) */
+ epicsEventSignal(pollEventId_);
+
+ return(asynSuccess);
+}
+
+/**\defgroup PIasynTask Routines to implement the motor axis simulation task
+@{
+*/
+
+/** Process one iteration of an axis
+
+ This routine takes a single axis and propogates its motion forward a given amount
+ of time.
+
+ \param pAxis [in] Pointer to axis information.
+ \param delta [in] Time in seconds to propogate motion forwards.
+
+ \return Integer indicating 0 (asynSuccess) for success or non-zero for failure.
+*/
+
+
+//
+//static void PIasynTaskC(void *drvPvt)
+//{
+// PIasynController *pController = (PIasynController*)drvPvt;
+// pController->PIasynTask();
+//}
+//
+//
+//
+//void PIasynController::PIasynTask()
+//{
+// double timeout = m_idlePollingRate;
+// int axis;
+// PIasynAxis *pAxis;
+// epicsEventSignal(pollEventId_); /* Force on poll at startup */
+//
+// int status;
+// while ( 1 )
+// {
+// if (timeout != 0.) status = epicsEventWaitWithTimeout(pollEventId_, timeout);
+// else status = epicsEventWait(pollEventId_);
+//
+// lock();
+// m_pGCSController->getGlobalState(pAxes_, numAxes_);
+// unlock();
+//
+// bool bAnyAxisMoving = false;
+// for (axis=0; axisnumAxes_; axis++)
+// {
+// lock();
+// pAxis = getPIAxis(axis);
+// process(pAxis);
+// pAxis->callParamCallbacks();
+// unlock();
+// bAnyAxisMoving = (pAxis->m_bMoving != 0);
+// }
+// m_pGCSController->m_bAnyAxisMoving = bAnyAxisMoving;
+// if (m_pGCSController->m_bAnyAxisMoving)
+// timeout = m_movingPollingRate;
+// else
+// timeout = m_idlePollingRate;
+// }
+//}
+
+asynStatus PIasynController::poll()
+{
+ return m_pGCSController->getGlobalState(pAxes_, numAxes_);
+
+ setDoubleParam( 0, PI_SUP_RBPIVOT_X, m_pGCSController->GetPivotX());
+ setDoubleParam( 0, PI_SUP_RBPIVOT_Y, m_pGCSController->GetPivotY());
+ setDoubleParam( 0, PI_SUP_RBPIVOT_Z, m_pGCSController->GetPivotZ());
+
+ setIntegerParam( 0, PI_SUP_LAST_ERR, m_pGCSController->GetLastError() );
+
+ callParamCallbacks();
+}
+
+
+/** Configuration command, called directly or from iocsh */
+extern "C" int PI_GCS2_CreateController(const char *portName, const char* asynPort, int numAxes, int priority, int stackSize, int movingPollingRate, int idlePollingRate)
+{
+ PIasynController *pasynController
+ = new PIasynController(portName, asynPort, numAxes, priority, stackSize, movingPollingRate, idlePollingRate);
+ pasynController = NULL;
+ return(asynSuccess);
+}
+
+/** Code for iocsh registration */
+static const iocshArg PI_GCS2_CreateControllerArg0 = {"Port name", iocshArgString};
+static const iocshArg PI_GCS2_CreateControllerArg1 = {"asyn Port name", iocshArgString};
+static const iocshArg PI_GCS2_CreateControllerArg2 = {"Number of axes", iocshArgInt};
+static const iocshArg PI_GCS2_CreateControllerArg3 = {"priority", iocshArgInt};
+static const iocshArg PI_GCS2_CreateControllerArg4 = {"stackSize", iocshArgInt};
+static const iocshArg PI_GCS2_CreateControllerArg5 = {"moving polling time [msec]", iocshArgInt};
+static const iocshArg PI_GCS2_CreateControllerArg6 = {"idle polling time [msec]", iocshArgInt};
+static const iocshArg * const PI_GCS2_CreateControllerArgs[] = {&PI_GCS2_CreateControllerArg0,
+ &PI_GCS2_CreateControllerArg1,
+ &PI_GCS2_CreateControllerArg2,
+ &PI_GCS2_CreateControllerArg3,
+ &PI_GCS2_CreateControllerArg4,
+ &PI_GCS2_CreateControllerArg5,
+ &PI_GCS2_CreateControllerArg6};
+static const iocshFuncDef PI_GCS2_CreateControllerDef = {"PI_GCS2_CreateController", 7, PI_GCS2_CreateControllerArgs};
+static void PI_GCS2_CreateControllerCallFunc(const iocshArgBuf *args)
+{
+ PI_GCS2_CreateController(args[0].sval, args[1].sval, args[2].ival, args[3].ival, args[4].ival, args[5].ival, args[6].ival);
+}
+
+
+static void PIasynDriverRegister(void)
+{
+ iocshRegister(&PI_GCS2_CreateControllerDef, PI_GCS2_CreateControllerCallFunc);
+}
+
+extern "C" {
+epicsExportRegistrar(PIasynDriverRegister);
+}
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIasynController.h b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIasynController.h
new file mode 100755
index 00000000..9090bbe9
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/PIasynController.h
@@ -0,0 +1,80 @@
+/*
+FILENAME... PIasynController.cpp
+USAGE... Simulated Motor Support.
+
+Based on drvMotorSim.c
+
+Mark Rivers
+December 13, 2009
+
+*/
+
+#ifndef PI_ASYN_DRIVER_INCLUDED_
+#define PI_ASYN_DRIVER_INCLUDED_
+
+#include "asynMotorController.h"
+#include "asynMotorAxis.h"
+
+class PIasynAxis;
+class PIGCSController;
+
+class PIasynController : asynMotorController {
+public:
+ PIasynController(const char *portName, const char* asynPort, int numAxes, int priority, int stackSize, int movingPollPeriod, int idlePollPeriod);
+ asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
+ asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value);
+ void report(FILE *fp, int level);
+ asynStatus profileMove(asynUser *pasynUser, int npoints, double positions[], double times[], int relative, int trigger);
+ asynStatus triggerProfile(asynUser *pasynUser);
+ asynStatus configAxis(PIasynAxis *pAxis);
+
+ PIasynAxis* getPIAxis(asynUser *pasynUser) { return (PIasynAxis*)asynMotorController::getAxis(pasynUser); }
+ PIasynAxis* getPIAxis(int axisNo) { return (PIasynAxis*)asynMotorController::getAxis(axisNo); }
+
+ virtual asynStatus poll();
+
+ friend class PIasynAxis;
+
+private:
+// void process(PIasynAxis *pAxis);
+ epicsThreadId motorThread;
+ int movesDeferred;
+ //int numAxes;
+ asynStatus processDeferredMoves();
+ //PIasynAxis** m_pAxes;
+
+ PIGCSController* m_pGCSController;
+
+ int PI_SUP_POSITION;
+ int PI_SUP_TARGET;
+ int PI_SUP_SERVO;
+ int PI_SUP_LAST_ERR;
+ int PI_SUP_PIVOT_X;
+ int PI_SUP_PIVOT_Y;
+ int PI_SUP_PIVOT_Z;
+ int PI_SUP_RBPIVOT_X;
+ int PI_SUP_RBPIVOT_Y;
+ int PI_SUP_RBPIVOT_Z;
+
+};
+
+
+#define PI_SUP_POSITION_String "PI_SUP_POSITION"
+#define PI_SUP_TARGET_String "PI_SUP_TARGET"
+#define PI_SUP_SERVO_String "PI_SUP_SERVO"
+#define PI_SUP_LAST_ERR_String "PI_SUP_LAST_ERR"
+#define PI_SUP_PIVOT_X_String "PI_SUP_PIVOT_X"
+#define PI_SUP_PIVOT_Y_String "PI_SUP_PIVOT_Y"
+#define PI_SUP_PIVOT_Z_String "PI_SUP_PIVOT_Z"
+#define PI_SUP_RBPIVOT_X_String "PI_SUP_RBPIVOT_X"
+#define PI_SUP_RBPIVOT_Y_String "PI_SUP_RBPIVOT_Y"
+#define PI_SUP_RBPIVOT_Z_String "PI_SUP_RBPIVOT_Z"
+
+
+typedef struct PIasynControllerNode {
+ ELLNODE node;
+ const char *portName;
+ PIasynController *pController;
+} PIasynControllerNode;
+
+#endif // PI_ASYN_DRIVER_INCLUDED_
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/ReadMe.txt b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/ReadMe.txt
new file mode 100755
index 00000000..39e304bb
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/ReadMe.txt
@@ -0,0 +1,61 @@
+Readme for PIasyn - EPICS support for PI GCS2 stages
+========================================================
+
+The PIasyn driver is written to support PI motion controllers which
+support GCS2 (General Command Set) as commanding language.
+Currently this is implemented with different C++ classes where the
+differences and specialties are handled. This can be implemented
+by querying the controller what features are supported. So in future
+developments these classes may disappear.
+
+ Homing
+========
+
+a) stages with absolute sensors
+Some PI stages, mostly piezo stages, use an absolute position sensor.
+The correct absolute position is known to the controller immediately after power up.
+For these stages homing is not necessary and thus not supported.
+These stages will ignore HOMF and HOMR.
+The HOME flag of the MSTA field is meaningless for these stages
+and HOMED is always true,
+
+b) stages with incremental sensors
+Some PIStages needs to be referenced after controller power up. The state
+is reflected by the HOMED flag of MSTA. There are different ways to home
+a stage. The default is by using the reference switch. If a stage has
+a reference switch HOMF and HOMR will move to this switch. The direction is
+determined by the controller. The reference signal is edge based, so the controller
+can find out on which side of the reference the stage is and can move using
+the shortest path. HOMF and HOMR will trigger the same move. If the stage has
+no reference switch the built in limit switches can be used to determine the absolute
+position. In this case HOMF will send the stage to its positive limit switch and
+HOMR to its negative limit switch. As the reference is edge based or not present the
+HOME bit of the MSTA field is meaningless for these stages.
+
+c) setting the homing velocity
+Reducing the velocity used for homing is usually done to improve the accuracy.
+PI controllers reach the reference every time from the same "side". So only this
+last approach is performed with the homing velocity set with HVEL. The coarse move
+to the proximity of the reference is done with the a velocity limited by the current
+velocity (set with VELO) and the maximum possible velocity to decelerate in case of
+hitting a limit switch.
+
+ "Motion Errors"
+=================
+
+If the controller detects a "motion error", i.e. the difference between target and
+current position is greater than some given limit (also known as "following error"),
+the driver will set the PROBLEM bit in MSTA. Servo control is also switched off.
+The EA_POSITION bit of MSTA will reflect the "servo control" state. To re-enable
+servo control use CNEN.
+
+
+ C-702
+=======
+
+The C-702 controller uses an older "dialect" of GCS1.
+That's why at some points different parameter IDs are used and why there is no communication
+during homing. So the position cannot be updated during homing and will "jump" to the final
+position after homing is finished.
+
+
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/picontrollererrors.h b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/picontrollererrors.h
new file mode 100755
index 00000000..4b5bf5de
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/picontrollererrors.h
@@ -0,0 +1,1075 @@
+// PIControllerErrors.h
+//
+// This file defines symbols for each error code used in C/C++ programs.
+//
+// This file is automagically generated from the central error code list.
+// DO NOT ADD ERROR CODES IN THIS FILE! Use the error list and the generation tool instead!
+//
+// after generation open file in VS and create the constants with numbers.
+// This can be done by performing 2 search/replace actions with regulyr expression activetad:
+// search for "\#define:b{:i}:b*{:z}L" replace with "#define \1__\2 \2L\n#define \1 \2L"
+// search for "\#define:b{:i}:b*-{:z}L" replace with "#define \1__MINUS\2 -\2L\n#define \1 -\2L"
+
+#ifndef __PI_CONTROLLER_ERROS_H__
+#define __PI_CONTROLLER_ERROS_H__
+
+//////////////////////////////////////////////////
+//
+// Dll Errors - DLL errors occured in GCS DLL
+//
+#define PI_UNKNOWN_AXIS_IDENTIFIER__MINUS1001 -1001L
+#define PI_UNKNOWN_AXIS_IDENTIFIER -1001L /**< \ingroup err
+ Unknown axis identifier */
+#define PI_NR_NAV_OUT_OF_RANGE__MINUS1002 -1002L
+#define PI_NR_NAV_OUT_OF_RANGE -1002L /**< \ingroup err
+ Number for NAV out of range--must be in [1,10000] */
+#define PI_INVALID_SGA__MINUS1003 -1003L
+#define PI_INVALID_SGA -1003L /**< \ingroup err
+ Invalid value for SGA--must be one of {1, 10, 100, 1000} */
+#define PI_UNEXPECTED_RESPONSE__MINUS1004 -1004L
+#define PI_UNEXPECTED_RESPONSE -1004L /**< \ingroup err
+ Controller sent unexpected response */
+#define PI_NO_MANUAL_PAD__MINUS1005 -1005L
+#define PI_NO_MANUAL_PAD -1005L /**< \ingroup err
+ No manual control pad installed, calls to SMA and related commands are not allowed */
+#define PI_INVALID_MANUAL_PAD_KNOB__MINUS1006 -1006L
+#define PI_INVALID_MANUAL_PAD_KNOB -1006L /**< \ingroup err
+ Invalid number for manual control pad knob */
+#define PI_INVALID_MANUAL_PAD_AXIS__MINUS1007 -1007L
+#define PI_INVALID_MANUAL_PAD_AXIS -1007L /**< \ingroup err
+ Axis not currently controlled by a manual control pad */
+#define PI_CONTROLLER_BUSY__MINUS1008 -1008L
+#define PI_CONTROLLER_BUSY -1008L /**< \ingroup err
+ Controller is busy with some lengthy operation (e.g. reference move, fast scan algorithm) */
+#define PI_THREAD_ERROR__MINUS1009 -1009L
+#define PI_THREAD_ERROR -1009L /**< \ingroup err
+ Internal error--could not start thread */
+#define PI_IN_MACRO_MODE__MINUS1010 -1010L
+#define PI_IN_MACRO_MODE -1010L /**< \ingroup err
+ Controller is (already) in macro mode--command not valid in macro mode */
+#define PI_NOT_IN_MACRO_MODE__MINUS1011 -1011L
+#define PI_NOT_IN_MACRO_MODE -1011L /**< \ingroup err
+ Controller not in macro mode--command not valid unless macro mode active */
+#define PI_MACRO_FILE_ERROR__MINUS1012 -1012L
+#define PI_MACRO_FILE_ERROR -1012L /**< \ingroup err
+ Could not open file to write or read macro */
+#define PI_NO_MACRO_OR_EMPTY__MINUS1013 -1013L
+#define PI_NO_MACRO_OR_EMPTY -1013L /**< \ingroup err
+ No macro with given name on controller, or macro is empty */
+#define PI_MACRO_EDITOR_ERROR__MINUS1014 -1014L
+#define PI_MACRO_EDITOR_ERROR -1014L /**< \ingroup err
+ Internal error in macro editor */
+#define PI_INVALID_ARGUMENT__MINUS1015 -1015L
+#define PI_INVALID_ARGUMENT -1015L /**< \ingroup err
+ One or more arguments given to function is invalid (empty string, index out of range, ...) */
+#define PI_AXIS_ALREADY_EXISTS__MINUS1016 -1016L
+#define PI_AXIS_ALREADY_EXISTS -1016L /**< \ingroup err
+ Axis identifier is already in use by a connected stage */
+#define PI_INVALID_AXIS_IDENTIFIER__MINUS1017 -1017L
+#define PI_INVALID_AXIS_IDENTIFIER -1017L /**< \ingroup err
+ Invalid axis identifier */
+#define PI_COM_ARRAY_ERROR__MINUS1018 -1018L
+#define PI_COM_ARRAY_ERROR -1018L /**< \ingroup err
+ Could not access array data in COM server */
+#define PI_COM_ARRAY_RANGE_ERROR__MINUS1019 -1019L
+#define PI_COM_ARRAY_RANGE_ERROR -1019L /**< \ingroup err
+ Range of array does not fit the number of parameters */
+#define PI_INVALID_SPA_CMD_ID__MINUS1020 -1020L
+#define PI_INVALID_SPA_CMD_ID -1020L /**< \ingroup err
+ Invalid parameter ID given to SPA or SPA? */
+#define PI_NR_AVG_OUT_OF_RANGE__MINUS1021 -1021L
+#define PI_NR_AVG_OUT_OF_RANGE -1021L /**< \ingroup err
+ Number for AVG out of range--must be >0 */
+#define PI_WAV_SAMPLES_OUT_OF_RANGE__MINUS1022 -1022L
+#define PI_WAV_SAMPLES_OUT_OF_RANGE -1022L /**< \ingroup err
+ Incorrect number of samples given to WAV */
+#define PI_WAV_FAILED__MINUS1023 -1023L
+#define PI_WAV_FAILED -1023L /**< \ingroup err
+ Generation of wave failed */
+#define PI_MOTION_ERROR__MINUS1024 -1024L
+#define PI_MOTION_ERROR -1024L /**< \ingroup err
+ Motion error: position error too large, servo is switched off automatically */
+#define PI_RUNNING_MACRO__MINUS1025 -1025L
+#define PI_RUNNING_MACRO -1025L /**< \ingroup err
+ Controller is (already) running a macro */
+#define PI_PZT_CONFIG_FAILED__MINUS1026 -1026L
+#define PI_PZT_CONFIG_FAILED -1026L /**< \ingroup err
+ Configuration of PZT stage or amplifier failed */
+#define PI_PZT_CONFIG_INVALID_PARAMS__MINUS1027 -1027L
+#define PI_PZT_CONFIG_INVALID_PARAMS -1027L /**< \ingroup err
+ Current settings are not valid for desired configuration */
+#define PI_UNKNOWN_CHANNEL_IDENTIFIER__MINUS1028 -1028L
+#define PI_UNKNOWN_CHANNEL_IDENTIFIER -1028L /**< \ingroup err
+ Unknown channel identifier */
+#define PI_WAVE_PARAM_FILE_ERROR__MINUS1029 -1029L
+#define PI_WAVE_PARAM_FILE_ERROR -1029L /**< \ingroup err
+ Error while reading/writing wave generator parameter file */
+#define PI_UNKNOWN_WAVE_SET__MINUS1030 -1030L
+#define PI_UNKNOWN_WAVE_SET -1030L /**< \ingroup err
+ Could not find description of wave form. Maybe WG.INI is missing? */
+#define PI_WAVE_EDITOR_FUNC_NOT_LOADED__MINUS1031 -1031L
+#define PI_WAVE_EDITOR_FUNC_NOT_LOADED -1031L /**< \ingroup err
+ The WGWaveEditor DLL function was not found at startup */
+#define PI_USER_CANCELLED__MINUS1032 -1032L
+#define PI_USER_CANCELLED -1032L /**< \ingroup err
+ The user cancelled a dialog */
+#define PI_C844_ERROR__MINUS1033 -1033L
+#define PI_C844_ERROR -1033L /**< \ingroup err
+ Error from C-844 Controller */
+#define PI_DLL_NOT_LOADED__MINUS1034 -1034L
+#define PI_DLL_NOT_LOADED -1034L /**< \ingroup err
+ DLL necessary to call function not loaded, or function not found in DLL */
+#define PI_PARAMETER_FILE_PROTECTED__MINUS1035 -1035L
+#define PI_PARAMETER_FILE_PROTECTED -1035L /**< \ingroup err
+ The open parameter file is protected and cannot be edited */
+#define PI_NO_PARAMETER_FILE_OPENED__MINUS1036 -1036L
+#define PI_NO_PARAMETER_FILE_OPENED -1036L /**< \ingroup err
+ There is no parameter file open */
+#define PI_STAGE_DOES_NOT_EXIST__MINUS1037 -1037L
+#define PI_STAGE_DOES_NOT_EXIST -1037L /**< \ingroup err
+ Selected stage does not exist */
+#define PI_PARAMETER_FILE_ALREADY_OPENED__MINUS1038 -1038L
+#define PI_PARAMETER_FILE_ALREADY_OPENED -1038L /**< \ingroup err
+ There is already a parameter file open. Close it before opening a new file */
+#define PI_PARAMETER_FILE_OPEN_ERROR__MINUS1039 -1039L
+#define PI_PARAMETER_FILE_OPEN_ERROR -1039L /**< \ingroup err
+ Could not open parameter file */
+#define PI_INVALID_CONTROLLER_VERSION__MINUS1040 -1040L
+#define PI_INVALID_CONTROLLER_VERSION -1040L /**< \ingroup err
+ The version of the connected controller is invalid */
+#define PI_PARAM_SET_ERROR__MINUS1041 -1041L
+#define PI_PARAM_SET_ERROR -1041L /**< \ingroup err
+ Parameter could not be set with SPA--parameter not defined for this controller! */
+#define PI_NUMBER_OF_POSSIBLE_WAVES_EXCEEDED__MINUS1042 -1042L
+#define PI_NUMBER_OF_POSSIBLE_WAVES_EXCEEDED -1042L /**< \ingroup err
+ The maximum number of wave definitions has been exceeded */
+#define PI_NUMBER_OF_POSSIBLE_GENERATORS_EXCEEDED__MINUS1043 -1043L
+#define PI_NUMBER_OF_POSSIBLE_GENERATORS_EXCEEDED -1043L /**< \ingroup err
+ The maximum number of wave generators has been exceeded */
+#define PI_NO_WAVE_FOR_AXIS_DEFINED__MINUS1044 -1044L
+#define PI_NO_WAVE_FOR_AXIS_DEFINED -1044L /**< \ingroup err
+ No wave defined for specified axis */
+#define PI_CANT_STOP_OR_START_WAV__MINUS1045 -1045L
+#define PI_CANT_STOP_OR_START_WAV -1045L /**< \ingroup err
+ Wave output to axis already stopped/started */
+#define PI_REFERENCE_ERROR__MINUS1046 -1046L
+#define PI_REFERENCE_ERROR -1046L /**< \ingroup err
+ Not all axes could be referenced */
+#define PI_REQUIRED_WAVE_NOT_FOUND__MINUS1047 -1047L
+#define PI_REQUIRED_WAVE_NOT_FOUND -1047L /**< \ingroup err
+ Could not find parameter set required by frequency relation */
+#define PI_INVALID_SPP_CMD_ID__MINUS1048 -1048L
+#define PI_INVALID_SPP_CMD_ID -1048L /**< \ingroup err
+ Command ID given to SPP or SPP? is not valid */
+#define PI_STAGE_NAME_ISNT_UNIQUE__MINUS1049 -1049L
+#define PI_STAGE_NAME_ISNT_UNIQUE -1049L /**< \ingroup err
+ A stage name given to CST is not unique */
+#define PI_FILE_TRANSFER_BEGIN_MISSING__MINUS1050 -1050L
+#define PI_FILE_TRANSFER_BEGIN_MISSING -1050L /**< \ingroup err
+ A uuencoded file transfered did not start with \"begin\" followed by the proper filename */
+#define PI_FILE_TRANSFER_ERROR_TEMP_FILE__MINUS1051 -1051L
+#define PI_FILE_TRANSFER_ERROR_TEMP_FILE -1051L /**< \ingroup err
+ Could not create/read file on host PC */
+#define PI_FILE_TRANSFER_CRC_ERROR__MINUS1052 -1052L
+#define PI_FILE_TRANSFER_CRC_ERROR -1052L /**< \ingroup err
+ Checksum error when transfering a file to/from the controller */
+#define PI_COULDNT_FIND_PISTAGES_DAT__MINUS1053 -1053L
+#define PI_COULDNT_FIND_PISTAGES_DAT -1053L /**< \ingroup err
+ The PiStages.dat database could not be found. This file is required to connect a stage with the CST command */
+#define PI_NO_WAVE_RUNNING__MINUS1054 -1054L
+#define PI_NO_WAVE_RUNNING -1054L /**< \ingroup err
+ No wave being output to specified axis */
+#define PI_INVALID_PASSWORD__MINUS1055 -1055L
+#define PI_INVALID_PASSWORD -1055L /**< \ingroup err
+ Invalid password */
+#define PI_OPM_COM_ERROR__MINUS1056 -1056L
+#define PI_OPM_COM_ERROR -1056L /**< \ingroup err
+ Error during communication with OPM (Optical Power Meter), maybe no OPM connected */
+#define PI_WAVE_EDITOR_WRONG_PARAMNUM__MINUS1057 -1057L
+#define PI_WAVE_EDITOR_WRONG_PARAMNUM -1057L /**< \ingroup err
+ WaveEditor: Error during wave creation, incorrect number of parameters */
+#define PI_WAVE_EDITOR_FREQUENCY_OUT_OF_RANGE__MINUS1058 -1058L
+#define PI_WAVE_EDITOR_FREQUENCY_OUT_OF_RANGE -1058L /**< \ingroup err
+ WaveEditor: Frequency out of range */
+#define PI_WAVE_EDITOR_WRONG_IP_VALUE__MINUS1059 -1059L
+#define PI_WAVE_EDITOR_WRONG_IP_VALUE -1059L /**< \ingroup err
+ WaveEditor: Error during wave creation, incorrect index for integer parameter */
+#define PI_WAVE_EDITOR_WRONG_DP_VALUE__MINUS1060 -1060L
+#define PI_WAVE_EDITOR_WRONG_DP_VALUE -1060L /**< \ingroup err
+ WaveEditor: Error during wave creation, incorrect index for floating point parameter */
+#define PI_WAVE_EDITOR_WRONG_ITEM_VALUE__MINUS1061 -1061L
+#define PI_WAVE_EDITOR_WRONG_ITEM_VALUE -1061L /**< \ingroup err
+ WaveEditor: Error during wave creation, could not calculate value */
+#define PI_WAVE_EDITOR_MISSING_GRAPH_COMPONENT__MINUS1062 -1062L
+#define PI_WAVE_EDITOR_MISSING_GRAPH_COMPONENT -1062L /**< \ingroup err
+ WaveEditor: Graph display component not installed */
+#define PI_EXT_PROFILE_UNALLOWED_CMD__MINUS1063 -1063L
+#define PI_EXT_PROFILE_UNALLOWED_CMD -1063L /**< \ingroup err
+ User Profile Mode: Command is not allowed, check for required preparatory commands */
+#define PI_EXT_PROFILE_EXPECTING_MOTION_ERROR__MINUS1064 -1064L
+#define PI_EXT_PROFILE_EXPECTING_MOTION_ERROR -1064L /**< \ingroup err
+ User Profile Mode: First target position in User Profile is too far from current position */
+#define PI_EXT_PROFILE_ACTIVE__MINUS1065 -1065L
+#define PI_EXT_PROFILE_ACTIVE -1065L /**< \ingroup err
+ Controller is (already) in User Profile Mode */
+#define PI_EXT_PROFILE_INDEX_OUT_OF_RANGE__MINUS1066 -1066L
+#define PI_EXT_PROFILE_INDEX_OUT_OF_RANGE -1066L /**< \ingroup err
+ User Profile Mode: Block or Data Set index out of allowed range */
+#define PI_PROFILE_GENERATOR_NO_PROFILE__MINUS1067 -1067L
+#define PI_PROFILE_GENERATOR_NO_PROFILE -1067L /**< \ingroup err
+ ProfileGenerator: No profile has been created yet */
+#define PI_PROFILE_GENERATOR_OUT_OF_LIMITS__MINUS1068 -1068L
+#define PI_PROFILE_GENERATOR_OUT_OF_LIMITS -1068L /**< \ingroup err
+ ProfileGenerator: Generated profile exceeds limits of one or both axes */
+#define PI_PROFILE_GENERATOR_UNKNOWN_PARAMETER__MINUS1069 -1069L
+#define PI_PROFILE_GENERATOR_UNKNOWN_PARAMETER -1069L /**< \ingroup err
+ ProfileGenerator: Unknown parameter ID in Set/Get Parameter command */
+#define PI_PROFILE_GENERATOR_PAR_OUT_OF_RANGE__MINUS1070 -1070L
+#define PI_PROFILE_GENERATOR_PAR_OUT_OF_RANGE -1070L /**< \ingroup err
+ ProfileGenerator: Parameter out of allowed range */
+#define PI_EXT_PROFILE_OUT_OF_MEMORY__MINUS1071 -1071L
+#define PI_EXT_PROFILE_OUT_OF_MEMORY -1071L /**< \ingroup err
+ User Profile Mode: Out of memory */
+#define PI_EXT_PROFILE_WRONG_CLUSTER__MINUS1072 -1072L
+#define PI_EXT_PROFILE_WRONG_CLUSTER -1072L /**< \ingroup err
+ User Profile Mode: Cluster is not assigned to this axis */
+#define PI_EXT_PROFILE_UNKNOWN_CLUSTER_IDENTIFIER__MINUS1073 -1073L
+#define PI_EXT_PROFILE_UNKNOWN_CLUSTER_IDENTIFIER -1073L /**< \ingroup err
+ Unknown cluster identifier */
+#define PI_INVALID_DEVICE_DRIVER_VERSION__MINUS1074 -1074L
+#define PI_INVALID_DEVICE_DRIVER_VERSION -1074L /**< \ingroup err
+ The installed device driver doesn't match the required version. Please see the documentation to determine the required device driver version. */
+#define PI_INVALID_LIBRARY_VERSION__MINUS1075 -1075L
+#define PI_INVALID_LIBRARY_VERSION -1075L /**< \ingroup err
+ The library used doesn't match the required version. Please see the documentation to determine the required library version. */
+#define PI_INTERFACE_LOCKED__MINUS1076 -1076L
+#define PI_INTERFACE_LOCKED -1076L /**< \ingroup err
+ The interface is currently locked by another function. Please try again later. */
+#define PI_PARAM_DAT_FILE_INVALID_VERSION__MINUS1077 -1077L
+#define PI_PARAM_DAT_FILE_INVALID_VERSION -1077L /**< \ingroup err
+ Version of parameter DAT file does not match the required version. Current files are available at www.pi.ws. */
+#define PI_CANNOT_WRITE_TO_PARAM_DAT_FILE__MINUS1078 -1078L
+#define PI_CANNOT_WRITE_TO_PARAM_DAT_FILE -1078L /**< \ingroup err
+ Cannot write to parameter DAT file to store user defined stage type. */
+#define PI_CANNOT_CREATE_PARAM_DAT_FILE__MINUS1079 -1079L
+#define PI_CANNOT_CREATE_PARAM_DAT_FILE -1079L /**< \ingroup err
+ Cannot create parameter DAT file to store user defined stage type. */
+#define PI_PARAM_DAT_FILE_INVALID_REVISION__MINUS1080 -1080L
+#define PI_PARAM_DAT_FILE_INVALID_REVISION -1080L /**< \ingroup err
+ Parameter DAT file does not have correct revision. */
+#define PI_USERSTAGES_DAT_FILE_INVALID_REVISION__MINUS1081 -1081L
+#define PI_USERSTAGES_DAT_FILE_INVALID_REVISION -1081L /**< \ingroup err
+ User stages DAT file does not have correct revision. */
+#define PI_SOFTWARE_TIMEOUT__MINUS1082 -1082L
+#define PI_SOFTWARE_TIMEOUT -1082L /**< \ingroup err
+ Timeout Error. Some lengthy operation did not finish within expected time. */
+//
+// End of Dll Errors
+//////////////////////////////////////////////////
+
+//////////////////////////////////////////////////
+//
+// Controller Errors - Errors set by the controller or the GCS DLL
+//
+#define PI_CNTR_NO_ERROR__0 0L
+#define PI_CNTR_NO_ERROR 0L /**< \ingroup err
+ No error */
+#define PI_CNTR_PARAM_SYNTAX__1 1L
+#define PI_CNTR_PARAM_SYNTAX 1L /**< \ingroup err
+ Parameter syntax error */
+#define PI_CNTR_UNKNOWN_COMMAND__2 2L
+#define PI_CNTR_UNKNOWN_COMMAND 2L /**< \ingroup err
+ Unknown command */
+#define PI_CNTR_COMMAND_TOO_LONG__3 3L
+#define PI_CNTR_COMMAND_TOO_LONG 3L /**< \ingroup err
+ Command length out of limits or command buffer overrun */
+#define PI_CNTR_SCAN_ERROR__4 4L
+#define PI_CNTR_SCAN_ERROR 4L /**< \ingroup err
+ Error while scanning */
+#define PI_CNTR_MOVE_WITHOUT_REF_OR_NO_SERVO__5 5L
+#define PI_CNTR_MOVE_WITHOUT_REF_OR_NO_SERVO 5L /**< \ingroup err
+ Unallowable move attempted on unreferenced axis, or move attempted with servo off */
+#define PI_CNTR_INVALID_SGA_PARAM__6 6L
+#define PI_CNTR_INVALID_SGA_PARAM 6L /**< \ingroup err
+ Parameter for SGA not valid */
+#define PI_CNTR_POS_OUT_OF_LIMITS__7 7L
+#define PI_CNTR_POS_OUT_OF_LIMITS 7L /**< \ingroup err
+ Position out of limits */
+#define PI_CNTR_VEL_OUT_OF_LIMITS__8 8L
+#define PI_CNTR_VEL_OUT_OF_LIMITS 8L /**< \ingroup err
+ Velocity out of limits */
+#define PI_CNTR_SET_PIVOT_NOT_POSSIBLE__9 9L
+#define PI_CNTR_SET_PIVOT_NOT_POSSIBLE 9L /**< \ingroup err
+ Attempt to set pivot point while U,V and W not all 0 */
+#define PI_CNTR_STOP__10 10L
+#define PI_CNTR_STOP 10L /**< \ingroup err
+ Controller was stopped by command */
+#define PI_CNTR_SST_OR_SCAN_RANGE__11 11L
+#define PI_CNTR_SST_OR_SCAN_RANGE 11L /**< \ingroup err
+ Parameter for SST or for one of the embedded scan algorithms out of range */
+#define PI_CNTR_INVALID_SCAN_AXES__12 12L
+#define PI_CNTR_INVALID_SCAN_AXES 12L /**< \ingroup err
+ Invalid axis combination for fast scan */
+#define PI_CNTR_INVALID_NAV_PARAM__13 13L
+#define PI_CNTR_INVALID_NAV_PARAM 13L /**< \ingroup err
+ Parameter for NAV out of range */
+#define PI_CNTR_INVALID_ANALOG_INPUT__14 14L
+#define PI_CNTR_INVALID_ANALOG_INPUT 14L /**< \ingroup err
+ Invalid analog channel */
+#define PI_CNTR_INVALID_AXIS_IDENTIFIER__15 15L
+#define PI_CNTR_INVALID_AXIS_IDENTIFIER 15L /**< \ingroup err
+ Invalid axis identifier */
+#define PI_CNTR_INVALID_STAGE_NAME__16 16L
+#define PI_CNTR_INVALID_STAGE_NAME 16L /**< \ingroup err
+ Invalid stage name */
+#define PI_CNTR_PARAM_OUT_OF_RANGE__17 17L
+#define PI_CNTR_PARAM_OUT_OF_RANGE 17L /**< \ingroup err
+ Parameter out of range */
+#define PI_CNTR_INVALID_MACRO_NAME__18 18L
+#define PI_CNTR_INVALID_MACRO_NAME 18L /**< \ingroup err
+ Invalid macro name */
+#define PI_CNTR_MACRO_RECORD__19 19L
+#define PI_CNTR_MACRO_RECORD 19L /**< \ingroup err
+ Error while recording macro */
+#define PI_CNTR_MACRO_NOT_FOUND__20 20L
+#define PI_CNTR_MACRO_NOT_FOUND 20L /**< \ingroup err
+ Macro not found */
+#define PI_CNTR_AXIS_HAS_NO_BRAKE__21 21L
+#define PI_CNTR_AXIS_HAS_NO_BRAKE 21L /**< \ingroup err
+ Axis has no brake */
+#define PI_CNTR_DOUBLE_AXIS__22 22L
+#define PI_CNTR_DOUBLE_AXIS 22L /**< \ingroup err
+ Axis identifier specified more than once */
+#define PI_CNTR_ILLEGAL_AXIS__23 23L
+#define PI_CNTR_ILLEGAL_AXIS 23L /**< \ingroup err
+ Illegal axis */
+#define PI_CNTR_PARAM_NR__24 24L
+#define PI_CNTR_PARAM_NR 24L /**< \ingroup err
+ Incorrect number of parameters */
+#define PI_CNTR_INVALID_REAL_NR__25 25L
+#define PI_CNTR_INVALID_REAL_NR 25L /**< \ingroup err
+ Invalid floating point number */
+#define PI_CNTR_MISSING_PARAM__26 26L
+#define PI_CNTR_MISSING_PARAM 26L /**< \ingroup err
+ Parameter missing */
+#define PI_CNTR_SOFT_LIMIT_OUT_OF_RANGE__27 27L
+#define PI_CNTR_SOFT_LIMIT_OUT_OF_RANGE 27L /**< \ingroup err
+ Soft limit out of range */
+#define PI_CNTR_NO_MANUAL_PAD__28 28L
+#define PI_CNTR_NO_MANUAL_PAD 28L /**< \ingroup err
+ No manual pad found */
+#define PI_CNTR_NO_JUMP__29 29L
+#define PI_CNTR_NO_JUMP 29L /**< \ingroup err
+ No more step-response values */
+#define PI_CNTR_INVALID_JUMP__30 30L
+#define PI_CNTR_INVALID_JUMP 30L /**< \ingroup err
+ No step-response values recorded */
+#define PI_CNTR_AXIS_HAS_NO_REFERENCE__31 31L
+#define PI_CNTR_AXIS_HAS_NO_REFERENCE 31L /**< \ingroup err
+ Axis has no reference sensor */
+#define PI_CNTR_STAGE_HAS_NO_LIM_SWITCH__32 32L
+#define PI_CNTR_STAGE_HAS_NO_LIM_SWITCH 32L /**< \ingroup err
+ Axis has no limit switch */
+#define PI_CNTR_NO_RELAY_CARD__33 33L
+#define PI_CNTR_NO_RELAY_CARD 33L /**< \ingroup err
+ No relay card installed */
+#define PI_CNTR_CMD_NOT_ALLOWED_FOR_STAGE__34 34L
+#define PI_CNTR_CMD_NOT_ALLOWED_FOR_STAGE 34L /**< \ingroup err
+ Command not allowed for selected stage(s) */
+#define PI_CNTR_NO_DIGITAL_INPUT__35 35L
+#define PI_CNTR_NO_DIGITAL_INPUT 35L /**< \ingroup err
+ No digital input installed */
+#define PI_CNTR_NO_DIGITAL_OUTPUT__36 36L
+#define PI_CNTR_NO_DIGITAL_OUTPUT 36L /**< \ingroup err
+ No digital output configured */
+#define PI_CNTR_NO_MCM__37 37L
+#define PI_CNTR_NO_MCM 37L /**< \ingroup err
+ No more MCM responses */
+#define PI_CNTR_INVALID_MCM__38 38L
+#define PI_CNTR_INVALID_MCM 38L /**< \ingroup err
+ No MCM values recorded */
+#define PI_CNTR_INVALID_CNTR_NUMBER__39 39L
+#define PI_CNTR_INVALID_CNTR_NUMBER 39L /**< \ingroup err
+ Controller number invalid */
+#define PI_CNTR_NO_JOYSTICK_CONNECTED__40 40L
+#define PI_CNTR_NO_JOYSTICK_CONNECTED 40L /**< \ingroup err
+ No joystick configured */
+#define PI_CNTR_INVALID_EGE_AXIS__41 41L
+#define PI_CNTR_INVALID_EGE_AXIS 41L /**< \ingroup err
+ Invalid axis for electronic gearing, axis can not be slave */
+#define PI_CNTR_SLAVE_POSITION_OUT_OF_RANGE__42 42L
+#define PI_CNTR_SLAVE_POSITION_OUT_OF_RANGE 42L /**< \ingroup err
+ Position of slave axis is out of range */
+#define PI_CNTR_COMMAND_EGE_SLAVE__43 43L
+#define PI_CNTR_COMMAND_EGE_SLAVE 43L /**< \ingroup err
+ Slave axis cannot be commanded directly when electronic gearing is enabled */
+#define PI_CNTR_JOYSTICK_CALIBRATION_FAILED__44 44L
+#define PI_CNTR_JOYSTICK_CALIBRATION_FAILED 44L /**< \ingroup err
+ Calibration of joystick failed */
+#define PI_CNTR_REFERENCING_FAILED__45 45L
+#define PI_CNTR_REFERENCING_FAILED 45L /**< \ingroup err
+ Referencing failed */
+#define PI_CNTR_OPM_MISSING__46 46L
+#define PI_CNTR_OPM_MISSING 46L /**< \ingroup err
+ OPM (Optical Power Meter) missing */
+#define PI_CNTR_OPM_NOT_INITIALIZED__47 47L
+#define PI_CNTR_OPM_NOT_INITIALIZED 47L /**< \ingroup err
+ OPM (Optical Power Meter) not initialized or cannot be initialized */
+#define PI_CNTR_OPM_COM_ERROR__48 48L
+#define PI_CNTR_OPM_COM_ERROR 48L /**< \ingroup err
+ OPM (Optical Power Meter) Communication Error */
+#define PI_CNTR_MOVE_TO_LIMIT_SWITCH_FAILED__49 49L
+#define PI_CNTR_MOVE_TO_LIMIT_SWITCH_FAILED 49L /**< \ingroup err
+ Move to limit switch failed */
+#define PI_CNTR_REF_WITH_REF_DISABLED__50 50L
+#define PI_CNTR_REF_WITH_REF_DISABLED 50L /**< \ingroup err
+ Attempt to reference axis with referencing disabled */
+#define PI_CNTR_AXIS_UNDER_JOYSTICK_CONTROL__51 51L
+#define PI_CNTR_AXIS_UNDER_JOYSTICK_CONTROL 51L /**< \ingroup err
+ Selected axis is controlled by joystick */
+#define PI_CNTR_COMMUNICATION_ERROR__52 52L
+#define PI_CNTR_COMMUNICATION_ERROR 52L /**< \ingroup err
+ Controller detected communication error */
+#define PI_CNTR_DYNAMIC_MOVE_IN_PROCESS__53 53L
+#define PI_CNTR_DYNAMIC_MOVE_IN_PROCESS 53L /**< \ingroup err
+ MOV! motion still in progress */
+#define PI_CNTR_UNKNOWN_PARAMETER__54 54L
+#define PI_CNTR_UNKNOWN_PARAMETER 54L /**< \ingroup err
+ Unknown parameter */
+#define PI_CNTR_NO_REP_RECORDED__55 55L
+#define PI_CNTR_NO_REP_RECORDED 55L /**< \ingroup err
+ No commands were recorded with REP */
+#define PI_CNTR_INVALID_PASSWORD__56 56L
+#define PI_CNTR_INVALID_PASSWORD 56L /**< \ingroup err
+ Password invalid */
+#define PI_CNTR_INVALID_RECORDER_CHAN__57 57L
+#define PI_CNTR_INVALID_RECORDER_CHAN 57L /**< \ingroup err
+ Data Record Table does not exist */
+#define PI_CNTR_INVALID_RECORDER_SRC_OPT__58 58L
+#define PI_CNTR_INVALID_RECORDER_SRC_OPT 58L /**< \ingroup err
+ Source does not exist; number too low or too high */
+#define PI_CNTR_INVALID_RECORDER_SRC_CHAN__59 59L
+#define PI_CNTR_INVALID_RECORDER_SRC_CHAN 59L /**< \ingroup err
+ Source Record Table number too low or too high */
+#define PI_CNTR_PARAM_PROTECTION__60 60L
+#define PI_CNTR_PARAM_PROTECTION 60L /**< \ingroup err
+ Protected Param: current Command Level (CCL) too low */
+#define PI_CNTR_AUTOZERO_RUNNING__61 61L
+#define PI_CNTR_AUTOZERO_RUNNING 61L /**< \ingroup err
+ Command execution not possible while Autozero is running */
+#define PI_CNTR_NO_LINEAR_AXIS__62 62L
+#define PI_CNTR_NO_LINEAR_AXIS 62L /**< \ingroup err
+ Autozero requires at least one linear axis */
+#define PI_CNTR_INIT_RUNNING__63 63L
+#define PI_CNTR_INIT_RUNNING 63L /**< \ingroup err
+ Initialization still in progress */
+#define PI_CNTR_READ_ONLY_PARAMETER__64 64L
+#define PI_CNTR_READ_ONLY_PARAMETER 64L /**< \ingroup err
+ Parameter is read-only */
+#define PI_CNTR_PAM_NOT_FOUND__65 65L
+#define PI_CNTR_PAM_NOT_FOUND 65L /**< \ingroup err
+ Parameter not found in non-volatile memory */
+#define PI_CNTR_VOL_OUT_OF_LIMITS__66 66L
+#define PI_CNTR_VOL_OUT_OF_LIMITS 66L /**< \ingroup err
+ Voltage out of limits */
+#define PI_CNTR_WAVE_TOO_LARGE__67 67L
+#define PI_CNTR_WAVE_TOO_LARGE 67L /**< \ingroup err
+ Not enough memory available for requested wave curve */
+#define PI_CNTR_NOT_ENOUGH_DDL_MEMORY__68 68L
+#define PI_CNTR_NOT_ENOUGH_DDL_MEMORY 68L /**< \ingroup err
+ Not enough memory available for DDL table; DDL can not be started */
+#define PI_CNTR_DDL_TIME_DELAY_TOO_LARGE__69 69L
+#define PI_CNTR_DDL_TIME_DELAY_TOO_LARGE 69L /**< \ingroup err
+ Time delay larger than DDL table; DDL can not be started */
+#define PI_CNTR_DIFFERENT_ARRAY_LENGTH__70 70L
+#define PI_CNTR_DIFFERENT_ARRAY_LENGTH 70L /**< \ingroup err
+ The requested arrays have different lengths; query them separately */
+#define PI_CNTR_GEN_SINGLE_MODE_RESTART__71 71L
+#define PI_CNTR_GEN_SINGLE_MODE_RESTART 71L /**< \ingroup err
+ Attempt to restart the generator while it is running in single step mode */
+#define PI_CNTR_ANALOG_TARGET_ACTIVE__72 72L
+#define PI_CNTR_ANALOG_TARGET_ACTIVE 72L /**< \ingroup err
+ Motion commands and wave generator activation are not allowed when analog target is active */
+#define PI_CNTR_WAVE_GENERATOR_ACTIVE__73 73L
+#define PI_CNTR_WAVE_GENERATOR_ACTIVE 73L /**< \ingroup err
+ Motion commands are not allowed when wave generator output is active; use WGO to disable generator output */
+#define PI_CNTR_AUTOZERO_DISABLED__74 74L
+#define PI_CNTR_AUTOZERO_DISABLED 74L /**< \ingroup err
+ No sensor channel or no piezo channel connected to selected axis (sensor and piezo matrix) */
+#define PI_CNTR_NO_WAVE_SELECTED__75 75L
+#define PI_CNTR_NO_WAVE_SELECTED 75L /**< \ingroup err
+ Generator started (WGO) without having selected a wave table (WSL). */
+#define PI_CNTR_IF_BUFFER_OVERRUN__76 76L
+#define PI_CNTR_IF_BUFFER_OVERRUN 76L /**< \ingroup err
+ Interface buffer did overrun and command couldn't be received correctly */
+#define PI_CNTR_NOT_ENOUGH_RECORDED_DATA__77 77L
+#define PI_CNTR_NOT_ENOUGH_RECORDED_DATA 77L /**< \ingroup err
+ Data Record Table does not hold enough recorded data */
+#define PI_CNTR_TABLE_DEACTIVATED__78 78L
+#define PI_CNTR_TABLE_DEACTIVATED 78L /**< \ingroup err
+ Data Record Table is not configured for recording */
+#define PI_CNTR_OPENLOOP_VALUE_SET_WHEN_SERVO_ON__79 79L
+#define PI_CNTR_OPENLOOP_VALUE_SET_WHEN_SERVO_ON 79L /**< \ingroup err
+ Open-loop commands (SVA, SVR) are not allowed when servo is on */
+#define PI_CNTR_RAM_ERROR__80 80L
+#define PI_CNTR_RAM_ERROR 80L /**< \ingroup err
+ Hardware error affecting RAM */
+#define PI_CNTR_MACRO_UNKNOWN_COMMAND__81 81L
+#define PI_CNTR_MACRO_UNKNOWN_COMMAND 81L /**< \ingroup err
+ Not macro command */
+#define PI_CNTR_MACRO_PC_ERROR__82 82L
+#define PI_CNTR_MACRO_PC_ERROR 82L /**< \ingroup err
+ Macro counter out of range */
+#define PI_CNTR_JOYSTICK_ACTIVE__83 83L
+#define PI_CNTR_JOYSTICK_ACTIVE 83L /**< \ingroup err
+ Joystick is active */
+#define PI_CNTR_MOTOR_IS_OFF__84 84L
+#define PI_CNTR_MOTOR_IS_OFF 84L /**< \ingroup err
+ Motor is off */
+#define PI_CNTR_ONLY_IN_MACRO__85 85L
+#define PI_CNTR_ONLY_IN_MACRO 85L /**< \ingroup err
+ Macro-only command */
+#define PI_CNTR_JOYSTICK_UNKNOWN_AXIS__86 86L
+#define PI_CNTR_JOYSTICK_UNKNOWN_AXIS 86L /**< \ingroup err
+ Invalid joystick axis */
+#define PI_CNTR_JOYSTICK_UNKNOWN_ID__87 87L
+#define PI_CNTR_JOYSTICK_UNKNOWN_ID 87L /**< \ingroup err
+ Joystick unknown */
+#define PI_CNTR_REF_MODE_IS_ON__88 88L
+#define PI_CNTR_REF_MODE_IS_ON 88L /**< \ingroup err
+ Move without referenced stage */
+#define PI_CNTR_NOT_ALLOWED_IN_CURRENT_MOTION_MODE__89 89L
+#define PI_CNTR_NOT_ALLOWED_IN_CURRENT_MOTION_MODE 89L /**< \ingroup err
+ Command not allowed in current motion mode */
+#define PI_CNTR_DIO_AND_TRACING_NOT_POSSIBLE__90 90L
+#define PI_CNTR_DIO_AND_TRACING_NOT_POSSIBLE 90L /**< \ingroup err
+ No tracing possible while digital IOs are used on this HW revision. Reconnect to switch operation mode. */
+#define PI_CNTR_COLLISION__91 91L
+#define PI_CNTR_COLLISION 91L /**< \ingroup err
+ Move not possible, would cause collision */
+#define PI_CNTR_SLAVE_NOT_FAST_ENOUGH__92 92L
+#define PI_CNTR_SLAVE_NOT_FAST_ENOUGH 92L /**< \ingroup err
+ Stage is not capable of following the master. Check the gear ratio(SRA). */
+#define PI_CNTR_CMD_NOT_ALLOWED_WHILE_AXIS_IN_MOTION__93 93L
+#define PI_CNTR_CMD_NOT_ALLOWED_WHILE_AXIS_IN_MOTION 93L /**< \ingroup err
+ This command is not allowed while the affected axis or its master is in motion. */
+#define PI_CNTR_OPEN_LOOP_JOYSTICK_ENABLED__94 94L
+#define PI_CNTR_OPEN_LOOP_JOYSTICK_ENABLED 94L /**< \ingroup err
+ Servo cannot be switched on when open-loop joystick control is enabled. */
+#define PI_CNTR_INVALID_SERVO_STATE_FOR_PARAMETER__95 95L
+#define PI_CNTR_INVALID_SERVO_STATE_FOR_PARAMETER 95L /**< \ingroup err
+ This parameter cannot be changed in current servo mode. */
+#define PI_CNTR_UNKNOWN_STAGE_NAME__96 96L
+#define PI_CNTR_UNKNOWN_STAGE_NAME 96L /**< \ingroup err
+ Unknown stage name */
+#define PI_LABVIEW_ERROR__100 100L
+#define PI_LABVIEW_ERROR 100L /**< \ingroup err
+ PI LabVIEW driver reports error. See source control for details. */
+#define PI_CNTR_NO_AXIS__200 200L
+#define PI_CNTR_NO_AXIS 200L /**< \ingroup err
+ No stage connected to axis */
+#define PI_CNTR_NO_AXIS_PARAM_FILE__201 201L
+#define PI_CNTR_NO_AXIS_PARAM_FILE 201L /**< \ingroup err
+ File with axis parameters not found */
+#define PI_CNTR_INVALID_AXIS_PARAM_FILE__202 202L
+#define PI_CNTR_INVALID_AXIS_PARAM_FILE 202L /**< \ingroup err
+ Invalid axis parameter file */
+#define PI_CNTR_NO_AXIS_PARAM_BACKUP__203 203L
+#define PI_CNTR_NO_AXIS_PARAM_BACKUP 203L /**< \ingroup err
+ Backup file with axis parameters not found */
+#define PI_CNTR_RESERVED_204__204 204L
+#define PI_CNTR_RESERVED_204 204L /**< \ingroup err
+ PI internal error code 204 */
+#define PI_CNTR_SMO_WITH_SERVO_ON__205 205L
+#define PI_CNTR_SMO_WITH_SERVO_ON 205L /**< \ingroup err
+ SMO with servo on */
+#define PI_CNTR_UUDECODE_INCOMPLETE_HEADER__206 206L
+#define PI_CNTR_UUDECODE_INCOMPLETE_HEADER 206L /**< \ingroup err
+ uudecode: incomplete header */
+#define PI_CNTR_UUDECODE_NOTHING_TO_DECODE__207 207L
+#define PI_CNTR_UUDECODE_NOTHING_TO_DECODE 207L /**< \ingroup err
+ uudecode: nothing to decode */
+#define PI_CNTR_UUDECODE_ILLEGAL_FORMAT__208 208L
+#define PI_CNTR_UUDECODE_ILLEGAL_FORMAT 208L /**< \ingroup err
+ uudecode: illegal UUE format */
+#define PI_CNTR_CRC32_ERROR__209 209L
+#define PI_CNTR_CRC32_ERROR 209L /**< \ingroup err
+ CRC32 error */
+#define PI_CNTR_ILLEGAL_FILENAME__210 210L
+#define PI_CNTR_ILLEGAL_FILENAME 210L /**< \ingroup err
+ Illegal file name (must be 8-0 format) */
+#define PI_CNTR_FILE_NOT_FOUND__211 211L
+#define PI_CNTR_FILE_NOT_FOUND 211L /**< \ingroup err
+ File not found on controller */
+#define PI_CNTR_FILE_WRITE_ERROR__212 212L
+#define PI_CNTR_FILE_WRITE_ERROR 212L /**< \ingroup err
+ Error writing file on controller */
+#define PI_CNTR_DTR_HINDERS_VELOCITY_CHANGE__213 213L
+#define PI_CNTR_DTR_HINDERS_VELOCITY_CHANGE 213L /**< \ingroup err
+ VEL command not allowed in DTR Command Mode */
+#define PI_CNTR_POSITION_UNKNOWN__214 214L
+#define PI_CNTR_POSITION_UNKNOWN 214L /**< \ingroup err
+ Position calculations failed */
+#define PI_CNTR_CONN_POSSIBLY_BROKEN__215 215L
+#define PI_CNTR_CONN_POSSIBLY_BROKEN 215L /**< \ingroup err
+ The connection between controller and stage may be broken */
+#define PI_CNTR_ON_LIMIT_SWITCH__216 216L
+#define PI_CNTR_ON_LIMIT_SWITCH 216L /**< \ingroup err
+ The connected stage has driven into a limit switch, some controllers need CLR to resume operation */
+#define PI_CNTR_UNEXPECTED_STRUT_STOP__217 217L
+#define PI_CNTR_UNEXPECTED_STRUT_STOP 217L /**< \ingroup err
+ Strut test command failed because of an unexpected strut stop */
+#define PI_CNTR_POSITION_BASED_ON_ESTIMATION__218 218L
+#define PI_CNTR_POSITION_BASED_ON_ESTIMATION 218L /**< \ingroup err
+ While MOV! is running position can only be estimated! */
+#define PI_CNTR_POSITION_BASED_ON_INTERPOLATION__219 219L
+#define PI_CNTR_POSITION_BASED_ON_INTERPOLATION 219L /**< \ingroup err
+ Position was calculated during MOV motion */
+#define PI_CNTR_INVALID_HANDLE__230 230L
+#define PI_CNTR_INVALID_HANDLE 230L /**< \ingroup err
+ Invalid handle */
+#define PI_CNTR_NO_BIOS_FOUND__231 231L
+#define PI_CNTR_NO_BIOS_FOUND 231L /**< \ingroup err
+ No bios found */
+#define PI_CNTR_SAVE_SYS_CFG_FAILED__232 232L
+#define PI_CNTR_SAVE_SYS_CFG_FAILED 232L /**< \ingroup err
+ Save system configuration failed */
+#define PI_CNTR_LOAD_SYS_CFG_FAILED__233 233L
+#define PI_CNTR_LOAD_SYS_CFG_FAILED 233L /**< \ingroup err
+ Load system configuration failed */
+#define PI_CNTR_SEND_BUFFER_OVERFLOW__301 301L
+#define PI_CNTR_SEND_BUFFER_OVERFLOW 301L /**< \ingroup err
+ Send buffer overflow */
+#define PI_CNTR_VOLTAGE_OUT_OF_LIMITS__302 302L
+#define PI_CNTR_VOLTAGE_OUT_OF_LIMITS 302L /**< \ingroup err
+ Voltage out of limits */
+#define PI_CNTR_OPEN_LOOP_MOTION_SET_WHEN_SERVO_ON__303 303L
+#define PI_CNTR_OPEN_LOOP_MOTION_SET_WHEN_SERVO_ON 303L /**< \ingroup err
+ Open-loop motion attempted when servo ON */
+#define PI_CNTR_RECEIVING_BUFFER_OVERFLOW__304 304L
+#define PI_CNTR_RECEIVING_BUFFER_OVERFLOW 304L /**< \ingroup err
+ Received command is too long */
+#define PI_CNTR_EEPROM_ERROR__305 305L
+#define PI_CNTR_EEPROM_ERROR 305L /**< \ingroup err
+ Error while reading/writing EEPROM */
+#define PI_CNTR_I2C_ERROR__306 306L
+#define PI_CNTR_I2C_ERROR 306L /**< \ingroup err
+ Error on I2C bus */
+#define PI_CNTR_RECEIVING_TIMEOUT__307 307L
+#define PI_CNTR_RECEIVING_TIMEOUT 307L /**< \ingroup err
+ Timeout while receiving command */
+#define PI_CNTR_TIMEOUT__308 308L
+#define PI_CNTR_TIMEOUT 308L /**< \ingroup err
+ A lengthy operation has not finished in the expected time */
+#define PI_CNTR_MACRO_OUT_OF_SPACE__309 309L
+#define PI_CNTR_MACRO_OUT_OF_SPACE 309L /**< \ingroup err
+ Insufficient space to store macro */
+#define PI_CNTR_EUI_OLDVERSION_CFGDATA__310 310L
+#define PI_CNTR_EUI_OLDVERSION_CFGDATA 310L /**< \ingroup err
+ Configuration data has old version number */
+#define PI_CNTR_EUI_INVALID_CFGDATA__311 311L
+#define PI_CNTR_EUI_INVALID_CFGDATA 311L /**< \ingroup err
+ Invalid configuration data */
+#define PI_CNTR_HARDWARE_ERROR__333 333L
+#define PI_CNTR_HARDWARE_ERROR 333L /**< \ingroup err
+ Internal hardware error */
+#define PI_CNTR_WAV_INDEX_ERROR__400 400L
+#define PI_CNTR_WAV_INDEX_ERROR 400L /**< \ingroup err
+ Wave generator index error */
+#define PI_CNTR_WAV_NOT_DEFINED__401 401L
+#define PI_CNTR_WAV_NOT_DEFINED 401L /**< \ingroup err
+ Wave table not defined */
+#define PI_CNTR_WAV_TYPE_NOT_SUPPORTED__402 402L
+#define PI_CNTR_WAV_TYPE_NOT_SUPPORTED 402L /**< \ingroup err
+ Wave type not supported */
+#define PI_CNTR_WAV_LENGTH_EXCEEDS_LIMIT__403 403L
+#define PI_CNTR_WAV_LENGTH_EXCEEDS_LIMIT 403L /**< \ingroup err
+ Wave length exceeds limit */
+#define PI_CNTR_WAV_PARAMETER_NR__404 404L
+#define PI_CNTR_WAV_PARAMETER_NR 404L /**< \ingroup err
+ Wave parameter number error */
+#define PI_CNTR_WAV_PARAMETER_OUT_OF_LIMIT__405 405L
+#define PI_CNTR_WAV_PARAMETER_OUT_OF_LIMIT 405L /**< \ingroup err
+ Wave parameter out of range */
+#define PI_CNTR_WGO_BIT_NOT_SUPPORTED__406 406L
+#define PI_CNTR_WGO_BIT_NOT_SUPPORTED 406L /**< \ingroup err
+ WGO command bit not supported */
+#define PI_CNTR_EMERGENCY_STOP_BUTTON_ACTIVATED__500 500L
+#define PI_CNTR_EMERGENCY_STOP_BUTTON_ACTIVATED 500L /**< \ingroup err
+ The \"red knob\" is still set and disables system */
+#define PI_CNTR_EMERGENCY_STOP_BUTTON_WAS_ACTIVATED__501 501L
+#define PI_CNTR_EMERGENCY_STOP_BUTTON_WAS_ACTIVATED 501L /**< \ingroup err
+ The \"red knob\" was activated and still disables system - reanimation required */
+#define PI_CNTR_REDUNDANCY_LIMIT_EXCEEDED__502 502L
+#define PI_CNTR_REDUNDANCY_LIMIT_EXCEEDED 502L /**< \ingroup err
+ Position consistency check failed */
+#define PI_CNTR_COLLISION_SWITCH_ACTIVATED__503 503L
+#define PI_CNTR_COLLISION_SWITCH_ACTIVATED 503L /**< \ingroup err
+ Hardware collision sensor(s) are activated */
+#define PI_CNTR_FOLLOWING_ERROR__504 504L
+#define PI_CNTR_FOLLOWING_ERROR 504L /**< \ingroup err
+ Strut following error occurred, e.g. caused by overload or encoder failure */
+#define PI_CNTR_SENSOR_SIGNAL_INVALID__505 505L
+#define PI_CNTR_SENSOR_SIGNAL_INVALID 505L /**< \ingroup err
+ One sensor signal is not valid */
+#define PI_CNTR_SERVO_LOOP_UNSTABLE__506 506L
+#define PI_CNTR_SERVO_LOOP_UNSTABLE 506L /**< \ingroup err
+ Servo loop was unstable due to wrong parameter setting and switched off to avoid damage. */
+#define PI_CNTR_UNKNOWN_ERROR__555 555L
+#define PI_CNTR_UNKNOWN_ERROR 555L /**< \ingroup err
+ BasMac: unknown controller error */
+#define PI_CNTR_NOT_ENOUGH_MEMORY__601 601L
+#define PI_CNTR_NOT_ENOUGH_MEMORY 601L /**< \ingroup err
+ Not enough memory */
+#define PI_CNTR_HW_VOLTAGE_ERROR__602 602L
+#define PI_CNTR_HW_VOLTAGE_ERROR 602L /**< \ingroup err
+ Hardware voltage error */
+#define PI_CNTR_HW_TEMPERATURE_ERROR__603 603L
+#define PI_CNTR_HW_TEMPERATURE_ERROR 603L /**< \ingroup err
+ Hardware temperature out of range */
+#define PI_CNTR_POSITION_ERROR_TOO_HIGH__604 604L
+#define PI_CNTR_POSITION_ERROR_TOO_HIGH 604L /**< \ingroup err
+ Position error of any axis in the system is too high */
+#define PI_CNTR_INPUT_OUT_OF_RANGE__606 606L
+#define PI_CNTR_INPUT_OUT_OF_RANGE 606L /**< \ingroup err
+ Maximum value of input signal has been exceeded */
+#define PI_CNTR_TOO_MANY_NESTED_MACROS__1000 1000L
+#define PI_CNTR_TOO_MANY_NESTED_MACROS 1000L /**< \ingroup err
+ Too many nested macros */
+#define PI_CNTR_MACRO_ALREADY_DEFINED__1001 1001L
+#define PI_CNTR_MACRO_ALREADY_DEFINED 1001L /**< \ingroup err
+ Macro already defined */
+#define PI_CNTR_NO_MACRO_RECORDING__1002 1002L
+#define PI_CNTR_NO_MACRO_RECORDING 1002L /**< \ingroup err
+ Macro recording not activated */
+#define PI_CNTR_INVALID_MAC_PARAM__1003 1003L
+#define PI_CNTR_INVALID_MAC_PARAM 1003L /**< \ingroup err
+ Invalid parameter for MAC */
+#define PI_CNTR_MACRO_DELETE_ERROR__1004 1004L
+#define PI_CNTR_MACRO_DELETE_ERROR 1004L /**< \ingroup err
+ Deleting macro failed */
+#define PI_CNTR_CONTROLLER_BUSY__1005 1005L
+#define PI_CNTR_CONTROLLER_BUSY 1005L /**< \ingroup err
+ Controller is busy with some lengthy operation (e.g. reference move, fast scan algorithm) */
+#define PI_CNTR_INVALID_IDENTIFIER__1006 1006L
+#define PI_CNTR_INVALID_IDENTIFIER 1006L /**< \ingroup err
+ Invalid identifier (invalid special characters, ...) */
+#define PI_CNTR_UNKNOWN_VARIABLE_OR_ARGUMENT__1007 1007L
+#define PI_CNTR_UNKNOWN_VARIABLE_OR_ARGUMENT 1007L /**< \ingroup err
+ Variable or argument not defined */
+#define PI_CNTR_RUNNING_MACRO__1008 1008L
+#define PI_CNTR_RUNNING_MACRO 1008L /**< \ingroup err
+ Controller is (already) running a macro */
+#define PI_CNTR_MACRO_INVALID_OPERATOR__1009 1009L
+#define PI_CNTR_MACRO_INVALID_OPERATOR 1009L /**< \ingroup err
+ Invalid or missing operator for condition. Check necessary spaces around operator. */
+#define PI_CNTR_MACRO_NO_ANSWER__1010 1010L
+#define PI_CNTR_MACRO_NO_ANSWER 1010L /**< \ingroup err
+ No answer was received while executing WAC/MEX/JRC/... */
+#define PI_CMD_NOT_VALID_IN_MACRO_MODE__1011 1011L
+#define PI_CMD_NOT_VALID_IN_MACRO_MODE 1011L /**< \ingroup err
+ Command not valid during macro execution */
+#define PI_CNTR_MOTION_ERROR__1024 1024L
+#define PI_CNTR_MOTION_ERROR 1024L /**< \ingroup err
+ Motion error: position error too large, servo is switched off automatically */
+#define PI_CNTR_EXT_PROFILE_UNALLOWED_CMD__1063 1063L
+#define PI_CNTR_EXT_PROFILE_UNALLOWED_CMD 1063L /**< \ingroup err
+ User Profile Mode: Command is not allowed, check for required preparatory commands */
+#define PI_CNTR_EXT_PROFILE_EXPECTING_MOTION_ERROR__1064 1064L
+#define PI_CNTR_EXT_PROFILE_EXPECTING_MOTION_ERROR 1064L /**< \ingroup err
+ User Profile Mode: First target position in User Profile is too far from current position */
+#define PI_CNTR_PROFILE_ACTIVE__1065 1065L
+#define PI_CNTR_PROFILE_ACTIVE 1065L /**< \ingroup err
+ Controller is (already) in User Profile Mode */
+#define PI_CNTR_PROFILE_INDEX_OUT_OF_RANGE__1066 1066L
+#define PI_CNTR_PROFILE_INDEX_OUT_OF_RANGE 1066L /**< \ingroup err
+ User Profile Mode: Block or Data Set index out of allowed range */
+#define PI_CNTR_PROFILE_OUT_OF_MEMORY__1071 1071L
+#define PI_CNTR_PROFILE_OUT_OF_MEMORY 1071L /**< \ingroup err
+ User Profile Mode: Out of memory */
+#define PI_CNTR_PROFILE_WRONG_CLUSTER__1072 1072L
+#define PI_CNTR_PROFILE_WRONG_CLUSTER 1072L /**< \ingroup err
+ User Profile Mode: Cluster is not assigned to this axis */
+#define PI_CNTR_PROFILE_UNKNOWN_CLUSTER_IDENTIFIER__1073 1073L
+#define PI_CNTR_PROFILE_UNKNOWN_CLUSTER_IDENTIFIER 1073L /**< \ingroup err
+ Unknown cluster identifier */
+#define PI_CNTR_ALREADY_HAS_SERIAL_NUMBER__2000 2000L
+#define PI_CNTR_ALREADY_HAS_SERIAL_NUMBER 2000L /**< \ingroup err
+ Controller already has a serial number */
+#define PI_CNTR_SECTOR_ERASE_FAILED__4000 4000L
+#define PI_CNTR_SECTOR_ERASE_FAILED 4000L /**< \ingroup err
+ Sector erase failed */
+#define PI_CNTR_FLASH_PROGRAM_FAILED__4001 4001L
+#define PI_CNTR_FLASH_PROGRAM_FAILED 4001L /**< \ingroup err
+ Flash program failed */
+#define PI_CNTR_FLASH_READ_FAILED__4002 4002L
+#define PI_CNTR_FLASH_READ_FAILED 4002L /**< \ingroup err
+ Flash read failed */
+#define PI_CNTR_HW_MATCHCODE_ERROR__4003 4003L
+#define PI_CNTR_HW_MATCHCODE_ERROR 4003L /**< \ingroup err
+ HW match code missing/invalid */
+#define PI_CNTR_FW_MATCHCODE_ERROR__4004 4004L
+#define PI_CNTR_FW_MATCHCODE_ERROR 4004L /**< \ingroup err
+ FW match code missing/invalid */
+#define PI_CNTR_HW_VERSION_ERROR__4005 4005L
+#define PI_CNTR_HW_VERSION_ERROR 4005L /**< \ingroup err
+ HW version missing/invalid */
+#define PI_CNTR_FW_VERSION_ERROR__4006 4006L
+#define PI_CNTR_FW_VERSION_ERROR 4006L /**< \ingroup err
+ FW version missing/invalid */
+#define PI_CNTR_FW_UPDATE_ERROR__4007 4007L
+#define PI_CNTR_FW_UPDATE_ERROR 4007L /**< \ingroup err
+ FW update failed */
+#define PI_CNTR_FW_CRC_PAR_ERROR__4008 4008L
+#define PI_CNTR_FW_CRC_PAR_ERROR 4008L /**< \ingroup err
+ FW Parameter CRC wrong */
+#define PI_CNTR_FW_CRC_FW_ERROR__4009 4009L
+#define PI_CNTR_FW_CRC_FW_ERROR 4009L /**< \ingroup err
+ FW CRC wrong */
+#define PI_CNTR_INVALID_PCC_SCAN_DATA__5000 5000L
+#define PI_CNTR_INVALID_PCC_SCAN_DATA 5000L /**< \ingroup err
+ PicoCompensation scan data is not valid */
+#define PI_CNTR_PCC_SCAN_RUNNING__5001 5001L
+#define PI_CNTR_PCC_SCAN_RUNNING 5001L /**< \ingroup err
+ PicoCompensation is running, some actions can not be executed during scanning/recording */
+#define PI_CNTR_INVALID_PCC_AXIS__5002 5002L
+#define PI_CNTR_INVALID_PCC_AXIS 5002L /**< \ingroup err
+ Given axis can not be defined as PPC axis */
+#define PI_CNTR_PCC_SCAN_OUT_OF_RANGE__5003 5003L
+#define PI_CNTR_PCC_SCAN_OUT_OF_RANGE 5003L /**< \ingroup err
+ Defined scan area is larger than the travel range */
+#define PI_CNTR_PCC_TYPE_NOT_EXISTING__5004 5004L
+#define PI_CNTR_PCC_TYPE_NOT_EXISTING 5004L /**< \ingroup err
+ Given PicoCompensation type is not defined */
+#define PI_CNTR_PCC_PAM_ERROR__5005 5005L
+#define PI_CNTR_PCC_PAM_ERROR 5005L /**< \ingroup err
+ PicoCompensation parameter error */
+#define PI_CNTR_PCC_TABLE_ARRAY_TOO_LARGE__5006 5006L
+#define PI_CNTR_PCC_TABLE_ARRAY_TOO_LARGE 5006L /**< \ingroup err
+ PicoCompensation table is larger than maximum table length */
+#define PI_CNTR_NEXLINE_ERROR__5100 5100L
+#define PI_CNTR_NEXLINE_ERROR 5100L /**< \ingroup err
+ Common error in Nexline firmware module */
+#define PI_CNTR_CHANNEL_ALREADY_USED__5101 5101L
+#define PI_CNTR_CHANNEL_ALREADY_USED 5101L /**< \ingroup err
+ Output channel for Nexline can not be redefined for other usage */
+#define PI_CNTR_NEXLINE_TABLE_TOO_SMALL__5102 5102L
+#define PI_CNTR_NEXLINE_TABLE_TOO_SMALL 5102L /**< \ingroup err
+ Memory for Nexline signals is too small */
+#define PI_CNTR_RNP_WITH_SERVO_ON__5103 5103L
+#define PI_CNTR_RNP_WITH_SERVO_ON 5103L /**< \ingroup err
+ RNP can not be executed if axis is in closed loop */
+#define PI_CNTR_RNP_NEEDED__5104 5104L
+#define PI_CNTR_RNP_NEEDED 5104L /**< \ingroup err
+ relax procedure (RNP) needed */
+#define PI_CNTR_AXIS_NOT_CONFIGURED__5200 5200L
+#define PI_CNTR_AXIS_NOT_CONFIGURED 5200L /**< \ingroup err
+ Axis must be configured for this action */
+//
+// End of Controller Errors
+//////////////////////////////////////////////////
+
+//////////////////////////////////////////////////
+//
+// Interface Errors - Interface errors occuring while communicating with the controller
+//
+#define COM_NO_ERROR__0 0L
+#define COM_NO_ERROR 0L /**< \ingroup err
+ No error occurred during function call */
+#define COM_ERROR__MINUS1 -1L
+#define COM_ERROR -1L /**< \ingroup err
+ Error during com operation (could not be specified) */
+#define SEND_ERROR__MINUS2 -2L
+#define SEND_ERROR -2L /**< \ingroup err
+ Error while sending data */
+#define REC_ERROR__MINUS3 -3L
+#define REC_ERROR -3L /**< \ingroup err
+ Error while receiving data */
+#define NOT_CONNECTED_ERROR__MINUS4 -4L
+#define NOT_CONNECTED_ERROR -4L /**< \ingroup err
+ Not connected (no port with given ID open) */
+#define COM_BUFFER_OVERFLOW__MINUS5 -5L
+#define COM_BUFFER_OVERFLOW -5L /**< \ingroup err
+ Buffer overflow */
+#define CONNECTION_FAILED__MINUS6 -6L
+#define CONNECTION_FAILED -6L /**< \ingroup err
+ Error while opening port */
+#define COM_TIMEOUT__MINUS7 -7L
+#define COM_TIMEOUT -7L /**< \ingroup err
+ Timeout error */
+#define COM_MULTILINE_RESPONSE__MINUS8 -8L
+#define COM_MULTILINE_RESPONSE -8L /**< \ingroup err
+ There are more lines waiting in buffer */
+#define COM_INVALID_ID__MINUS9 -9L
+#define COM_INVALID_ID -9L /**< \ingroup err
+ There is no interface or DLL handle with the given ID */
+#define COM_NOTIFY_EVENT_ERROR__MINUS10 -10L
+#define COM_NOTIFY_EVENT_ERROR -10L /**< \ingroup err
+ Event/message for notification could not be opened */
+#define COM_NOT_IMPLEMENTED__MINUS11 -11L
+#define COM_NOT_IMPLEMENTED -11L /**< \ingroup err
+ Function not supported by this interface type */
+#define COM_ECHO_ERROR__MINUS12 -12L
+#define COM_ECHO_ERROR -12L /**< \ingroup err
+ Error while sending \"echoed\" data */
+#define COM_GPIB_EDVR__MINUS13 -13L
+#define COM_GPIB_EDVR -13L /**< \ingroup err
+ IEEE488: System error */
+#define COM_GPIB_ECIC__MINUS14 -14L
+#define COM_GPIB_ECIC -14L /**< \ingroup err
+ IEEE488: Function requires GPIB board to be CIC */
+#define COM_GPIB_ENOL__MINUS15 -15L
+#define COM_GPIB_ENOL -15L /**< \ingroup err
+ IEEE488: Write function detected no listeners */
+#define COM_GPIB_EADR__MINUS16 -16L
+#define COM_GPIB_EADR -16L /**< \ingroup err
+ IEEE488: Interface board not addressed correctly */
+#define COM_GPIB_EARG__MINUS17 -17L
+#define COM_GPIB_EARG -17L /**< \ingroup err
+ IEEE488: Invalid argument to function call */
+#define COM_GPIB_ESAC__MINUS18 -18L
+#define COM_GPIB_ESAC -18L /**< \ingroup err
+ IEEE488: Function requires GPIB board to be SAC */
+#define COM_GPIB_EABO__MINUS19 -19L
+#define COM_GPIB_EABO -19L /**< \ingroup err
+ IEEE488: I/O operation aborted */
+#define COM_GPIB_ENEB__MINUS20 -20L
+#define COM_GPIB_ENEB -20L /**< \ingroup err
+ IEEE488: Interface board not found */
+#define COM_GPIB_EDMA__MINUS21 -21L
+#define COM_GPIB_EDMA -21L /**< \ingroup err
+ IEEE488: Error performing DMA */
+#define COM_GPIB_EOIP__MINUS22 -22L
+#define COM_GPIB_EOIP -22L /**< \ingroup err
+ IEEE488: I/O operation started before previous operation completed */
+#define COM_GPIB_ECAP__MINUS23 -23L
+#define COM_GPIB_ECAP -23L /**< \ingroup err
+ IEEE488: No capability for intended operation */
+#define COM_GPIB_EFSO__MINUS24 -24L
+#define COM_GPIB_EFSO -24L /**< \ingroup err
+ IEEE488: File system operation error */
+#define COM_GPIB_EBUS__MINUS25 -25L
+#define COM_GPIB_EBUS -25L /**< \ingroup err
+ IEEE488: Command error during device call */
+#define COM_GPIB_ESTB__MINUS26 -26L
+#define COM_GPIB_ESTB -26L /**< \ingroup err
+ IEEE488: Serial poll-status byte lost */
+#define COM_GPIB_ESRQ__MINUS27 -27L
+#define COM_GPIB_ESRQ -27L /**< \ingroup err
+ IEEE488: SRQ remains asserted */
+#define COM_GPIB_ETAB__MINUS28 -28L
+#define COM_GPIB_ETAB -28L /**< \ingroup err
+ IEEE488: Return buffer full */
+#define COM_GPIB_ELCK__MINUS29 -29L
+#define COM_GPIB_ELCK -29L /**< \ingroup err
+ IEEE488: Address or board locked */
+#define COM_RS_INVALID_DATA_BITS__MINUS30 -30L
+#define COM_RS_INVALID_DATA_BITS -30L /**< \ingroup err
+ RS-232: 5 data bits with 2 stop bits is an invalid combination, as is 6, 7, or 8 data bits with 1.5 stop bits */
+#define COM_ERROR_RS_SETTINGS__MINUS31 -31L
+#define COM_ERROR_RS_SETTINGS -31L /**< \ingroup err
+ RS-232: Error configuring the COM port */
+#define COM_INTERNAL_RESOURCES_ERROR__MINUS32 -32L
+#define COM_INTERNAL_RESOURCES_ERROR -32L /**< \ingroup err
+ Error dealing with internal system resources (events, threads, ...) */
+#define COM_DLL_FUNC_ERROR__MINUS33 -33L
+#define COM_DLL_FUNC_ERROR -33L /**< \ingroup err
+ A DLL or one of the required functions could not be loaded */
+#define COM_FTDIUSB_INVALID_HANDLE__MINUS34 -34L
+#define COM_FTDIUSB_INVALID_HANDLE -34L /**< \ingroup err
+ FTDIUSB: invalid handle */
+#define COM_FTDIUSB_DEVICE_NOT_FOUND__MINUS35 -35L
+#define COM_FTDIUSB_DEVICE_NOT_FOUND -35L /**< \ingroup err
+ FTDIUSB: device not found */
+#define COM_FTDIUSB_DEVICE_NOT_OPENED__MINUS36 -36L
+#define COM_FTDIUSB_DEVICE_NOT_OPENED -36L /**< \ingroup err
+ FTDIUSB: device not opened */
+#define COM_FTDIUSB_IO_ERROR__MINUS37 -37L
+#define COM_FTDIUSB_IO_ERROR -37L /**< \ingroup err
+ FTDIUSB: IO error */
+#define COM_FTDIUSB_INSUFFICIENT_RESOURCES__MINUS38 -38L
+#define COM_FTDIUSB_INSUFFICIENT_RESOURCES -38L /**< \ingroup err
+ FTDIUSB: insufficient resources */
+#define COM_FTDIUSB_INVALID_PARAMETER__MINUS39 -39L
+#define COM_FTDIUSB_INVALID_PARAMETER -39L /**< \ingroup err
+ FTDIUSB: invalid parameter */
+#define COM_FTDIUSB_INVALID_BAUD_RATE__MINUS40 -40L
+#define COM_FTDIUSB_INVALID_BAUD_RATE -40L /**< \ingroup err
+ FTDIUSB: invalid baud rate */
+#define COM_FTDIUSB_DEVICE_NOT_OPENED_FOR_ERASE__MINUS41 -41L
+#define COM_FTDIUSB_DEVICE_NOT_OPENED_FOR_ERASE -41L /**< \ingroup err
+ FTDIUSB: device not opened for erase */
+#define COM_FTDIUSB_DEVICE_NOT_OPENED_FOR_WRITE__MINUS42 -42L
+#define COM_FTDIUSB_DEVICE_NOT_OPENED_FOR_WRITE -42L /**< \ingroup err
+ FTDIUSB: device not opened for write */
+#define COM_FTDIUSB_FAILED_TO_WRITE_DEVICE__MINUS43 -43L
+#define COM_FTDIUSB_FAILED_TO_WRITE_DEVICE -43L /**< \ingroup err
+ FTDIUSB: failed to write device */
+#define COM_FTDIUSB_EEPROM_READ_FAILED__MINUS44 -44L
+#define COM_FTDIUSB_EEPROM_READ_FAILED -44L /**< \ingroup err
+ FTDIUSB: EEPROM read failed */
+#define COM_FTDIUSB_EEPROM_WRITE_FAILED__MINUS45 -45L
+#define COM_FTDIUSB_EEPROM_WRITE_FAILED -45L /**< \ingroup err
+ FTDIUSB: EEPROM write failed */
+#define COM_FTDIUSB_EEPROM_ERASE_FAILED__MINUS46 -46L
+#define COM_FTDIUSB_EEPROM_ERASE_FAILED -46L /**< \ingroup err
+ FTDIUSB: EEPROM erase failed */
+#define COM_FTDIUSB_EEPROM_NOT_PRESENT__MINUS47 -47L
+#define COM_FTDIUSB_EEPROM_NOT_PRESENT -47L /**< \ingroup err
+ FTDIUSB: EEPROM not present */
+#define COM_FTDIUSB_EEPROM_NOT_PROGRAMMED__MINUS48 -48L
+#define COM_FTDIUSB_EEPROM_NOT_PROGRAMMED -48L /**< \ingroup err
+ FTDIUSB: EEPROM not programmed */
+#define COM_FTDIUSB_INVALID_ARGS__MINUS49 -49L
+#define COM_FTDIUSB_INVALID_ARGS -49L /**< \ingroup err
+ FTDIUSB: invalid arguments */
+#define COM_FTDIUSB_NOT_SUPPORTED__MINUS50 -50L
+#define COM_FTDIUSB_NOT_SUPPORTED -50L /**< \ingroup err
+ FTDIUSB: not supported */
+#define COM_FTDIUSB_OTHER_ERROR__MINUS51 -51L
+#define COM_FTDIUSB_OTHER_ERROR -51L /**< \ingroup err
+ FTDIUSB: other error */
+#define COM_PORT_ALREADY_OPEN__MINUS52 -52L
+#define COM_PORT_ALREADY_OPEN -52L /**< \ingroup err
+ Error while opening the COM port: was already open */
+#define COM_PORT_CHECKSUM_ERROR__MINUS53 -53L
+#define COM_PORT_CHECKSUM_ERROR -53L /**< \ingroup err
+ Checksum error in received data from COM port */
+#define COM_SOCKET_NOT_READY__MINUS54 -54L
+#define COM_SOCKET_NOT_READY -54L /**< \ingroup err
+ Socket not ready, you should call the function again */
+#define COM_SOCKET_PORT_IN_USE__MINUS55 -55L
+#define COM_SOCKET_PORT_IN_USE -55L /**< \ingroup err
+ Port is used by another socket */
+#define COM_SOCKET_NOT_CONNECTED__MINUS56 -56L
+#define COM_SOCKET_NOT_CONNECTED -56L /**< \ingroup err
+ Socket not connected (or not valid) */
+#define COM_SOCKET_TERMINATED__MINUS57 -57L
+#define COM_SOCKET_TERMINATED -57L /**< \ingroup err
+ Connection terminated (by peer) */
+#define COM_SOCKET_NO_RESPONSE__MINUS58 -58L
+#define COM_SOCKET_NO_RESPONSE -58L /**< \ingroup err
+ Can't connect to peer */
+#define COM_SOCKET_INTERRUPTED__MINUS59 -59L
+#define COM_SOCKET_INTERRUPTED -59L /**< \ingroup err
+ Operation was interrupted by a nonblocked signal */
+#define COM_PCI_INVALID_ID__MINUS60 -60L
+#define COM_PCI_INVALID_ID -60L /**< \ingroup err
+ No Device with this ID is present */
+#define COM_PCI_ACCESS_DENIED__MINUS61 -61L
+#define COM_PCI_ACCESS_DENIED -61L /**< \ingroup err
+ Driver could not be opened (on Vista: run as administrator!) */
+//
+// End of Interface Errors
+//////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// obsolet, provided for backward compatibility
+#define PI_CNTR_MOVE_WITHOUT_INI 5 // name "INI" is misleading - we mean "reference"
+#define PI_CNTR_INVALID_AXIS 23 // misleading name: INVALID means something different than "illegal"
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#endif // __PI_CONTROLLER_ERROS_H__
+
diff --git a/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/translateerror.c b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/translateerror.c
new file mode 100755
index 00000000..d505bfc5
--- /dev/null
+++ b/motorApp/PI_GCS2/PI_GCS2_App/PI_GCS2_Src/translateerror.c
@@ -0,0 +1,3132 @@
+/*
+ * TranslateErrors.c
+ *
+ *
+ * This file is automagically generated from the central error code list.
+ * DO NOT ADD ERROR CODES IN THIS FILE! Use the error list and the generation tool instead!
+ *
+ */
+
+#include
+#include
+
+#include "picontrollererrors.h"
+
+#ifndef BOOL
+#define BOOL int
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+/**
+ * translate error code to c-string
+ */
+BOOL TranslatePIError(const int error, char* szBuffer, const int maxlen)
+{
+ switch (error)
+ {
+/*************************************************
+ **
+ ** Dll Errors - DLL errors occured in GCS DLL
+ */
+ case(PI_UNKNOWN_AXIS_IDENTIFIER): /* -1001 */
+ {
+ if (strlen("Unknown axis identifier")0")0");
+ return TRUE;
+ }
+ break;
+ }
+ case(PI_WAV_SAMPLES_OUT_OF_RANGE): /* -1022 */
+ {
+ if (strlen("Incorrect number of samples given to WAV")
+
+# Set this when your IOC and the host use different paths
+# to access the application. This will be needed to boot
+# from a Microsoft FTP server or with some NFS mounts.
+# You must rebuild in the iocBoot directory for this to
+# take effect.
+#IOCS_APPL_TOP =
diff --git a/motorApp/PI_GCS2/configure/Makefile b/motorApp/PI_GCS2/configure/Makefile
new file mode 100755
index 00000000..914f4f88
--- /dev/null
+++ b/motorApp/PI_GCS2/configure/Makefile
@@ -0,0 +1,8 @@
+TOP=..
+
+include $(TOP)/configure/CONFIG
+
+TARGETS = $(CONFIG_TARGETS)
+CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
+
+include $(TOP)/configure/RULES
diff --git a/motorApp/PI_GCS2/configure/RELEASE b/motorApp/PI_GCS2/configure/RELEASE
new file mode 100755
index 00000000..a5ae5e13
--- /dev/null
+++ b/motorApp/PI_GCS2/configure/RELEASE
@@ -0,0 +1,36 @@
+# RELEASE - Location of external support modules
+#
+# IF YOU MAKE ANY CHANGES to this file you must subsequently
+# do a "gnumake rebuild" in this application's top level
+# directory.
+#
+# The build process does not check dependencies against files
+# that are outside this application, thus you should do a
+# "gnumake rebuild" in the top level directory after EPICS_BASE
+# or any other external module pointed to below is rebuilt.
+#
+# Host- or target-specific settings can be given in files named
+# RELEASE.$(EPICS_HOST_ARCH).Common
+# RELEASE.Common.$(T_A)
+# RELEASE.$(EPICS_HOST_ARCH).$(T_A)
+#
+# This file should ONLY define paths to other support modules,
+# or include statements that pull in similar RELEASE files.
+# Build settings that are NOT module paths should appear in a
+# CONFIG_SITE file.
+
+TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
+
+# If using the sequencer, point SNCSEQ at its top directory:
+#SNCSEQ=$(EPICS_BASE)/../modules/soft/seq
+
+# EPICS_BASE usually appears last so other apps can override stuff:
+EPICS_BASE=/home/sra/epics/base
+
+# Set RULES here if you want to take build rules from somewhere
+# other than EPICS_BASE:
+#RULES=/path/to/epics/support/module/rules/x-y
+
+ASYN=/home/sra/epics/synApps_5_6/support/asyn-4-18
+MOTOR=/home/sra/epics/synApps_5_6/support/motor-6-7
+
diff --git a/motorApp/PI_GCS2/configure/RULES b/motorApp/PI_GCS2/configure/RULES
new file mode 100755
index 00000000..6a97327c
--- /dev/null
+++ b/motorApp/PI_GCS2/configure/RULES
@@ -0,0 +1,6 @@
+# RULES
+
+include $(CONFIG)/RULES
+
+# Library should be rebuilt because LIBOBJS may have changed.
+$(LIBNAME): ../Makefile
diff --git a/motorApp/PI_GCS2/configure/RULES.ioc b/motorApp/PI_GCS2/configure/RULES.ioc
new file mode 100755
index 00000000..a445ea56
--- /dev/null
+++ b/motorApp/PI_GCS2/configure/RULES.ioc
@@ -0,0 +1,2 @@
+#RULES.ioc
+include $(CONFIG)/RULES.ioc
diff --git a/motorApp/PI_GCS2/configure/RULES_DIRS b/motorApp/PI_GCS2/configure/RULES_DIRS
new file mode 100755
index 00000000..3535ca4f
--- /dev/null
+++ b/motorApp/PI_GCS2/configure/RULES_DIRS
@@ -0,0 +1,2 @@
+#RULES_DIRS
+include $(CONFIG)/RULES_DIRS
diff --git a/motorApp/PI_GCS2/configure/RULES_TOP b/motorApp/PI_GCS2/configure/RULES_TOP
new file mode 100755
index 00000000..ad13fced
--- /dev/null
+++ b/motorApp/PI_GCS2/configure/RULES_TOP
@@ -0,0 +1,3 @@
+#RULES_TOP
+include $(CONFIG)/RULES_TOP
+