diff --git a/.gitmodules b/.gitmodules index 0f0a2c46..8c542b09 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "modules/motorNewport"] path = modules/motorNewport url = https://github.com/epics-motor/motorNewport.git +[submodule "modules/motorOms"] + path = modules/motorOms + url = https://github.com/epics-motor/motorOms.git diff --git a/iocBoot/iocNoAsyn/st.cmd.Vx b/iocBoot/iocNoAsyn/st.cmd.Vx index ca05ba6c..1d64f59e 100644 --- a/iocBoot/iocNoAsyn/st.cmd.Vx +++ b/iocBoot/iocNoAsyn/st.cmd.Vx @@ -1,4 +1,4 @@ -# This example if for OMS VME8/44 controllers. Since OMS controllers +# This example is for controllers that # communicate across the VME backplane, this example does not require # ASYN. @@ -23,51 +23,6 @@ dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=IOC:") #!dbLoadRecords("$(TOP)/motorApp/Db/SoftMotorEx.db","user=IOC,motor=m1", startup) -# OMS VME driver setup parameters: -# (1)cards, (2)base address(short, 16-byte boundary), -# (3)interrupt vector (0=disable or 64 - 255), (4)interrupt level (1 - 6), -# (5)motor task polling rate (min=1Hz,max=60Hz) -#!omsSetup(1, 0xFC00, 180, 5, 10) -#!drvOMSdebug = 4 - -# OMS VME58 driver setup parameters: -# (1)cards, (2)base address(short, 4k boundary), -# (3)interrupt vector (0=disable or 64 - 255), (4)interrupt level (1 - 6), -# (5)motor task polling rate (min=1Hz,max=60Hz) -#!oms58Setup(1, 0x1000, 190, 5, 10) -#!drvOms58debug = 4 - -# OMS MAXv driver setup parameters: -# (1)number of cards in array. -# (2)VME Address Space - A(16,24,32). -# (3)Base Address (see README file). -# (4)interrupt vector (0=disable or 64 - 255). -# (5)interrupt level (2 - 6). -# (6)motor task polling rate (min=1Hz,max=60Hz). -#!MAXvSetup(1, 16, 0xF000, 200, 5, 10) -#!MAXvSetup(1, 24, 0xFF0000, 200, 5, 10) -#!MAXvSetup(1, 32, 0xFF000000, 200, 5, 10) -#!drvMAXvdebug=4 - -# OMS MAXv configuration string: -# (1) number of card being configured (0-14). -# (2) configuration string; axis type (PSO/PSE/PSM) MUST be set here. -# For example, set which TTL signal level defines -# an active limit switch. Set X,Y,Z,T to active low and set U,V,R,S -# to active high. Set all axes to open-loop stepper (PSO). See MAXv -# User's Manual for LTL/LTH and PSO/PSE/PSM commands. -# (3) SSI based absolute encoder bit flag. Bit #0 for Axis X, bit #1 for -# Axis Y, etc.. Set a bit flag to '1' for absolute encoder values; '0' -# for the standard incremental encoder values. -# (4) SSI based absolute encoder grey code flags (0/1 - yes/no, 0x12 -> UY) - -#!str = malloc(200); -#!strcpy str, "AA; LMH,H,H,H,H,H,H,H;" -#!strcat str, "AX LTH PSO; AY LTH PSO; AZ LTL PSO; AT LTL PSO; AU LTL PSO; AV LTL PSO; AR LTL PSO; AS LTL PSO;" -#!MAXvConfig(0, str, 0, 0) -#!free(str) - - # PMAC VME driver setup parameters: # (1)cards, (2) VME Address Type (24,32) # (3)Mailbox base address, (4)DPRAM base address, diff --git a/iocBoot/iocWithAsyn/st.cmd.Vx b/iocBoot/iocWithAsyn/st.cmd.Vx index d62d4d0c..85b86d2d 100644 --- a/iocBoot/iocWithAsyn/st.cmd.Vx +++ b/iocBoot/iocWithAsyn/st.cmd.Vx @@ -161,17 +161,6 @@ dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=IOC:") #!MDriveConfig(0, "a-Serial[0]") #!drvMDrivedebug = 4 -# OMS PC68/78 stand-alone serial driver setup parameters: -# (1) maximum number of controllers in system -# (2) motor task polling rate (min=1Hz,max=60Hz) -#!OmsPC68Setup(1, 10) - -# OMS PC68/78 stand-alone serial driver configuration parameters: -# (1) Card# being configured -# (2) asyn port name -#!OmsPC68Config(0, "L0") -#!drvOmsPC68debug=4 - # Kohzu SC-800 motor controller setup parameters: # (1) maximum number of controllers in system # (2) motor task polling rate (min=1Hz,max=60Hz) diff --git a/modules/Makefile b/modules/Makefile index ae9161aa..9b97b318 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -3,6 +3,7 @@ include $(TOP)/configure/CONFIG # Submodules #SUBMODULES += motorVendor +SUBMODULES += motorOms SUBMODULES += motorNewport # Allow sites to add extra submodules diff --git a/modules/motorOms b/modules/motorOms new file mode 160000 index 00000000..052194c4 --- /dev/null +++ b/modules/motorOms @@ -0,0 +1 @@ +Subproject commit 052194c426d67983825b07516cffb4b72e8ef1c0 diff --git a/motorApp/OmsSrc/MAX_trajectoryScan.h b/motorApp/OmsSrc/MAX_trajectoryScan.h deleted file mode 100644 index f938e90d..00000000 --- a/motorApp/OmsSrc/MAX_trajectoryScan.h +++ /dev/null @@ -1,360 +0,0 @@ -/* MAX_trajectoryScan.h - * - * This file is included in MAX_trajectoryScan.st. - */ - - -/* State codes for Build, Read and Execute. Careful, these must match the - * corresponding MBBI records, but there is no way to check this */ -#define BUILD_STATE_DONE 0 -#define BUILD_STATE_BUSY 1 -#define READ_STATE_DONE 0 -#define READ_STATE_BUSY 1 -#define EXECUTE_STATE_DONE 0 -#define EXECUTE_STATE_MOVE_START 1 -#define EXECUTE_STATE_EXECUTING 2 -#define EXECUTE_STATE_FLYBACK 3 - -/* Status codes for Build, Execute and Read */ -#define STATUS_UNDEFINED 0 -#define STATUS_SUCCESS 1 -#define STATUS_FAILURE 2 -#define STATUS_ABORT 3 -#define STATUS_TIMEOUT 4 - -/* Time modes */ -#define TIME_MODE_TOTAL 0 -#define TIME_MODE_PER_ELEMENT 1 - -/* Move modes */ -#define MOVE_MODE_RELATIVE 0 -#define MOVE_MODE_ABSOLUTE 1 -#define MOVE_MODE_HYBRID 2 - -/* The maximum number of axes per controller. If this is changed from 8 - * then many assign statements in this file must be changed */ -#define MAX_AXES 8 - -#define MSGSIZE 40 - -/* Define PVs */ -int debugLevel; assign debugLevel to "{P}{R}DebugLevel.VAL"; -monitor debugLevel; -int numAxes; assign numAxes to "{P}{R}NumAxes.VAL"; -monitor numAxes; -int nelements; assign nelements to "{P}{R}Nelements.VAL"; -monitor nelements; -int npulses; assign npulses to "{P}{R}Npulses.VAL"; -monitor npulses; -int startPulses; assign startPulses to "{P}{R}StartPulses.VAL"; -monitor startPulses; -int endPulses; assign endPulses to "{P}{R}EndPulses.VAL"; -monitor endPulses; -int nactual; assign nactual to "{P}{R}Nactual.VAL"; -int moveMode; assign moveMode to "{P}{R}MoveMode.VAL"; -monitor moveMode; -double time_PV; assign time_PV to "{P}{R}Time.VAL"; -monitor time_PV; -double timeScale; assign timeScale to "{P}{R}TimeScale.VAL"; -monitor timeScale; -int timeMode; assign timeMode to "{P}{R}TimeMode.VAL"; -monitor timeMode; -double accel; assign accel to "{P}{R}Accel.VAL"; -monitor accel; -int build; assign build to "{P}{R}Build.VAL"; -monitor build; -int buildState; assign buildState to "{P}{R}BuildState.VAL"; -int buildStatus; assign buildStatus to "{P}{R}BuildStatus.VAL"; -string buildMessage;assign buildMessage to "{P}{R}BuildMessage.VAL"; -int simMode; assign simMode to "{P}{R}SimMode.VAL"; -monitor simMode; -int execute; assign execute to "{P}{R}Execute.VAL"; -monitor execute; -int execState; assign execState to "{P}{R}ExecState.VAL"; -monitor execState; -int execStatus; assign execStatus to "{P}{R}ExecStatus.VAL"; -string execMessage; assign execMessage to "{P}{R}ExecMessage.VAL"; -int abort; assign abort to "{P}{R}Abort.VAL"; -monitor abort; -int readback; assign readback to "{P}{R}Readback.VAL"; -monitor readback; -int readState; assign readState to "{P}{R}ReadState.VAL"; -int readStatus; assign readStatus to "{P}{R}ReadStatus.VAL"; -string readMessage; assign readMessage to "{P}{R}ReadMessage.VAL"; -double timeTrajectory[MAX_ELEMENTS]; -assign timeTrajectory to "{P}{R}TimeTraj.VAL"; -monitor timeTrajectory; -string trajectoryFile; assign trajectoryFile to "{P}{R}TrajectoryFile.VAL"; -monitor trajectoryFile; - -/*** BEGIN: Specific to MAX_trajectoryScan.st ***/ - -/* time since trajectory start */ -double elapsedTime; assign elapsedTime to "{P}{R}ElapsedTime.VAL"; - -/* Number (0..15) of general purpose I/O bit to be used for output pulses (e.g., to trigger detector). */ -int outBitNum; assign outBitNum to "{P}{R}OutBitNum.VAL"; -monitor outBitNum; - -/* Number (0..15) of general purpose I/O bit to be used for input start-trajectory pulse. */ -int inBitNum; assign inBitNum to "{P}{R}InBitNum.VAL"; -monitor inBitNum; - -/* Used to calculate velocity-override percentages while trajectory is executing */ -double overrideFactor; assign overrideFactor to "{P}{R}OverrideFactor"; -monitor overrideFactor; - -/* MAX controller's update frequency (one of 1024, 2048, 4096, or 8192 Hz) */ -int updateFreq; assign updateFreq to "{P}{R}UpdateFreq.RVAL"; -monitor updateFreq; - -/* time in seconds from trajectory start */ -double realTimeTrajectory[MAX_ELEMENTS]; -assign realTimeTrajectory to "{P}{R}realTimeTrajectory.VAL"; - -/* raw values read from the controller, generally while a trajectory is executing */ -int motorCurrentRaw[MAX_AXES]; -int motorCurrentVRaw[MAX_AXES]; -int motorCurrentARaw[MAX_AXES]; - -/* EPICS motor record resolution */ -double epicsMotorMres[MAX_AXES]; -assign epicsMotorMres to {"","","","","","","",""}; -monitor epicsMotorMres; - -/* EPICS motor-controller card number. (For now, we talk to the controller via drvMAX.cc) */ -int epicsMotorCard[MAX_AXES]; -assign epicsMotorCard to {"","","","","","","",""}; -monitor epicsMotorCard; - -/* EPICS motor record soft limits */ -double epicsMotorHLM[MAX_AXES]; -assign epicsMotorHLM to {"","","","","","","",""}; -monitor epicsMotorHLM; -double epicsMotorLLM[MAX_AXES]; -assign epicsMotorLLM to {"","","","","","","",""}; -monitor epicsMotorLLM; - -double motorMinSpeed[MAX_AXES]; -assign motorMinSpeed to - {"{P}{R}M1MinSpeed.VAL", - "{P}{R}M2MinSpeed.VAL", - "{P}{R}M3MinSpeed.VAL", - "{P}{R}M4MinSpeed.VAL", - "{P}{R}M5MinSpeed.VAL", - "{P}{R}M6MinSpeed.VAL", - "{P}{R}M7MinSpeed.VAL", - "{P}{R}M8MinSpeed.VAL"}; - -double motorMaxSpeed[MAX_AXES]; -assign motorMaxSpeed to - {"{P}{R}M1MaxSpeed.VAL", - "{P}{R}M2MaxSpeed.VAL", - "{P}{R}M3MaxSpeed.VAL", - "{P}{R}M4MaxSpeed.VAL", - "{P}{R}M5MaxSpeed.VAL", - "{P}{R}M6MaxSpeed.VAL", - "{P}{R}M7MaxSpeed.VAL", - "{P}{R}M8MaxSpeed.VAL"}; - -double motorStart[MAX_AXES]; -assign motorStart to - {"{P}{R}M1Start.VAL", - "{P}{R}M2Start.VAL", - "{P}{R}M3Start.VAL", - "{P}{R}M4Start.VAL", - "{P}{R}M5Start.VAL", - "{P}{R}M6Start.VAL", - "{P}{R}M7Start.VAL", - "{P}{R}M8Start.VAL"}; - -int addAccelDecel; assign addAccelDecel to "{P}{R}AddAccelDecel.VAL"; -monitor addAccelDecel; -evflag moveModeMon; sync moveMode moveModeMon; -int moveModePrev; - -/*** END: Specific to MAX_trajectoryScan.st ***/ - -int moveAxis[MAX_AXES]; -assign moveAxis to - {"{P}{R}M1Move.VAL", - "{P}{R}M2Move.VAL", - "{P}{R}M3Move.VAL", - "{P}{R}M4Move.VAL", - "{P}{R}M5Move.VAL", - "{P}{R}M6Move.VAL", - "{P}{R}M7Move.VAL", - "{P}{R}M8Move.VAL"}; -monitor moveAxis; - -double motorTrajectory[MAX_AXES][MAX_ELEMENTS]; -assign motorTrajectory to - {"{P}{R}M1Traj.VAL", - "{P}{R}M2Traj.VAL", - "{P}{R}M3Traj.VAL", - "{P}{R}M4Traj.VAL", - "{P}{R}M5Traj.VAL", - "{P}{R}M6Traj.VAL", - "{P}{R}M7Traj.VAL", - "{P}{R}M8Traj.VAL"}; -monitor motorTrajectory; - -double motorReadbacks[MAX_AXES][MAX_PULSES]; -assign motorReadbacks to - {"{P}{R}M1Actual.VAL", - "{P}{R}M2Actual.VAL", - "{P}{R}M3Actual.VAL", - "{P}{R}M4Actual.VAL", - "{P}{R}M5Actual.VAL", - "{P}{R}M6Actual.VAL", - "{P}{R}M7Actual.VAL", - "{P}{R}M8Actual.VAL"}; - -double motorError[MAX_AXES][MAX_PULSES]; -assign motorError to - {"{P}{R}M1Error.VAL", - "{P}{R}M2Error.VAL", - "{P}{R}M3Error.VAL", - "{P}{R}M4Error.VAL", - "{P}{R}M5Error.VAL", - "{P}{R}M6Error.VAL", - "{P}{R}M7Error.VAL", - "{P}{R}M8Error.VAL"}; - -double motorCurrent[MAX_AXES]; -assign motorCurrent to - {"{P}{R}M1Current.VAL", - "{P}{R}M2Current.VAL", - "{P}{R}M3Current.VAL", - "{P}{R}M4Current.VAL", - "{P}{R}M5Current.VAL", - "{P}{R}M6Current.VAL", - "{P}{R}M7Current.VAL", - "{P}{R}M8Current.VAL"}; - -double motorMDVS[MAX_AXES]; -assign motorMDVS to - {"{P}{R}M1MDVS.VAL", - "{P}{R}M2MDVS.VAL", - "{P}{R}M3MDVS.VAL", - "{P}{R}M4MDVS.VAL", - "{P}{R}M5MDVS.VAL", - "{P}{R}M6MDVS.VAL", - "{P}{R}M7MDVS.VAL", - "{P}{R}M8MDVS.VAL"}; -monitor motorMDVS; - -double motorMDVA[MAX_AXES]; -assign motorMDVA to - {"{P}{R}M1MDVA.VAL", - "{P}{R}M2MDVA.VAL", - "{P}{R}M3MDVA.VAL", - "{P}{R}M4MDVA.VAL", - "{P}{R}M5MDVA.VAL", - "{P}{R}M6MDVA.VAL", - "{P}{R}M7MDVA.VAL", - "{P}{R}M8MDVA.VAL"}; - -int motorMDVE[MAX_AXES]; -assign motorMDVE to - {"{P}{R}M1MDVE.VAL", - "{P}{R}M2MDVE.VAL", - "{P}{R}M3MDVE.VAL", - "{P}{R}M4MDVE.VAL", - "{P}{R}M5MDVE.VAL", - "{P}{R}M6MDVE.VAL", - "{P}{R}M7MDVE.VAL", - "{P}{R}M8MDVE.VAL"}; - -double motorMVA[MAX_AXES]; -assign motorMVA to - {"{P}{R}M1MVA.VAL", - "{P}{R}M2MVA.VAL", - "{P}{R}M3MVA.VAL", - "{P}{R}M4MVA.VAL", - "{P}{R}M5MVA.VAL", - "{P}{R}M6MVA.VAL", - "{P}{R}M7MVA.VAL", - "{P}{R}M8MVA.VAL"}; - -int motorMVE[MAX_AXES]; -assign motorMVE to - {"{P}{R}M1MVE.VAL", - "{P}{R}M2MVE.VAL", - "{P}{R}M3MVE.VAL", - "{P}{R}M4MVE.VAL", - "{P}{R}M5MVE.VAL", - "{P}{R}M6MVE.VAL", - "{P}{R}M7MVE.VAL", - "{P}{R}M8MVE.VAL"}; - -double motorMAA[MAX_AXES]; -assign motorMAA to - {"{P}{R}M1MAA.VAL", - "{P}{R}M2MAA.VAL", - "{P}{R}M3MAA.VAL", - "{P}{R}M4MAA.VAL", - "{P}{R}M5MAA.VAL", - "{P}{R}M6MAA.VAL", - "{P}{R}M7MAA.VAL", - "{P}{R}M8MAA.VAL"}; - -int motorMAE[MAX_AXES]; -assign motorMAE to - {"{P}{R}M1MAE.VAL", - "{P}{R}M2MAE.VAL", - "{P}{R}M3MAE.VAL", - "{P}{R}M4MAE.VAL", - "{P}{R}M5MAE.VAL", - "{P}{R}M6MAE.VAL", - "{P}{R}M7MAE.VAL", - "{P}{R}M8MAE.VAL"}; - -/* We don't assign the EPICS motors here because there may be fewer than - * MAX_AXES actually in use. */ -double epicsMotorPos[MAX_AXES]; -assign epicsMotorPos to {"","","","","","","",""}; -monitor epicsMotorPos; - -int epicsMotorDir[MAX_AXES]; -assign epicsMotorDir to {"","","","","","","",""}; -monitor epicsMotorDir; - -double epicsMotorOff[MAX_AXES]; -assign epicsMotorOff to {"","","","","","","",""}; -monitor epicsMotorOff; - -double epicsMotorDone[MAX_AXES]; -assign epicsMotorDone to {"","","","","","","",""}; -monitor epicsMotorDone; - -double epicsMotorVELO[MAX_AXES]; -assign epicsMotorVELO to {"","","","","","","",""}; -monitor epicsMotorVELO; - -double epicsMotorVMAX[MAX_AXES]; -assign epicsMotorVMAX to {"","","","","","","",""}; -monitor epicsMotorVMAX; - -double epicsMotorVMIN[MAX_AXES]; -assign epicsMotorVMIN to {"","","","","","","",""}; -monitor epicsMotorVMIN; - -double epicsMotorACCL[MAX_AXES]; -assign epicsMotorACCL to {"","","","","","","",""}; -monitor epicsMotorACCL; - -string epicsMotorOUT[MAX_AXES]; -assign epicsMotorOUT to {"","","","","","","",""}; - - -evflag buildMon; sync build buildMon; -evflag executeMon; sync execute executeMon; -evflag execStateMon; sync execState execStateMon; -evflag abortMon; sync abort abortMon; -evflag readbackMon; sync readback readbackMon; -evflag nelementsMon; sync nelements nelementsMon; -evflag motorMDVSMon; sync motorMDVS motorMDVSMon; - - - diff --git a/motorApp/OmsSrc/MAX_trajectoryScan.st b/motorApp/OmsSrc/MAX_trajectoryScan.st deleted file mode 100644 index 10a14d82..00000000 --- a/motorApp/OmsSrc/MAX_trajectoryScan.st +++ /dev/null @@ -1,1449 +0,0 @@ -program MAX_trajectoryScan("P=13IDC:,R=traj1,M1=M1,M2=M2,M3=M3,M4=M4,M5=M5,M6=M6,M7=M7,M8=M8,PORT=serial1") - -/* sample program invocation: - * dbLoadRecords("$(MOTOR)/motorApp/Db/trajectoryScan.db","P=xxx:,R=traj1:,NAXES=2,NELM=100,NPULSE=100") - * ... - * iocInit() - * ... - * seq &MAX_trajectoryScan, "P=xxx:,R=traj1:,M1=m1,M2=m2,M3=m3,M4=m4,M5=m5,M6=m6,M7=m7,M8=m8,PORT=none" - */ - -/* This sequencer program works with trajectoryScan.db. It implements - * coordinated trajectory motion with an OMS (Prodex) MAXV motor controller. - * Eventually I hope to generalize to a MAXnet controller. (More precisely, - * I hope to generalize to an asyn-based solution which could work for either.) - * - * Tim Mooney -- based on MM4000_trajectoryScan.st by Mark Rivers. - */ - -%% #include -%% #include -%% #include -%% #include -%% #include -%% #include -%% #include -%% #include -%% #include - -#include /* definition of MAGIC */ -#define VERSION_INT(MAJ,MIN) ((MAJ)*1000000+(MIN)*1000) -#define LT_SEQ_VERSION(MAJ,MIN) ((MAGIC) < VERSION_INT(MAJ,MIN)) - -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#define MIN(a,b) ((a) > (b) ? (b) : (a)) -#define NINT(f) (int)((f)>0 ? (f)+0.5 : (f)-0.5) - -/* This program must be compiled with the recursive option */ -option +r; - -/* Maximum # of trajectory elements. The MAXV allows something like 2550 for - * a trajectory preloaded into the controller (unlimited if you're willing to - * write elements while the trajectory is running). For now, we limit the number - * of elements to 1000. This uses a lot of memory, the variable motorTrajectory - * uses MAX_AXES*MAX_ELEMENTS*8 bytes in this SNL program (up to 128KB). - * Similar memory will be required for the records in the database. - * (Note that currently MAX_AXES is fixed at 8, in trajectoryScan.h.) - * MAX_ELEMENTS_P2 = MAX_ELEMENTS+2 is needed for accel/decel - */ -#define MAX_ELEMENTS 1000 -#define MAX_ELEMENTS_P2 1002 - -/* Maximum # of output pulses. For now, we emit a pulse at the beginning of - * every trajectory element. - */ -#define MAX_PULSES 1000 - -/* Note that MAX_ELEMENTS, and MAX_PULSES must be defined before including - * trajectoryScan.h, which defines MAX_AXES. */ -#include "MAX_trajectoryScan.h" - -/* Maximum size of string messages we'll be sending to the MAX controller */ -#define MAX_MESSAGE_STRING 100 - -/* Buffer sizes */ -#define NAME_LEN 100 - -/* Maximum size of string in EPICS string PVs. This is defined in - * epicsTypes.h, but in order to include that file it must be escaped, and then - * SNL compiler gives a warning. */ -#define MAX_STRING_SIZE 40 - -/* After the trajectory commands have been loaded into the MAX controller, nobody - * can talk to it. For relative and hybrid trajectories, this is sort of ok, because - * we don't need to move the motor to the start point. But if the user wants to - * load a trajectory and then move the motor before executing the trajectory, the - * move will fail. If LOAD_EARLY==0, we postpone loading the trajectory until we get - * an "Execute" command. This avoids all kinds of problems, but imposes a few second - * delay before execution actually starts. - */ -#define LOAD_EARLY 0 - -/* Until I get an asyn driver I can use, I'll test by writing/reading - * directly to/from drvMaxv.cc's send_mess()/recv_mess() functions. - */ -#define USE_ASYN 0 - -#if USE_ASYN -#else -int cardNumber; - -/* send_mess: - * If name is an axis name, command is prefixed by single-axis command, such as "AX ". - * If name is null, command is sent without modification. - * return value: {OK = 0, ERROR = 1} - */ -%%extern int MAXV_send_mess(int cardNumber, char const *message, char *name); - -/* recv_mess: - * amount: -1 means flush and discard; other values specify number of messages to read - * - */ -%%extern int MAXV_recv_mess(int cardNumber, char *message, int amount); - -%%extern int MAXV_send_recv_mess(int cardNumber, char const *command, char *name, char *message, int amount); -%%extern int MAXV_getPositions(int card, epicsInt32 *positions, int nPositions); -#endif - - -/* Polling interval in seconds for waiting for motors to reach their targets */ -#define POLL_INTERVAL (1/5.) -#define READ_INTERVAL (1/60.) - -%%char axis_name[] = "XYZTUVRS"; -char stringOut[MAX_MESSAGE_STRING]; -char sbuf[MAX_MESSAGE_STRING]; -char stringIn[MAX_MESSAGE_STRING]; -char *asynPort; -char *pasynUser; /* This is really asynUser* */ -int status; -int i; -int j; -int k; -int n; -double delay; -int anyMoving; -int ncomplete; -int nextra; -int npoints; -double dtime; -double dpos; -double accelDist[MAX_AXES]; -double decelDist[MAX_AXES]; -%%double aDist; -%%double dDist; -double posActual; -double posTheory; -double expectedTime; -double initialPos[MAX_AXES]; -char macroBuf[NAME_LEN]; -char motorName[NAME_LEN]; -char *p; -char *tok_save; -int currPulse; -double frac; -double deltaV; -double v; -double vO; -int vOverride; -double lastPollTime; -int lastRealTimePoint; -int doPoll; -int initStatus; -int limitViolation; - -/* All PVs which will be accessed in local C functions need to have their index - * extracted with pvIndex() */ -int motorCurrentIndex[MAX_AXES]; -int epicsMotorDoneIndex[MAX_AXES]; - -/* Note, this should be time_t, but SNL doesn't understand that. This is - * the defininition in vxWorks. */ -unsigned long startTime; -%%epicsTimeStamp eStartTime; - -/* Define escaped C functions at end of file */ -%% static int writeOnly(SS_ID ssId, struct UserVar *pVar, char *command); -%% static int writeRead(SS_ID ssId, struct UserVar *pVar, char *command, char *reply); -%% static int getMotorPositions(SS_ID ssId, struct UserVar *pVar, double *pos, epicsInt32 *raw, double *dtime); -%% static int getMotorMoving(SS_ID ssId, struct UserVar *pVar, int movingMask); -%% static int getEpicsMotorMoving(SS_ID ssId, struct UserVar *pVar); -%% static int waitEpicsMotors(SS_ID ssId, struct UserVar *pVar); -%% static int buildTrajectory(SS_ID ssId, struct UserVar *pVar, double *realTimeTrajectory, -%% double *motorTrajectory, int epicsMotorDir, int moveMode, int npoints, double motorOffset, -%% double motorResolution, double motorVmin, int *position, int *velocity, int *acceleration, -%% double *accelDist, double *decelDist); -%% static int loadTrajectory(SS_ID ssId, struct UserVar *pVar, int simMode); -%% static int getStarted(SS_ID ssId, struct UserVar *pVar); -%% static int userToRaw(double user, double off, int dir, double res); -%% static double rawToUser(int raw, double off, int dir, double res); - -int position[MAX_AXES][MAX_ELEMENTS_P2]; -int velocity[MAX_AXES][MAX_ELEMENTS_P2]; -int acceleration[MAX_AXES][MAX_ELEMENTS_P2]; -/* if we're adding accel/decel points, we need a copy of realTimeTrajectory we can modify. */ -double realTimeTrajectoryAccelDecel[MAX_ELEMENTS_P2]; -double *rttraj; - -int motorStartRaw[MAX_AXES]; -double motorEnd[MAX_AXES]; -double dbuf[MAX_PULSES]; - -/* variables for constructing trajectory commands */ -int movingMask; -int waitingForTrigger; - -/* temporary variables to hold mav speed and acceleration for a motor */ -double vmax; -double amax; - -int card; -int signal; - -ss maxTrajectoryScan { - - /* Initialize things when first starting */ - state init { - when() { - cardNumber = -2; - initStatus = STATUS_UNDEFINED; - /* Force numAxes to be <= MAX_AXES */ - if (numAxes > MAX_AXES) numAxes = MAX_AXES; - for (i=0; istatus = pasynOctetSyncIO->connect(pVar->asynPort, 0, (asynUser **)&pVar->pasynUser, NULL); - if (status != 0) { - printf("trajectoryScan error in pasynOctetSyncIO->connect\n"); - printf(" status=%d, port=%s\n", status, asynPort); - } -#endif - for (j=0; j=1)) { - /* If nelements changes, then change endPulses to this value, - * since this is what the user normally wants. endPulses can be - * changed again after changing nelements if this is desired. */ - endPulses = nelements; - pvPut(endPulses); - } state monitor_inputs - - when(efTestAndClear(motorMDVSMon)) { - /* We don't use this. */ - } state monitor_inputs - - when (efTestAndClear(moveModeMon)) { - /* We don't support hybrid mode (yet?). */ - if (moveMode == MOVE_MODE_HYBRID) { - moveMode = moveModePrev; - pvPut(moveMode); - } else { - moveModePrev = moveMode; - } - buildStatus = STATUS_UNDEFINED; - pvPut(buildStatus); - } state monitor_inputs - } - - /* Build trajectory */ - state build { - when() { - /* Set busy flag while building */ - buildState = BUILD_STATE_BUSY; - pvPut(buildState); - buildStatus=STATUS_UNDEFINED; - pvPut(buildStatus); - epicsSnprintf(buildMessage, MSGSIZE, "Building..."); - pvPut(buildMessage); - - - buildStatus = STATUS_SUCCESS; /* presume we'll be successful */ - /* Initialize new trajectory */ - /* If time mode is TIME_MODE_TOTAL then construct timeTrajectory and post it */ - /* Note that timeTrajectory[i] is the time to go from motorTrajectory[i] to motorTrajectory[i+1] */ - if (timeMode == TIME_MODE_TOTAL) { - dtime = time_PV/(nelements-1); - for (i=0; irttraj, pVar->motorTrajectory[pVar->j], - %% pVar->epicsMotorDir[pVar->j], pVar->moveMode, pVar->npoints, - %% pVar->epicsMotorOff[pVar->j], pVar->epicsMotorMres[pVar->j], pVar->epicsMotorVMIN[pVar->j], - %% pVar->position[pVar->j], pVar->velocity[pVar->j], pVar->acceleration[pVar->j], - %% &aDist, &dDist); - %%pVar->accelDist[pVar->j] = aDist; - %%pVar->decelDist[pVar->j] = dDist; - } - } - - /* Compute expected time for trajectory. This includes timeScale factor. */ - if (addAccelDecel) { - /* Accel/decel segments are not scaled with timeScale factor. */ - expectedTime = realTimeTrajectoryAccelDecel[npoints+1]; - } else { - expectedTime = realTimeTrajectory[npoints-1]; - } - - /* Check trajectories against motor soft limits */ - limitViolation = 0; - for (j=0; j epicsMotorHLM[j]) || (posActual < epicsMotorLLM[j]); - if (limitViolation) { - epicsSnprintf(buildMessage, MSGSIZE, "Limit: m%d at pt. %d (%f)", j+1, k+1, posActual); - } - if (velocity[j][k]*epicsMotorMres[j] > vmax) { - limitViolation |= 1; - epicsSnprintf(buildMessage, MSGSIZE, "V limit: m%d at pt. %d (%f)", j+1, k+1, - velocity[j][k]*epicsMotorMres[j]); - } - if (fabs(acceleration[j][k]*epicsMotorMres[j]) > amax) { - limitViolation |= 1; - epicsSnprintf(buildMessage, MSGSIZE, "A limit: m%d at pt. %d (%f)", j+1, k+1, - acceleration[j][k]*epicsMotorMres[j]); - } - if (fabs(velocity[j][k]) > motorMVA[j]) { - motorMVA[j] = velocity[j][k]; - motorMVE[j] = k; - } - if (fabs(acceleration[j][k]) > motorMAA[j]) { - motorMAA[j] = acceleration[j][k]; - motorMAE[j] = k; - } - } - motorMVA[j] *= epicsMotorMres[j]; - motorMAA[j] *= epicsMotorMres[j]; - pvPut(motorMVA[j]); - pvPut(motorMAA[j]); - pvPut(motorMVE[j]); - pvPut(motorMAE[j]); - } - } - - if (limitViolation) { - buildStatus = STATUS_FAILURE; - } - - /* Post start positions. For relative scans, positions will be recalculated at exec time. */ - for (j=0; jmotorCurrent, pVar->motorCurrentRaw, &(pVar->dtime)); - for (j=0; jsimMode); - } -#endif - - /* Set status and message string */ - - /* Clear busy flag, post status */ - buildState = BUILD_STATE_DONE; - pvPut(buildState); - pvPut(buildStatus); - pvPut(buildMessage); - /* Clear build command, post. This is a "busy" record, don't want - * to do this until build is complete. */ - build=0; - pvPut(build); - if (buildStatus == STATUS_SUCCESS) { - epicsSnprintf(buildMessage, MSGSIZE, "Done"); - pvPut(buildMessage); - } - } state monitor_inputs - } - - - state execute { - when () { - /* Set busy flag */ - execState = EXECUTE_STATE_MOVE_START; - pvPut(execState); - /* Set status to INVALID */ - execStatus = STATUS_UNDEFINED; - pvPut(execStatus); - /* Erase the readback and error arrays */ - for (j=0; jsimMode); - } -#else - %%loadTrajectory(ssId, pVar, pVar->simMode); -#endif - - %%getMotorPositions(ssId, pVar, pVar->motorStart, pVar->motorStartRaw, &(pVar->dtime)); - n = sprintf(stringOut, "AM;"); /* Axis multitasking mode */ - for (j=0; jstringOut); - - n = sprintf(stringOut, "AM;"); /* Axis multitasking mode */ - for (j=0; jstringOut); - - /* Get start time of execute */ - elapsedTime = 0.; - pvPut(elapsedTime); - startTime = time(0); - %%epicsTimeGetCurrent(&eStartTime); - execState = EXECUTE_STATE_EXECUTING; - pvPut(execState); - lastPollTime = -POLL_INTERVAL; - lastRealTimePoint = 0; - waitingForTrigger = ((inBitNum >= 0) && (inBitNum <= 15)); - for (j=0, movingMask = 0; jmotorCurrent, pVar->motorCurrentRaw, &(pVar->dtime)); - for (j=0; jmotorCurrent, pVar->motorCurrentRaw, &(pVar->dtime)); - for (j=0; jwaitingForTrigger = (getStarted(ssId, pVar) ? 0 : 1); - startTime = time(0); - %%epicsTimeGetCurrent(&eStartTime); - } - } - - if (!waitingForTrigger) { - /* Get the current motor positions, post them */ - %%getMotorPositions(ssId, pVar, pVar->motorCurrent, pVar->motorCurrentRaw, &(pVar->dtime)); - elapsedTime = dtime; - - doPoll = (dtime - lastPollTime) > POLL_INTERVAL; - if (doPoll) pvPut(elapsedTime); - for (j=0; j= 10) printf("wait_execute: motor %d: rb=%f, t=%f\n", - j, motorReadbacks[j][currPulse], motorError[j][currPulse]); - } - /*** compare current time, position with desired trajectory ***/ - /* bracket dtime in the interval [realTimeTrajectoryAccelDecel[i], realTimeTrajectoryAccelDecel[i+1]] */ - for (i=lastRealTimePoint; (i0.) && (dtime > realTimeTrajectoryAccelDecel[i]); i++); - i--; - if (i<0) i = 0; - if (doPoll && (i > 2) && (i < npoints-2) && (overrideFactor >= .01) && (currPulse < MAX_PULSES-1)) { - if (debugLevel >= 10) printf("wait_execute: time=%f, i=%d, realTimeTrajectoryAccelDecel[i]=%f\n", - dtime, i, realTimeTrajectoryAccelDecel[i]); - frac = (dtime - realTimeTrajectoryAccelDecel[i]) / (realTimeTrajectoryAccelDecel[i+1] - realTimeTrajectoryAccelDecel[i]); - posTheory = motorTrajectory[j][i] + frac * (motorTrajectory[j][i+1] - motorTrajectory[j][i]); - if (moveMode != MOVE_MODE_ABSOLUTE) { - posTheory += motorStart[j]; - } - dpos = motorCurrent[j] - posTheory; - if (debugLevel >= 4) printf("\n wait_execute: actual=%.2f, ideal=%.2f, err=%.2f\n", - motorCurrent[j], posTheory, dpos); - /* dp/dt */ - v = (motorReadbacks[j][currPulse] - motorReadbacks[j][currPulse-1]) / - (motorError[j][currPulse] - motorError[j][currPulse-1]); - /* change in speed needed to make up the position in a time equal to the length of the current - * segment */ - deltaV = dpos / (realTimeTrajectoryAccelDecel[i+1] - realTimeTrajectoryAccelDecel[i]); - vO = (1-(deltaV/v)*overrideFactor) * 100; - %%pVar->vOverride = NINT(pVar->vO); - if (vOverride<80) vOverride=80; - if (vOverride>120) vOverride=120; - if (debugLevel >= 10) printf(" wait_execute: v=%.2f, dV=%.2f, vOverride=%.2f (%d)\n", - v, deltaV, vO, vOverride); - /* legal range of vOverride is [0, 200] */ - sprintf(stringOut, "AM; VO[%d]=%d;", j+1, vOverride); - %%writeOnly(ssId, pVar, pVar->stringOut); - if (debugLevel >= 2) printf(", 'VO[%d]=%3d'", j+1, vOverride); - } - } - - } - ++currPulse; - lastRealTimePoint = i; - if (doPoll) { - lastPollTime = dtime; - %%pVar->anyMoving = getMotorMoving(ssId, pVar, pVar->movingMask); - if (anyMoving == 0) { - execState = EXECUTE_STATE_FLYBACK; - execStatus = STATUS_SUCCESS; - strcpy(execMessage, " "); - } - /* See if the elapsed time is more than twice expected, time out */ - if (difftime(time(0), startTime) > expectedTime*2.) { - execState = EXECUTE_STATE_FLYBACK; - execStatus = STATUS_TIMEOUT; - strcpy(execMessage, "Timeout"); - - for (j=0; jstringOut); - } - } - /* SHOULD PROBABLY WAIT FOR MOTORS TO DECELERATE TO A STOP BEFORE KILLING */ - /* kill selected axes and flush queues */ - sprintf(stringOut, "KS"); - for (j=0; jstringOut); - - %%waitEpicsMotors(ssId, pVar); /* wait until all motors are done */ - } - } - /* Check for errors while trajectories are in progress */ - } /* if (!waitingForTrigger) */ - } state wait_execute - - when (execState==EXECUTE_STATE_FLYBACK) { - if (debugLevel) printf("\nflyback. currPulse=%d\n", currPulse); - pvPut(elapsedTime); - pvPut(execState); - pvPut(execStatus); - pvPut(execMessage); - /* Get the current motor positions, post them */ - %%getMotorPositions(ssId, pVar, pVar->motorCurrent, pVar->motorCurrentRaw, &(pVar->dtime)); - for (j=0; jstringOut); - } - } - /* SHOULD PROBABLY WAIT FOR MOTORS TO DECELERATE TO A STOP BEFORE KILLING */ - /* kill selected axes and flush queues */ - sprintf(stringOut, "KS"); - for (j=0; jstringOut); - - execStatus = STATUS_ABORT; - pvPut(execStatus); - strcpy(execMessage, "Motion aborted"); - pvPut(execMessage); - pvPut(elapsedTime); - /* Clear abort command, post. This is a "busy" record, don't - * want to do this until abort command has been sent. */ - abort=0; - pvPut(abort); - } state monitorAbort - } -} - -/***********************************************************************************************************/ -/* C functions */ -%{ - -/* writeOnly sends a command to the MAX controller */ -static int writeOnly(SS_ID ssId, struct UserVar *pVar, char *command) -{ - asynStatus status=0; - int debug_out=0; -#if USE_ASYN - size_t nwrite; - char buffer[MAX_MESSAGE_STRING]; - - /* Copy command so we can add terminator */ - strncpy(buffer, command, MAX_MESSAGE_STRING-3); - strcat(buffer, "\r"); - if (pVar->simMode==0) { - status = pasynOctetSyncIO->write((asynUser *)pVar->pasynUser, buffer, - strlen(buffer), 1.0, &nwrite); - } -#else - if (pVar->simMode==0) { - status = (asynStatus) MAXV_send_mess(pVar->cardNumber, command, (char *) NULL); - } -#endif - if (pVar->execState==EXECUTE_STATE_EXECUTING) - debug_out = (pVar->debugLevel >= 7); - else - debug_out = (pVar->debugLevel >= 2); - if (debug_out) printf(" writeOnly:command='%s'\n", command); - return(status); -} - - -/* writeRead sends a command to the MAX controller and reads the response into - * the global character buffer, stringIn. - */ -static int writeRead(SS_ID ssId, struct UserVar *pVar, char *command, char *reply) -{ - asynStatus status; - char buffer[MAX_MESSAGE_STRING]; -#if USE_ASYN - size_t nwrite, nread; - int eomReason; -#endif - - strncpy(buffer, command, MAX_MESSAGE_STRING-3); - -#if USE_ASYN - strcat(buffer, "\r"); - /* Use 30 second timeout, some commands take a long time to reply */ - status = pasynOctetSyncIO->writeRead((asynUser *)pVar->pasynUser, buffer, - strlen(buffer), reply, MAX_MESSAGE_STRING, - 30.0, &nwrite, &nread, &eomReason); -#else - - /* status = (asynStatus) MAXV_send_mess(pVar->cardNumber, command, (char *) NULL); - * status |= (asynStatus) MAXV_recv_mess(pVar->cardNumber, reply, 1); - */ - status = MAXV_send_recv_mess(pVar->cardNumber, command, (char *) NULL, reply, 1); -#endif - if (pVar->debugLevel >= 2) { - printf(" writeRead:command='%s', reply='%s'\n", buffer, reply); - } - return(status); -} - - -/* getMotorPositions returns the positions of each motor */ -static int getMotorPositions(SS_ID ssId, struct UserVar *pVar, double *pos, epicsInt32 *rawP, double *dt) -{ - int j; - int dir; - epicsTimeStamp currtime; - - MAXV_getPositions(pVar->cardNumber, rawP, pVar->numAxes); - - epicsTimeGetCurrent(&currtime); - *dt = epicsTimeDiffInSeconds(&currtime, &eStartTime); - for (j=0; jnumAxes; j++) { - if (pVar->epicsMotorDir[j] == 0) dir=1; else dir=-1; - pos[j] = rawToUser(rawP[j], pVar->epicsMotorOff[j], dir, pVar->epicsMotorMres[j]); - } - - if (pVar->debugLevel >= 1) { - printf("\ndt=%6.3f, p=%7d", *dt, rawP[0]); - } - epicsThreadSleep(READ_INTERVAL); - return(0); -} - - -/* getMotorMoving returns 1 if any of the motors in movingMask are moving */ -static int getMotorMoving(SS_ID ssId, struct UserVar *pVar, int movingMask) -{ - int i, j, mask, moving; - - for (j=0; j<2; j++) { - mask = 1; - moving = 0; - /* Read the current status of all the axes */ - writeRead(ssId, pVar, "QI", pVar->stringIn); - - /* Parse the return string which is of the form - * MDNN,MDNN,PNLN,PNNN,PNLN,PNNN,PNNN,PNNN, - * The second character of each status word is 'D' (done) or 'N' (not done) - */ - - for (i=1; i<37; i+=5, mask<<=1) { - if (pVar->stringIn[i] == 'N') moving |= mask; - } - - pVar->stringIn[40] = '\0'; - if (pVar->debugLevel >= 7) { - printf("\ngetMotorMoving: reply = '%s', moving = %2x", pVar->stringIn, moving); - } - if (moving & movingMask) return(1); - } - return(0); -} - - -static int getStarted(SS_ID ssId, struct UserVar *pVar) { - int i, bits, mask; - char c; - - writeRead(ssId, pVar, "BX", pVar->stringIn); - for (i=0, bits=0; i<4; i++) { - bits <<= 4; - c = pVar->stringIn[i]; - /* convert hex character to number */ - if (isdigit((int)c)) { - c = c - '0'; - } else if (isxdigit((int)c)) { - if (islower((int)c)) { - c = (c - 'a') + 10; - } else { - c = (c - 'A') + 10; - } - } - bits |= c; - } - mask = 1 << (pVar->inBitNum); - if (pVar->debugLevel >= 5) - printf("\ngetStarted: reply='%s', bits=0x%x, mask=0x%x", pVar->stringIn, bits, mask); - return (bits & mask); -} - -/* getEpicsMotorMoving returns the EPICS moving status of each motor, packed into - * a single int. Bit 0 = motor 1, bit 1 = motor 2, etc. 0=not moving, 1=moving. - * If the entire int is 0 then no motors are moving */ -static int getEpicsMotorMoving(SS_ID ssId, struct UserVar *pVar) -{ - int j; - int result=0, mask=0x01; - - for (j=0; jnumAxes; j++) { - seq_pvGet(ssId, pVar->epicsMotorDoneIndex[j], 0); - if (pVar->epicsMotorDone[j] == 0) result |= mask; - mask = mask << 1; - } - return(result); -} - -/* waitEpicsMotors waits for all motors to stop moving using the EPICS motor - * records.. It reads and posts the motor positions during each loop. */ -static int waitEpicsMotors(SS_ID ssId, struct UserVar *pVar) -{ - int j; - - /* Logic is that we always want to post position motor positions - * after the end of move is detected. */ - while (getEpicsMotorMoving(ssId, pVar)) { - /* Get the current motor positions, post them */ - for (j=0; jnumAxes; j++) { - pVar->motorCurrent[j] = pVar->epicsMotorPos[j]; - seq_pvPut(ssId, pVar->motorCurrentIndex[j], 0); - } - if (pVar->debugLevel >= 1) printf("waitEpicsMotors: m1=%f\n", pVar->epicsMotorPos[0]); - epicsThreadSleep(POLL_INTERVAL); - } - for (j=0; jnumAxes; j++) { - pVar->motorCurrent[j] = pVar->epicsMotorPos[j]; - seq_pvPut(ssId, pVar->motorCurrentIndex[j], 0); - } - return(0); -} - -/* Calculate velocities and accelerations suitable for MAX variable velocity contouring commands. - * We're given x(t) in the form x[i], t[i]. We need to calculate v(x) and a(x) that will produce x(t). - */ -volatile int MAXv_traj_quantized = 1; -volatile int MAXv_traj_vmin = 0; - -double y2[MAX_ELEMENTS_P2], v_out[MAX_ELEMENTS_P2], a_out[MAX_ELEMENTS_P2], calcMotorTrajectory[MAX_ELEMENTS_P2]; -static int buildTrajectory(SS_ID ssId, struct UserVar *pVar, double *realTimeTrajectory, - double *motorTrajectory, int epicsMotorDir, int moveMode, int npoints, double motorOffset, - double motorResolution, double motorVmin, int *position, int *velocity, int *acceleration, - double *accelDist, double *decelDist) -{ - - double dp, dt, v_ideal, v_lin, accel_p, accel_v, thisTime; - double x0; - int i, dir; - - *accelDist = 0; /* init; these are used only if pVar->addAccelDecel */ - *decelDist = 0; - - if (pVar->addAccelDecel) { - dp = motorTrajectory[1] - motorTrajectory[0]; - dt = realTimeTrajectory[2] - realTimeTrajectory[1]; - *accelDist = (dp/dt * pVar->accel) / 2; - /* Average speed over last trajectory segment is the speed from which we want to decelerate to 0 speed. */ - dp = motorTrajectory[npoints-1] - motorTrajectory[npoints-2]; - dt = realTimeTrajectory[npoints] - realTimeTrajectory[npoints-1]; - /* Note that accel_time == decel_time, but the distances are different. */ - *decelDist = (dp/dt * pVar->accel) / 2; - - /* Shift motorTrajectory forward by one element; prepend accel, append decel; restore before returning. - * realTimeTrajectory was modified for us by caller. */ - for (i=npoints; i>0; i--) { - motorTrajectory[i] = motorTrajectory[i-1]; - } - motorTrajectory[0] = motorTrajectory[1] - *accelDist; - motorTrajectory[npoints+1] = motorTrajectory[npoints] + *decelDist; - npoints += 2; - } - - calcMotorTrajectory[0] = motorTrajectory[0]; - v_out[0] = 0; - if (pVar->debugLevel >= 7) { - printf("\n###:%8s %8s %7s %8s %8s %8s %8s %8s\n", - "pos", "calcPos", "dp", "t", "v_ideal", "accel_p", "accel_v", "accel_s"); - } - for (i=1; idebugLevel >= 7) { - printf("%3d:%8.2f %8.2f %7.2f %8.3f %8.3f %8.3f %8.3f %8.3f\n", - i, motorTrajectory[i-1], calcMotorTrajectory[i-1], dp, realTimeTrajectory[i-1], v_ideal, accel_p, accel_v, (y2[i-1]+y2[i])/2); - } - if (MAXv_traj_quantized) { - /* Motor acceleration is quantized. Take effect into account by assuming nearest achievable acceleration. */ - a_out[i-1] = motorResolution * NINT(a_out[i-1]/motorResolution); - } - v_out[i] = v_out[i-1] + a_out[i-1]*dt; - if (MAXv_traj_quantized) { - /* Motor speed is quantized. Take effect into account by calculating nearest achievable speed. */ - v_out[i] = motorResolution * NINT(v_out[i]/motorResolution); - } - if (MAXv_traj_vmin) { - /* Motor speed has lower limit. Take effect into account by calculating nearest achievable speed. */ - if (v_out[i] < motorVmin) { - double vsav = v_out[i]; - v_out[i] = (v_out[i] < motorVmin/2) ? 0. : motorVmin; - printf("v < vmin; %f corrected to %f\n", vsav, v_out[i]); - } - } - calcMotorTrajectory[i] = calcMotorTrajectory[i-1] + v_out[i-1]*dt + .5 * a_out[i-1]*dt*dt; - } - a_out[npoints-1] = a_out[npoints-2]; - - if (pVar->debugLevel >= 7) { - printf("buildTrajectory:\n"); - printf("%10s %10s %10s %10s %10s\n", "realTime", "motorTraj", "calcTraj", "v_out", "a_out"); - for (i=0; idebugLevel >= 1) { - printf("motor resolution %f\n", motorResolution); - printf("%10s %10s %10s %10s %10s\n", "time", "position", "calcpos", "velocity", "acceleration"); - } - for (i=0; i0) { - x0 = position[i-1] + velocity[i-1]*dt + .5 * acceleration[i]*dt*dt; - } else { - x0 = .5 * acceleration[i]*dt*dt; - } - if (pVar->debugLevel >= 1) printf("%10.2f %10d %10d %10d %10d\n", thisTime, position[i], NINT(x0), velocity[i], acceleration[i]); - } - - if (pVar->addAccelDecel) { - /* Shift motorTrajectory backward by one element, and clear decel element. */ - npoints -= 2; - for (i=0; istartPulses; - endPulses = pVar->endPulses; - npoints = pVar->npoints; - - if (pVar->addAccelDecel) { - /* We assume the arrays pVar->position, pVar->acceleration, pVar->velocity, and pVar->realTimeTrajectoryAccelDecel - * have had accel/decel trajectory points added. */ - startPulses++; - endPulses++; - npoints+=2; - } - - sprintf(stringOut, "AM;"); /* multitasking mode, flush queue */ - writeOnly(ssId, pVar, stringOut); - - /* digital I/O commands */ - if ((pVar->outBitNum >= 0) && (pVar->outBitNum <= 15)) { - onMask = 1 << (pVar->outBitNum); - offMask = 0; - outMask = 1 << (pVar->outBitNum); - /*sprintf(stringOut, "IO%d,1;", pVar->outBitNum);*/ /* set bit as output */ - sprintf(stringOut, "BD%04x;", outMask); /* set bit as output */ - writeOnly(ssId, pVar, stringOut); - sprintf(stringOut, "BL%d;", pVar->outBitNum); /* set output bit low */ - writeOnly(ssId, pVar, stringOut); - } - - if ((pVar->inBitNum >= 0) && (pVar->inBitNum <= 15)) { - sprintf(stringOut, "IO%d,0;", pVar->inBitNum); /* set bit as input */ - writeOnly(ssId, pVar, stringOut); - } - - /* trajectory commands */ - absRel = 'A'; - /*absRel = (moveMode == MOVE_MODE_ABSOLUTE) ? 'A' : 'R';*/ - - /* clear motor queue */ - sprintf(stringOut, "AM; SI"); - for (j=0; jmoveAxis[j]) strcat(stringOut, "1"); - if (j<(MAX_AXES-1)) strcat(stringOut, ","); - } - strcat(stringOut, ";"); - writeOnly(ssId, pVar, stringOut); - - /* Get update rate */ - sprintf(stringOut, "AX; #UR?;"); - writeRead(ssId, pVar, stringOut, stringOut); - if (pVar->debugLevel > 0) printf("Update rate ='%s'\n", stringOut); - currUpdateRate = atol(stringOut); - - epicsTimeGetCurrent(&eStartTime); /* not actually the start time, getMotorPositions just needs a value */ - getMotorPositions(ssId, pVar, pVar->motorCurrent, pVar->motorCurrentRaw, &(pVar->dtime)); - -#if 0 - /* It's a bad idea to change updateFreq at run time. Better to set it at init time. */ - /* Set update rate. */ - i = 1024 * pVar->updateFreq; - if (i != currUpdateRate) { - sprintf(stringOut, "AX; #UR%d;", i); - writeOnly(ssId, pVar, stringOut); - - /* reload motor positions to what they were before the #UR command */ - /* Note that LP sets both motor and encoder positions to the same value */ - n = sprintf(stringOut, "AM; LP"); - for (j=0; jmotorCurrentRaw[j]); - if (j<(MAX_AXES-1)) n += sprintf(&(stringOut[n]), ","); - } - strcat(stringOut, ";"); - writeOnly(ssId, pVar, stringOut); - } -#endif - - /* we may need current raw positions to mock up relative mode */ - epicsTimeGetCurrent(&eStartTime); /* not actually the start time, getMotorPositions just needs eStartTime to have a value. */ - getMotorPositions(ssId, pVar, pVar->motorCurrent, pVar->motorCurrentRaw, &(pVar->dtime)); - - for (j=0, firstTask=1; jmoveAxis[j]) { - if (pVar->epicsMotorDir[j] == 0) dir=1; else dir=-1; - - addForRelMove = pVar->motorCurrent[j]*dir / pVar->epicsMotorMres[j]; - if (pVar->debugLevel > 2) printf("addForRelMove=%f\n", addForRelMove); - - /* output bit */ - if (firstTask && ((pVar->outBitNum >= 0) && (pVar->outBitNum <= 15))) { - /* Tell controller to output a pulse at the beginning of every trajectory segment. */ - sprintf(stringOut, "AM; VIO[%d]%04x,%04x,%04x;", j+1, onMask, offMask, outMask); - writeOnly(ssId, pVar, stringOut); - pulsesEnabled = 1; - } else { - /* Tell controller NOT to output a pulse at the beginning of every trajectory segment. */ - sprintf(stringOut, "AM; VIO[%d]0,0,0;", j+1); - writeOnly(ssId, pVar, stringOut); - pulsesEnabled = 0; - } - /* done flag and interrupt */ - sprintf(stringOut, "AM; VID[%d]1;", j+1); - writeOnly(ssId, pVar, stringOut); - - /* Don't start until I tell you to start */ - sprintf(stringOut, "AM; VH[%d]0;", j+1); - writeOnly(ssId, pVar, stringOut); - - /* Arm the trajectories to start on an input trigger bit. - * If no input trigger bit, then start now. - */ - if ((pVar->inBitNum >= 0) && (pVar->inBitNum <= 15)) { - /* Wait for input bit to go high before processing any more commands. */ - sprintf(stringOut, "A%c; SW%d;", axis_name[j], pVar->inBitNum); - writeOnly(ssId, pVar, stringOut); - } - - for (i=0; iacceleration[j][i] > 0) { - segment_accel = pVar->acceleration[j][i]; - segment_decel = pVar->acceleration[j][i]; - } else { - segment_accel = -(pVar->acceleration[j][i]); - segment_decel = -(pVar->acceleration[j][i]); - } - if (segment_accel < 1) segment_accel = 1; - if (segment_accel > 8000000) segment_accel = 8000000; - if (segment_decel < 1) segment_decel = 1; - if (segment_decel > 8000000) segment_decel = 8000000; - - segment_v_start = (i==0) ? pVar->velocity[j][0] : pVar->velocity[j][i-1]; - segment_v_end = pVar->velocity[j][i]; - - /* If velocity goes through zero during this segment, we'll need to split the segment. */ - do_split = (segment_v_start>0) != (segment_v_end>0); - do_split = do_split && (abs(segment_v_start)>2) && (abs(segment_v_end)>2); - do_split = do_split && (i>0); - if (do_split) { - /* time from the beginning of the trajectory segment at which the velocity reaches zero.*/ - t_v0 = (double)(-segment_v_start) / pVar->acceleration[j][i]; - - if ((t_v0 < .005) || (((pVar->realTimeTrajectoryAccelDecel[i] - pVar->realTimeTrajectoryAccelDecel[i-1]) - t_v0) < .005)) { - /* Don't split very near either end of segment. */ - if (pVar->debugLevel > 0) printf("declined to split segment at t=%f\n", t_v0); - do_split = 0; - } else { - v1 = 0; - p1_double = pVar->position[j][i-1] + segment_v_start*t_v0 + - 0.5 * pVar->acceleration[j][i]*t_v0*t_v0; - p1 = NINT(p1_double); /* Note that this already has addForRelMove added to it. */ - if (pVar->debugLevel > 0) printf("split segment at t=%f, x=%d\n", t_v0, p1); - } - } - - segment_v_start = abs(segment_v_start); - segment_v_end = abs(segment_v_end); - - if (segment_v_start < 1) segment_v_start = 1; - if (segment_v_start > 4194303) segment_v_start = 4194303; - if (segment_v_end < 0) segment_v_end = 0; - if (segment_v_end > 4194303) segment_v_end = 4194303; - - if (pVar->moveMode != MOVE_MODE_ABSOLUTE) { - p1_double = pVar->position[j][i]; - pVar->position[j][i] = NINT(p1_double + addForRelMove); - } - - if (do_split) { - if (firstTask && ((pVar->outBitNum >= 0) && (pVar->outBitNum <= 15))) { - /* Disable output pulses */ - if (pulsesEnabled) { - sprintf(stringOut, "AM; VIO[%d]0,0,0;", j+1); - writeOnly(ssId, pVar, stringOut); - pulsesEnabled = 0; - } - } - /* we have to split this segment where velocity goes through zero. */ - n = sprintf(stringOut, "AM; VA[%d]%d;", j+1, segment_accel); - n += sprintf(&stringOut[n], "VV[%d]%d,%d;", j+1, segment_v_start, v1); - n += sprintf(&stringOut[n], "VP[%d]%c", j+1, absRel); - for (k=0; koutBitNum >= 0) && (pVar->outBitNum <= 15))) { - /* Enable output pulses */ - if (!pulsesEnabled) { - sprintf(stringOut, "AM; VIO[%d]%04x,%04x,%04x;", j+1, onMask, offMask, outMask); - writeOnly(ssId, pVar, stringOut); - pulsesEnabled = 1; - } - } - n = sprintf(stringOut, "AM; VA[%d]%d;", j+1, segment_accel); - if (i < (pVar->npoints)-1) { - n += sprintf(&stringOut[n], "VV[%d]%d;", j+1, segment_v_end); - } else { - n += sprintf(&stringOut[n], "VV[%d]%d,%d;", j+1, 1, segment_v_end); - } - n += sprintf(&stringOut[n], "VP[%d]%c", j+1, absRel); - for (k=0; kposition[j][i]); - for (k=j+1; koutBitNum >= 0) && (pVar->outBitNum <= 15))) { - if (i >= startPulses && i <= endPulses) { - /* Enable output pulses */ - if (!pulsesEnabled) { - sprintf(stringOut, "AM; VIO[%d]%04x,%04x,%04x;", j+1, onMask, offMask, outMask); - writeOnly(ssId, pVar, stringOut); - pulsesEnabled = 1; - } - } else { - if (pulsesEnabled) { - /* Disable output pulses */ - sprintf(stringOut, "AM; VIO[%d]0,0,0;", j+1); - writeOnly(ssId, pVar, stringOut); - pulsesEnabled = 0; - } - } - } - - n = sprintf(stringOut, "AM; VA[%d]%d;", j+1, segment_accel); - if (i < (pVar->npoints)-1) { - n += sprintf(&stringOut[n], "VV[%d]%d;", j+1, segment_v_end); - } else { - n += sprintf(&stringOut[n], "VV[%d]%d,%d;", j+1, segment_v_start, segment_v_end); - } - n += sprintf(&stringOut[n], "VP[%d]%c", j+1, absRel); - for (k=0; kposition[j][i]); - for (k=j+1; k - -#include "motorRecord.h" -#include "devOmsCom.h" -#include "epicsExport.h" - -extern int MAXv_num_cards; -extern struct driver_table MAXv_access; - -/* ----------------Create the dsets for devMAXv----------------- */ -static long MAXv_init(int); -static long MAXv_init_record(void *); -static long MAXv_start_trans(struct motorRecord *); -static RTN_STATUS MAXv_end_trans(struct motorRecord *); - -struct motor_dset devMAXv = -{ - {8, NULL, (DEVSUPFUN) MAXv_init, (DEVSUPFUN) MAXv_init_record, NULL}, - motor_update_values, - MAXv_start_trans, - oms_build_trans, - MAXv_end_trans -}; - -extern "C" {epicsExportAddress(dset,devMAXv);} - -static struct board_stat **MAXv_cards; -static const char errmsg[] = {"\n\n!!!ERROR!!! - Oms MAXv driver uninitialized.\n"}; - -static long MAXv_init(int after) -{ - if (*(MAXv_access.init_indicator) == NO) - { - errlogSevPrintf(errlogMinor, "%s", errmsg); - return(ERROR); - } - else - return(motor_init_com(after, MAXv_num_cards, &MAXv_access, &MAXv_cards)); -} - -static long MAXv_init_record(void *arg) -{ - struct motorRecord *mr = (struct motorRecord *) arg; - return(motor_init_record_com(mr, MAXv_num_cards, &MAXv_access, MAXv_cards)); -} - -static long MAXv_start_trans(struct motorRecord *mr) -{ - struct motor_trans *trans; - long rtnval; - - rtnval = motor_start_trans_com(mr, MAXv_cards); - /* Initialize a STOP_AXIS command termination string pointer. */ - trans = (struct motor_trans *) mr->dpvt; - trans->motor_call.termstring = " ID"; - return(rtnval); -} - -static RTN_STATUS MAXv_end_trans(struct motorRecord *mr) -{ - if (*(MAXv_access.init_indicator) == NO) - { - errlogSevPrintf(errlogMinor, "%s", errmsg); - return(ERROR); - } - else - return(motor_end_trans_com(mr, &MAXv_access)); -} - diff --git a/motorApp/OmsSrc/devOms.cc b/motorApp/OmsSrc/devOms.cc deleted file mode 100644 index 018f58e8..00000000 --- a/motorApp/OmsSrc/devOms.cc +++ /dev/null @@ -1,125 +0,0 @@ -/* -FILENAME... devOms.cc -USAGE... Device level support for OMS VME8 and VME44 models. - - -*/ - -/* - * Original Author: Jim Kowalkowski - * Date: 01/18/93 - * Current Author: Ron Sluiter - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - * .01 01-18-93 jbk initialized - * ... - * .03 03-19-96 tmm v1.10: modified encoder-ratio calculation - * .04 11-26-96 jps allow for bumpless-reboot on position - * .04a 02-19-97 tmm fixed for EPICS 3.13 - * .05 06-16-03 rls Converted to R3.14.x. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "motorRecord.h" -#include "motor.h" -#include "drvOms.h" -#include "devOmsCom.h" - -#include "epicsExport.h" - - -extern int oms44_num_cards; -extern struct driver_table oms_access; - -/* ----------------Create the dsets for devOMS----------------- */ -static long oms_init(int); -static long oms_init_record(void *); -static long oms_start_trans(struct motorRecord *); -static RTN_STATUS oms_end_trans(struct motorRecord *); - -struct motor_dset devOMS = -{ - {8, NULL, (DEVSUPFUN) oms_init, (DEVSUPFUN) oms_init_record, NULL}, - motor_update_values, - oms_start_trans, - oms_build_trans, - oms_end_trans -}; - -extern "C" {epicsExportAddress(dset,devOMS);} - -static struct board_stat **oms_cards; -static const char errmsg[] = {"\n\n!!!ERROR!!! - Oms driver uninitialized.\n"}; - -static long oms_init(int after) -{ - if (*(oms_access.init_indicator) == NO) - { - errlogSevPrintf(errlogMinor, "%s", errmsg); - return(ERROR); - } - else - return(motor_init_com(after, oms44_num_cards, &oms_access, &oms_cards)); -} - -static long oms_init_record(void *arg) -{ - struct motorRecord *mr = (struct motorRecord *) arg; - return(motor_init_record_com(mr, oms44_num_cards, &oms_access, oms_cards)); -} - -static long oms_start_trans(struct motorRecord *mr) -{ - struct motor_trans *trans; - long rtnval; - - rtnval = motor_start_trans_com(mr, oms_cards); - /* Initialize a STOP_AXIS command termination string pointer. */ - trans = (struct motor_trans *) mr->dpvt; - trans->motor_call.termstring = " ID"; - return(rtnval); -} - -static RTN_STATUS oms_end_trans(struct motorRecord *mr) -{ - if (*(oms_access.init_indicator) == NO) - { - errlogSevPrintf(errlogMinor, "%s", errmsg); - return(ERROR); - } - else - return(motor_end_trans_com(mr, &oms_access)); -} - diff --git a/motorApp/OmsSrc/devOms.dbd b/motorApp/OmsSrc/devOms.dbd deleted file mode 100644 index 569232b4..00000000 --- a/motorApp/OmsSrc/devOms.dbd +++ /dev/null @@ -1,22 +0,0 @@ -# Oregon Micro Systems VME8/44 driver support. -device(motor,VME_IO,devOMS,"OMS VME8/44") -driver(drvOms) - -# Oregon Micro Systems VME58 driver support. -device(motor,VME_IO,devOms58,"OMS VME58") -driver(drvOms58) -registrar(oms58Registrar) - -# Oregon Micro Systems MAXv driver support. -device(motor,VME_IO,devMAXv,"OMS MAXv") -driver(drvMAXv) -registrar(OmsMAXvRegister) - -# Oregon Micro Systems PC68/78 RS-232 serial driver support. -device(motor,VME_IO,devOmsPC68,"OMS PC68/78") -driver(drvOmsPC68) -registrar(OmsPC68Register) -variable(drvOmsPC68debug) - -registrar(MAX_trajectoryScanRegistrar) - diff --git a/motorApp/OmsSrc/devOms58.cc b/motorApp/OmsSrc/devOms58.cc deleted file mode 100644 index d788a068..00000000 --- a/motorApp/OmsSrc/devOms58.cc +++ /dev/null @@ -1,125 +0,0 @@ -/* -FILENAME... devOms58.c -USAGE... Motor record device level support for OMS VME58. - -*/ - -/* - * Original Author: Jim Kowalkowski - * Current Author: Joe Sullivan - * Date: 11/14/94 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - * .01 01-18-93 jbk initialized - * .02 11-14-94 jps copy devOMS.c and modify to point to vme58 driver - * .03 03-19-96 tmm v1.10: modified encoder-ratio calculation - * .04 06-20-96 jps allow for bumpless-reboot on position - * .04a 02-19-97 tmm fixed for EPICS 3.13 - * .05 06-16-03 rls Converted to R3.14.x. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "motorRecord.h" -#include "motor.h" -#include "drvOms58.h" -#include "devOmsCom.h" - -#include "epicsExport.h" - -extern int oms58_num_cards; -extern struct driver_table oms58_access; - -/* ----------------Create the dsets for devOMS----------------- */ -static long oms_init(int); -static long oms_init_record(void *); -static long oms_start_trans(struct motorRecord *); -static RTN_STATUS oms_end_trans(struct motorRecord *); - -struct motor_dset devOms58 = -{ - {8, NULL, (DEVSUPFUN) oms_init, (DEVSUPFUN) oms_init_record, NULL}, - motor_update_values, - oms_start_trans, - oms_build_trans, - oms_end_trans -}; - -extern "C" {epicsExportAddress(dset,devOms58);} - -static struct board_stat **oms_cards; -static const char errmsg[] = {"\n\n!!!ERROR!!! - Oms58 driver uninitialized.\n"}; - -static long oms_init(int after) -{ - if (*(oms58_access.init_indicator) == NO) - { - errlogSevPrintf(errlogMinor, "%s", errmsg); - return(ERROR); - } - else - return(motor_init_com(after, oms58_num_cards, &oms58_access, &oms_cards)); -} - -static long oms_init_record(void *arg) -{ - struct motorRecord *mr = (struct motorRecord *) arg; - return(motor_init_record_com(mr, oms58_num_cards, &oms58_access, oms_cards)); -} - -static long oms_start_trans(struct motorRecord *mr) -{ - struct motor_trans *trans; - long rtnval; - - rtnval = motor_start_trans_com(mr, oms_cards); - /* Initialize a STOP_AXIS command termination string pointer. */ - trans = (struct motor_trans *) mr->dpvt; - trans->motor_call.termstring = " ID"; - return(rtnval); -} - -static RTN_STATUS oms_end_trans(struct motorRecord *mr) -{ - if (*(oms58_access.init_indicator) == NO) - { - errlogSevPrintf(errlogMinor, "%s", errmsg); - return(ERROR); - } - else - return(motor_end_trans_com(mr, &oms58_access)); -} - - - diff --git a/motorApp/OmsSrc/devOmsCom.cc b/motorApp/OmsSrc/devOmsCom.cc deleted file mode 100644 index 524d56da..00000000 --- a/motorApp/OmsSrc/devOmsCom.cc +++ /dev/null @@ -1,543 +0,0 @@ -/* -FILENAME... devOmsCom.cc -USAGE... Data and functions common to all OMS device level support. - -*/ - -/* - * Original Author: Jim Kowalkowski - * Previous Author: Joe Sullivan - * Date: 11/14/94 - * Current Author: Ron Sluiter - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - * .01 01-18-93 jbk initialized - * .02 11-14-94 jps copy devOMS.c and modify to point to vme58 driver - * .03 03-19-96 tmm v1.10: modified encoder-ratio calculation - * .04 06-20-96 jps allow for bumpless-reboot on position - * .04a 02-19-97 tmm fixed for EPICS 3.13 - * .05 05-14-01 rls Support for jog velocity and acceleration commands. - * Added "CA" to home and jog commands so JVEL does not - * see done flag from previous operation. - * .06 03-27-02 rls Eliminated RES. All input positions, velocities and - * accelerations are in motor steps. - * .07 07-05-02 rls Work around for OMS bug that ignores MR+/-1. - * Use OMS UU command to support reference is always in - * motor steps. - * .08 06-04-03 rls Convert to R3.14.x. - * .09 06-04-03 rls extended device directive support PREM and POST. - * .10 06-16-03 rls Converted to R3.14.x. - * .11 06-16-04 rls Terminate "LP" command with ";" to prevent MAXv stale data. - * .12 08-27-04 rls Terminate "JG" command with ";" to prevent MAXv stale data. - * .13 03-21-05 rls OSI - built for solaris and linux hosts. - * .14 03-23-05 rls restrict acceleration to valid values. - * .15 08-18-06 rls Output "slew <= base" error message only one time. - * .16 02-16-07 rls Bug fix for overwriting PID parameter fields during - * normalization calculation. - * .17 05-14-08 rls Fixed stop acceleration calculation. - * .18 05-14-08 rls For MAXv, restore slew acceleration after STOP command. - * .19 06-11-08 rls For MAXv, fix error on ER command; replace UU1.0 with UF. - * .20 07-24-08 rls For MAXv, normalize PID values based on 32,767 maximum. - * .21 03-01-10 rls Some MR commands still ignored; change fraction to .9. - * .22 11-10-10 rls Error check for valid acceleration rate on STOP command. - * .23 10-26-11 rls Use MAXv motor type to support MRES and ERES with - * different polarity (signs). - * .24 11-29-12 rls Terminate UU command argument with a ';' character. - * Fixes "Command error" with MAXv ver:1.41 firmware. - * .25 03-13-15 rls Bug fix for incorrect deceleration calculation at end of - * JOG command. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "motorRecord.h" -#include "motor.h" -#include "motordevCom.h" -#include "devOmsCom.h" -#include "drvMAXv.h" - - -/* WARNING... The following is a COPY of a motorRecord.cc definition. - If device support uses MIP definitions, then they should be moved - from motorRecord.cc to motor.h. In addition, for device support to - fully use MIP (e.g. correct accleration on STOP command), device - support needs record support to implement previous MIP (PMIP). */ -#define MIP_JOG_STOP 0x2000 /* Stop jogging. */ - -/* -Command set used by record support. WARNING! this must match "motor_cmnd" in -motor.h -*/ - -struct motor_table -{ - msg_types type; - const char *command; - int num_parms; -}; - -struct motor_table const oms_table[] = -{ - {MOTION, " MA", 1}, /* MOVE_ABS */ - {MOTION, " MR", 1}, /* MOVE_REL */ - {MOTION, " CA HM", 1}, /* HOME_FOR */ - {MOTION, " CA HR", 1}, /* HOME_REV */ - {IMMEDIATE, " LP", 1}, /* LOAD_POS */ - {IMMEDIATE, " VB", 1}, /* SET_VEL_BASE */ - {IMMEDIATE, " VL", 1}, /* SET_VELO */ - {IMMEDIATE, " AC", 1}, /* SET_ACCEL */ - {IMMEDIATE, " GD", 0}, /* jps: from GO to GD */ - {IMMEDIATE, " ER", 2}, /* SET_ENC_RATIO */ - {INFO, " ", 0}, /* GET_INFO */ - {MOVE_TERM, " ST", 0}, /* STOP_AXIS */ - {VELOCITY, " CA JG", 1}, /* JOG */ - {IMMEDIATE," KP", 1}, /* SET_PGAIN */ - {IMMEDIATE," KI", 1}, /* SET_IGAIN */ - {IMMEDIATE," KD", 1}, /* SET_DGAIN */ - {IMMEDIATE," HN", 0}, /* ENABLE_TORQUE */ - {IMMEDIATE," HF", 0}, /* DISABL_TORQUE */ - {IMMEDIATE, "", 0}, /* PRIMITIVE */ - {IMMEDIATE, "", 0}, /* SET_HIGH_LIMIT */ - {IMMEDIATE, "", 0}, /* SET_LOW_LIMIT */ - {VELOCITY, " JG", 1}, /* JOG_VELOCITY */ -}; - - -/* -FUNCTION... long oms_build_trans(motor_cmnd, double *, struct motorRecord *) -USAGE... Add a part to the transaction. - -INPUT... command - index into oms_table[]. - *parms - one or more input parameters; determined by - "num_parms" in oms_table. - *mr - motor record pointer. -LOGIC... - Initialize pointers; return value to OK. - Set highest command type priority. - IF transaction is NOT initialized (i.e., state != BUILD_STATE) - ERROR RETURN. - ENDIF - - IF input command is a PRIMITIVE command, AND, the INIT field is not empty. - IF input command is a "device directive". - Find terminating '@'. - IF valid "device directive" (i.e, directive bracketed by '@'s). - IF "Driver Power Monitoring ON" directive. - Flush response buffer. - Read motor controller's GPIO configuration. - IF bit corresponding to current axis is configured as an - output bit. - Set "Driver Power Monitoring" indicator true. - ELSE - Output ERROR message. - ENDIF - ENDIF - Strip device directive and copy rest of INIT field to local buffer. - ELSE - Copy INIT field to local buffer. - ENDIF - ELSE - Copy INIT field to local buffer. - ENDIF - ELSE - IF input command is set HIGH or LOW travel limit. - Null command. Set transaction state to IDLE. - ELSE - IF input command is Proportional Gain, AND, gain < valid minimum. - Set the gain and the PCOF field to the minimum. - Set return indicator to ERROR. - ELSE IF input command is STOP_AXIS. - NOTE: This logic is here as a workaround for an OMS firmware - error. When a STOP command was issued during the target move, - the backlash acceleration would go into effect. - - Prefix command with ACCL field acceleration. - ENDIF - IF command type is MOTION or VELOCITY. - Process PREM and POST fields. - ENDIF - IF Overtravel status indicator true, AND, input command is a MOVE. - NOTE: This logic is here as a workaround for the "Moving off a - limit switch" OMS firmware error. - - IF incremental distance to target position is positive. - Set OMS controller "direction logic" positive. - ELSE - Set OMS controller "direction logic" negative. - ENDIF - ENDIF - Copy input command into output message. - Copy input command parameters into output message. - ENDIF - ENDIF -*/ - -RTN_STATUS oms_build_trans(motor_cmnd command, double *parms, struct motorRecord *mr) -{ - struct motor_trans *trans = (struct motor_trans *) mr->dpvt; - struct mess_node *motor_call; - struct controller *brdptr; - struct MAXvController *MAXvCntrl = NULL; - char buffer[40]; - msg_types cmnd_type; - RTN_STATUS rtnind; - static bool invalid_velmsg_latch = false; - bool MAXv = false; - int card, signal; - long valid_acc; - - rtnind = OK; - motor_call = &trans->motor_call; - card = motor_call->card; - signal = motor_call->signal; - - cmnd_type = oms_table[command].type; - if (cmnd_type > motor_call->type) - motor_call->type = cmnd_type; - - /* concatenate onto the dpvt message field */ - if (trans->state != BUILD_STATE) - return(rtnind = ERROR); - - if ((brdptr = (*trans->tabptr->card_array)[card]) == NULL) /* Test for disabled board. */ - return(rtnind = ERROR); - - if (strncmp(brdptr->ident, "MAXv", 4) == 0) - { - MAXv = true; - MAXvCntrl = (struct MAXvController *) brdptr->DevicePrivate; - /* Error check; ER command only for MAXv PSE type motors. */ - if (command == SET_ENC_RATIO && MAXvCntrl->typeID[signal] != PSE) - { - trans->state = IDLE_STATE; /* No command sent to the controller. */ - return(rtnind); - } - } - - if ((command == PRIMITIVE) && (mr->init != NULL) && - (strlen(mr->init) != 0)) - { - extern struct driver_table oms58_access; - /* Test for a "device directive" in the Initialization string. */ - if ((mr->init[0] == '@') && (trans->tabptr == &oms58_access)) - { - char *end = strrchr(&mr->init[1], '@'); - if (end != NULL) - { - struct driver_table *tabptr = trans->tabptr; - int size = (end - &mr->init[0]) + 1; - strncpy(buffer, mr->init, size); - buffer[size] = (char) NULL; - if (strcmp(buffer, "@DPM_ON@") == 0) - { - int response, bitselect; - char respbuf[10]; - - (*tabptr->getmsg)(card, respbuf, -1); - (*tabptr->sendmsg)(card, "RB\r", (char*) NULL); - (*tabptr->getmsg)(card, respbuf, 1); - if (sscanf(respbuf, "%x", &response) == 0) - response = 0; /* Force an error. */ - bitselect = (1 << motor_call->signal); - if ((response & bitselect) == 0) - trans->dpm = true; - else - errPrintf(0, __FILE__, __LINE__, - "Invalid VME58 configuration; RB = 0x%x\n", response); - } - end++; - strcpy(buffer, end); - } - else - strcpy(buffer, mr->init); - } - else - strcpy(buffer, mr->init); - - strcat(motor_call->message, buffer); - strcat(motor_call->message, ";"); - } - else - { - int first_one, itera; - - if (command == SET_HIGH_LIMIT || command == SET_LOW_LIMIT) - trans->state = IDLE_STATE; /* No command sent to the controller. */ - else - { - msta_field msta; - - /* Silently enforce minimum range on KP command. */ - if (command == SET_PGAIN && *parms < 0.00005) - { - *parms = 0.00005; - mr->pcof = 0.00005; - rtnind = ERROR; - } - else if (command == STOP_AXIS) - { - double acc; - - /* Use MIP to determine which acc. rate to use. */ - if (mr->mip & MIP_JOG_STOP) - acc = mr->jar / fabs(mr->mres); - else - acc = ((mr->velo - mr->vbas) / fabs(mr->mres)) / mr->accl; - - valid_acc = NINT(acc); - - /* For VME8/44 & MAXv, valid_acc < 8E6. For VME58, valid_acc < 1E9. - * Use 8E6 in common code. */ - if (valid_acc < 1 || valid_acc > 8E6) - { - errPrintf(-1, __FILE__, __LINE__, - "Overriding invalid acceleration.\n"); - valid_acc = (long) 200000; /* Using VME58 default. */ - } - - /* Put in acceleration. */ - if (MAXv == true) - strcat(motor_call->message, "FL"); - strcat(motor_call->message, oms_table[SET_ACCEL].command); - sprintf(buffer, "%ld", valid_acc); - strcat(motor_call->message, buffer); - if (MAXv == true) - strcat(motor_call->message, "; WQ"); - } - - if (cmnd_type == MOTION || cmnd_type == VELOCITY) - { - if (strlen(mr->prem) != 0) - { - char prem_buff[40]; - - /* Test for a "device directive" in the PREM string. */ - if (mr->prem[0] == '@') - { - bool errind = false; - char *end = strchr(&mr->prem[1], '@'); - if (end == NULL) - errind = true; - else - { - DBADDR addr; - double delay; - char *start, *tail; - int size = (end - &mr->prem[0]) + 1; - - /* Copy device directive to prem_buff. */ - strncpy(prem_buff, mr->prem, size); - prem_buff[size] = (char) NULL; - - if (strncmp(prem_buff, "@PUT(", 5) != 0) - goto errorexit; - - /* Point "start" to PV name argument. */ - tail = NULL; - start = epicsStrtok_r(&prem_buff[5], ",", &tail); - if (tail == NULL) - goto errorexit; - - if (dbNameToAddr(start, &addr)) /* Get address of PV. */ - { - errPrintf(-1, __FILE__, __LINE__, "Invalid PV name: %s", start); - goto errorexit; - } - - /* Point "start" to PV value argument. */ - start = epicsStrtok_r(NULL, ",", &tail); - if (tail == NULL) - { - delay = 0.0; - tail = start; - start = epicsStrtok_r(NULL, ")", &tail); - if (tail == NULL) - goto errorexit; - } - else - { - char *last; - - last = epicsStrtok_r(NULL, ")", &tail); - if (last == NULL) - goto errorexit; - delay = atof(last); - } - if (dbPutField(&addr, DBR_STRING, start, 1L)) - { - errPrintf(-1, __FILE__, __LINE__, "invalid value: %s", start); - goto errorexit; - } - if (delay != 0.0) - { - if (delay > 10.0) - delay = 10.0; - epicsThreadSleep(delay); - } - } - - if (errind == true) -errorexit: errMessage(-1, "Invalid device directive"); - end++; - strcpy(prem_buff, end); - } - else - strcpy(prem_buff, mr->prem); - - strcat(motor_call->message, " "); - strcat(motor_call->message, prem_buff); - strcat(motor_call->message, " "); - } - if (strlen(mr->post) != 0) - motor_call->postmsgptr = (char *) &mr->post; - } - - /* Code to hide Oms58 moving off limit switch problem. */ - msta.All = mr->msta; - if ((msta.Bits.RA_PLUS_LS || msta.Bits.RA_MINUS_LS) && - (command == MOVE_ABS || command == MOVE_REL)) - { - if (mr->rdif >= 0) - strcat(motor_call->message, " MP"); - else - strcat(motor_call->message, " MM"); - } - - /* put in command */ - strcat(motor_call->message, oms_table[command].command); - - /* put in parameters */ - for (first_one = YES, itera = 0; itera < oms_table[command].num_parms; - itera++) - { - if (first_one == YES) - first_one = NO; - else - strcat(motor_call->message, ","); - - switch (command) - { - case SET_PGAIN: - case SET_IGAIN: - case SET_DGAIN: - if (MAXv == true) - sprintf(buffer, "%.1f;", (parms[itera] * 32767.0)); - else - sprintf(buffer, "%.1f;", (parms[itera] * 1999.9)); - break; - - case SET_VELOCITY: /* OMS errors if VB = VL. */ - { - long vbase, vel; - - vbase = NINT(mr->vbas / fabs(mr->mres)); - vel = NINT(parms[itera]); - - if (vel <= vbase) - { - if (invalid_velmsg_latch == false) - { - invalid_velmsg_latch = true; /* Ouput msg. one time. */ - errPrintf(-1, __FILE__, __LINE__, - "Overriding invalid velocity; slew <= base.\n"); - } - vel = vbase + 1; - } - sprintf(buffer, "%ld", vel); - } - break; - - case MOVE_REL: - { - /* Code around OMS bug that ignores MR+/-1. */ - long relmove; - - relmove = NINT(parms[itera]); - sprintf(buffer, "%ld.9", relmove); - } - break; - - case SET_ACCEL: /* Prevent invalid acceleration values. */ - { - valid_acc = NINT(parms[itera]); - - if (valid_acc < 1 || valid_acc > 8E6) - { - errPrintf(-1, __FILE__, __LINE__, - "Overriding invalid acceleration.\n"); - valid_acc = (long) 200000; /* Using VME58 default. */ - } - sprintf(buffer, "%ld", valid_acc); - } - break; - - default: - sprintf(buffer, "%ld", NINT(parms[itera])); - } - strcat(motor_call->message, buffer); - } - - switch (command) - { - case SET_ENC_RATIO: - if (MAXv == true && parms[0] == parms[1]) - sprintf(buffer, " UF"); - else - sprintf(buffer, " UU%f;", fabs(parms[0]/parms[1])); - strcat(motor_call->message, buffer); - break; - - case LOAD_POS: - if ((MAXv == true) && (MAXvCntrl != NULL) && (MAXvCntrl->typeID[signal] != PSO) && (MAXvCntrl->fwver > 1.29)) - { - long int ref = NINT(parms[0]); - long int fdbk = ref; - if ((mr->mres > 0.0 && mr->eres < 0.0) || - (mr->mres < 0.0 && mr->eres > 0.0)) - fdbk *= -1; - sprintf(motor_call->message, "LO%ld LPE%ld;", ref, fdbk); - } - break; - - case JOG: - case JOG_VELOCITY: - strcat(motor_call->message, ";"); - - default: - break; - } - } - } - return(rtnind); -} - diff --git a/motorApp/OmsSrc/devOmsCom.h b/motorApp/OmsSrc/devOmsCom.h deleted file mode 100644 index 10722b21..00000000 --- a/motorApp/OmsSrc/devOmsCom.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -FILENAME.. devOmsCom.h - -USAGE... This file contains OMS device information that is - common to all OMS device support modules. - -*/ - -/* - * Original Author: Ron Sluiter - * Date: 12/22/98 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contract - * W-31-109-ENG-38 at Argonne National Laboratory. - * - * Beamline Controls & Data Acquisition Group - * Experimental Facilities Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - */ - -#ifndef INCdevOmsComh -#define INCdevOmsComh 1 - -#include "motordevCom.h" - -extern RTN_STATUS oms_build_trans(motor_cmnd, double *, struct motorRecord *); - -#endif /* INCdevOmsComh */ diff --git a/motorApp/OmsSrc/devOmsPC68.cc b/motorApp/OmsSrc/devOmsPC68.cc deleted file mode 100644 index 0df953cf..00000000 --- a/motorApp/OmsSrc/devOmsPC68.cc +++ /dev/null @@ -1,130 +0,0 @@ -/* -FILENAME... devOmsPC68.c -USAGE... Motor record device level support for OMS VME58. - -*/ - -/* - * Original Author: Brian Tieman - * Current Author: Ron Sluiter - * Date: 04/24/06 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - * .01 04-25-06 copied from devOms.cc - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "motorRecord.h" -#include "motor.h" -#include "drvOmsPC68Com.h" -#include "devOmsCom.h" - -#include "epicsExport.h" - -#define STATIC static - -extern int OmsPC68_num_cards; -extern struct driver_table OmsPC68_access; - -/* ----------------Create the dsets for devOMS----------------- */ -STATIC long oms_init(int); -STATIC long oms_init_record(void *); -STATIC long oms_start_trans(struct motorRecord *); -STATIC RTN_STATUS oms_end_trans(struct motorRecord *); - -struct motor_dset devOmsPC68 = -{ - {8, NULL, (DEVSUPFUN) oms_init, (DEVSUPFUN) oms_init_record, NULL}, - motor_update_values, - oms_start_trans, - oms_build_trans, - oms_end_trans -}; - -extern "C" {epicsExportAddress(dset,devOmsPC68);} - -STATIC struct board_stat **oms_cards; -STATIC const char errmsg[] = {"\n\n!!!ERROR!!! - OmsPC68 driver uninitialized.\n"}; - -//__________________________________________________________________________________________ - -STATIC long oms_init(int after) -{ - if (*(OmsPC68_access.init_indicator) == NO) - { - errlogSevPrintf(errlogMinor, "%s", errmsg); - return(ERROR); - } - else - return(motor_init_com (after, OmsPC68_num_cards, &OmsPC68_access, &oms_cards)); -} - -//__________________________________________________________________________________________ - -STATIC long oms_init_record(void *arg) -{ - struct motorRecord *mr = (struct motorRecord *) arg; - - return(motor_init_record_com(mr, OmsPC68_num_cards, &OmsPC68_access, oms_cards)); -} - -//__________________________________________________________________________________________ - -STATIC long oms_start_trans(struct motorRecord *mr) -{ - struct motor_trans *trans; - long rtnval; - - rtnval = motor_start_trans_com(mr, oms_cards); - /* Initialize a STOP_AXIS command termination string pointer. */ - trans = (struct motor_trans *) mr->dpvt; - trans->motor_call.termstring = " ID"; - return(rtnval); -} - -//__________________________________________________________________________________________ - -STATIC RTN_STATUS oms_end_trans(struct motorRecord *mr) -{ - if (*(OmsPC68_access.init_indicator) == NO) - { - errlogSevPrintf(errlogMinor, "%s", errmsg); - return(ERROR); - } - else - return(motor_end_trans_com(mr, &OmsPC68_access)); -} - -//__________________________________________________________________________________________ diff --git a/motorApp/OmsSrc/drvMAXv.cc b/motorApp/OmsSrc/drvMAXv.cc deleted file mode 100644 index 29ffee47..00000000 --- a/motorApp/OmsSrc/drvMAXv.cc +++ /dev/null @@ -1,1486 +0,0 @@ -/* -FILENAME... drvMAXv.cc -USAGE... Motor record driver level support for OMS model MAXv. - -*/ - -/* - * Original Author: Ron Sluiter - * Date: 04/05/04 - * Current Author: Ron Sluiter - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * NOTES - * ----- - * Verified with MAXv firmware: - * - ver:1.25 - * - ver:1.29 (has ECO #1432; fixes initialization problem). - * - ver:1.31 (fixes DPRAM encoder position data problem when using mixed motor types.) - * - ver:1.33, FPGA:B2:A6 BOOT:1.2 (Watchdog Timeout Counter added) - * - ver:1.34, FPGA:03:A6 BOOT:1.3 - * - ver:1.41 & 1.42, suffers from having limit switches disabled at power-up. - * - ver:1.44, No known problems. - * - ver:1.45, limit switches are disabled by default. - * - * Modification Log: - * ----------------- - * 01 04-05-04 rls - Copied from drvOms58.cc - * 02 09-20-04 rls - support for 32axes/controller. - * - added MAXvConfig() with initilization string. Axis type MUST be set before iocInit is called. - * 03 12-14-04 rls - MS Visual C compiler support. - * - eliminate calls to devConnectInterrupt() due to C++ problems with devLib.h; i.e. "sorry, not - * implemented: `tree_list' not supported..." compiler error message. - * 04 03-21-05 rls - Make MAXv OSI. - * 05 05-02-05 rls - Bug fix for stale data delay; set delay = 10ms. - * 06 05-17-06 rls - Allow polling rate up to 1/epicsThreadSleepQuantum(). - * - Protect against multiple MAXvSetup() calls. - * 07 06-05-07 rls - Added Jens Eden (BESSY) modifications; - * - register iocsh commands. - * - added USE_DEVLIB with RTEMS conditionial. - * - replaced errlogPrintf calls in ISR with epicsInterruptContextMessage calls. - * 08 08-20-07 rls - Make send_mess() and recv_mess() non-global. - * - removed unneeded stub start_status(). - * 09 02-26-08 rls - set "update delay" to zero. - * 10 05-14-08 rls - read the commanded velocity. - * 11 05-20-08 rls - A24/A32 address mode bug fix. - * 12 01-05-09 rls - Dirk Zimoch's (PSI) bug fix for set_status() overwriting the home switch status in the response - * string. - * 13 06-18-09 rls - Make MAXvSetup() error messages more prominent. - * 14 07-02-09 rls - backwards compatibility with ver:1.29 and earlier firmware. OMS changed from '' to - * '' for RA, QA, EA and RL command with ver:1.30 - * 15 09-09-09 rls - board "running" error check added. - * 16 03-08-10 rls - sprintf() not callable from RTEMS interrupt context. - * 17 03-09-10 rls - sprintf() not callable from any OS ISR. - * 18 06-01-10 rls - Save firmware version in static float array. - * - For firmware ver:1.33 and above, read Watchdog Timeout Counter. If Counter is nonzero, print - * error message and clear Counter. - * 19 06-07-10 rls - Disable board if WDT CTR is nonzero; don't clear CTR. - * 20 02-03-11 rls - Increase max. config. string size from 150 to 300 bytes. - * - Increase all receive buffer sizes to same 300 bytes. - * - Add error checks for buffer overflow with MAXvConfig()'s configuration string argument and in - * readbuf(). - * 21 02-04-11 rls - Added counter to send_mess()'s "waiting for message acknowledgement" loop to prevent infinite - * loop. - * 22 09-23-11 ajr - Added configuration word MAXvConfig. - * 23 10-26-11 rls - Changed Debug() to Mark River's variable arguments macro. - * - Added MAXvController data structure using private data in motor record to store motor type. Motor - * type used in device support (devOmsCom.cc) to allow MRES and ERES with different polarity (signs). - * 24 02-24-14 rls - After the initialization string is read, if limit mode is "Off", set it to "Hard". - * - Added MAXvConfig() 4th argument to support absolute encoders with grey code data formats. - * 25 07-05-14 rls - send_mess() terminates all commands with a ';'. OMS tech support's suggested fix for intermittent - * "Command Error" messages on valid messages (e.g., "AY VB100 VL4000 AC19500 MA5100 GD ID"). - * - More than one command with a response not allowed when terminated with a ';'. Broke "QA EA" - * command into two commands. - * - Fix for intermittent wrong command displayed from Command Error message. motorIsr() saves the - * message in a separate static buffer. - * 26 02-08-16 rls - Valid IRQ levels are 2 thru 6. - * 27 04-04-17 rls - Added error check for new failure mode where board reboots after 1st command with response. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "motorRecord.h" /* For Driver Power Monitor feature only. */ -#include "motor.h" -#include "motordevCom.h" /* For Driver Power Monitor feature only. */ -#include "drvMAXv.h" - -#include "epicsExport.h" - -#define MUTEX(card) ((struct MAXvController *)(motor_state[card]->DevicePrivate))->message_mutex - -/* Define for return test on devNoResponseProbe() */ -#define PROBE_SUCCESS(STATUS) ((STATUS)==S_dev_addressOverlap) - -/* Are we using VME-Bus/devLib */ -#if (defined(vxWorks) || defined(__rtems__)) - #define USE_DEVLIB -#endif - -/* jps: INFO messages - add RV and move QA to top */ -#define AXIS_INFO "QA" -#define ENCODER_QUERY "EA ID" -#define AXIS_CLEAR "CA" /* Clear done of addressed axis */ -#define DONE_QUERY "RA" /* ?? Is this needed?? */ -#define PID_QUERY "?KA ID" - -/*----------------debugging-----------------*/ -volatile int drvMAXvdebug = 0; -extern "C" {epicsExportAddress(int, drvMAXvdebug);} - -static inline void Debug(int level, const char *format, ...) { - #ifdef DEBUG - if (level < drvMAXvdebug) { - va_list pVar; - va_start(pVar, format); - vprintf(format, pVar); - va_end(pVar); - } - #endif -} - -#define pack2x16(p) ((epicsUInt32)(((p[0])<<16)|(p[1]))) -#define INITSTR_SIZE 300 /* 300 byte configuration string. */ - -/* Global data. */ -int MAXv_num_cards = 0; - -/* Local data required for every driver; see "motordrvComCode.h" */ -#include "motordrvComCode.h" - -/* --- Local data common to all OMS drivers. --- */ -static char *MAXv_addrs = 0x0; -static epicsAddressType MAXv_ADDRS_TYPE; -static volatile unsigned MAXvInterruptVector = 0; -static volatile epicsUInt8 omsInterruptLevel = OMS_INT_LEVEL; -static volatile int motionTO = 10; -static const char *MAXv_axis[] = {"X", "Y", "Z", "T", "U", "V", "R", "S"}; -static double quantum; -static char **initstring = 0; -static epicsUInt32 MAXv_brd_size; /* card address boundary */ -static char cmndbuf[MAX_MSG_SIZE]; /* Command buffer used by send_mess() and - * motorIsr if there is a "command error"*/ - -/* First 8-bits [0..7] used to indicate absolute or */ -/* incremental position registers to be read */ -static int configurationFlags[MAXv_NUM_CARDS] = {0}; -static int greycodeConfigFlags[MAXv_NUM_CARDS] = {0}; - -/*----------------functions-----------------*/ - -/* Common local function declarations. */ -extern "C" { -RTN_STATUS MAXvSetup(int, int, unsigned int, unsigned int, int, int); -RTN_VALUES MAXvConfig(int, const char *, int); -} -static long report(int); -static long init(); -static void query_done(int, int, struct mess_node *); -static int set_status(int, int); -static RTN_STATUS send_mess(int, char const *, char *); -static int recv_mess(int, char *, int); -static int getPositions(int card, epicsInt32 *positions, int nPositions); -static int send_recv_mess(int card, char const * command, char *axis, char *buf, int nMessages); - -extern "C" { - -int MAXV_send_mess(int card, char const * command, char *axis) { - return (int)send_mess(card, command, axis); -} - -int MAXV_recv_mess(int card, char *buf, int nMessages) { - return recv_mess(card, buf, nMessages); -} - -int MAXV_send_recv_mess(int card, char const * command, char *axis, char *buf, int nMessages) { - return send_recv_mess(card, command, axis, buf, nMessages); -} - -int MAXV_getPositions(int card, epicsInt32 *positions, int nPositions) { - return getPositions(card, positions, nPositions); -} - -} - -static int getPositions(int card, epicsInt32 *positions, int nPositions) { - volatile struct MAXv_motor *pmotor; - pmotor = (struct MAXv_motor *) motor_state[card]->localaddr; - int i; - for (i=0; icmndPos[i]; - Debug(5, "getPositions: motor %d position=%d\n", i, positions[i]); - } - return(0); -} - -static void motorIsr(int); -static int motor_init(); -static void MAXv_reset(void *); -static char *readbuf(volatile struct MAXv_motor *, char *); - -static int motorIsrSetup(int card); - -struct driver_table MAXv_access = -{ - NULL, - motor_send, - motor_free, - motor_card_info, - motor_axis_info, - &mess_queue, - &queue_lock, - &free_list, - &freelist_lock, - &motor_sem, - &motor_state, - &total_cards, - &any_motor_in_motion, - send_mess, - recv_mess, - set_status, - query_done, - NULL, - &initialized, - (char **) MAXv_axis -}; - -struct drvMAXv_drvet -{ - long number; - long (*report) (int); - long (*init) (void); -} drvMAXv = {2, report, init}; - -extern "C" {epicsExportAddress(drvet, drvMAXv);} - -static struct thread_args targs = {SCAN_RATE, &MAXv_access, 0.000}; - -static char wdctrmsg[] = "\n***MAXv card #%d Disabled*** Watchdog Timeout CTR %s\n\n"; -static char norunmsg[] = "\n*** MAXv card #%d is NOT running *** status = 0x%x\n"; - - -/*----------------functions-----------------*/ - -static long report(int level) -{ - int card; - - if (MAXv_num_cards <= 0) - printf(" No MAXv controllers configured.\n"); - else - { - for (card = 0; card < MAXv_num_cards; card++) - { - struct controller *brdptr = motor_state[card]; - - if (brdptr == NULL) - printf(" Oms MAXv motor card #%d not found.\n", card); - else - printf(" Oms MAXv motor card #%d @ %p, id: %s \n", card, - motor_state[card]->localaddr, motor_state[card]->ident); - } - } - return (0); -} - -static long init() -{ - initialized = true; /* Indicate that driver is initialized. */ - (void) motor_init(); - return ((long) 0); -} - - -static void query_done(int card, int axis, struct mess_node *nodeptr) -{ - char buffer[MAX_IDENT_LEN]; - - send_recv_mess(card, DONE_QUERY, (char *) MAXv_axis[axis], buffer, 1); - - if (nodeptr->status.Bits.RA_PROBLEM) - send_mess(card, AXIS_STOP, (char *) MAXv_axis[axis]); -} - - -/****************************************************************************** -* FUNCTION NAME: set_status -* -* ARGUMETS Type I/O Description -* -------- ---- --- ----------- -* -* card int I Controller card index #. -* signal int I Motor index. -* -* LOGIC -* Initialize. -* IF encoder present. -* Get axis and encoder information. -* ELSE -* Get axis information. -* ENDIF -* -* Process controller response strings. -* -* ... -* ... -* IF "motor-in-motion" (i.e., nodeptr != 0), AND, no limit switch error. -* IF drive power monitoring enabled. -* ... -* ENDIF -* ENDIF -* -* IF no motion, OR, status indicates limit switch error, OR, motor done, OR, -* controller problem. -* Set return state to "callback record". -* ELSE -* Set return state to skip "record callback". -* ENDIF -* IF status indicates DONE/LIMIT, AND, "motor-in-motion" (nodeptr != 0), AND, -* post-move message is not null. -* Send post-move message to controller. -* Clear post-move message pointer. -* ENDIF -* EXIT with return state indicator. -******************************************************************************/ - -static int set_status(int card, int signal) -{ - struct mess_info *motor_info; - struct mess_node *nodeptr; - volatile struct MAXv_motor *pmotor; - epicsInt32 motorData; - /* Message parsing variables */ - char *p, *tok_save; - struct axis_status *ax_stat; - struct encoder_status *en_stat; - struct controller *brdptr; - struct MAXvController *MAXvCntrl; - - char q_buf[MAX_IDENT_LEN], outbuf[50]; - int index; - bool ls_active = false; - msta_field status; - - int absoluteAxis = (configurationFlags[card] & (1 << signal)); - - int rtn_state; - - motor_info = &(motor_state[card]->motor_info[signal]); - nodeptr = motor_info->motor_motion; - pmotor = (struct MAXv_motor *) motor_state[card]->localaddr; - status.All = motor_info->status.All; - - if ((brdptr = motor_state[card]) == NULL) /* Test for board disabled. */ - return(rtn_state = 1); /* End move. */ - - MAXvCntrl = (struct MAXvController *) brdptr->DevicePrivate; - if (MAXvCntrl->fwver >= 1.33) - { - send_recv_mess(card, "#WS", (char *) NULL, q_buf, 1); - if (strcmp(q_buf, "=0") != 0) - { - errlogPrintf(wdctrmsg, card, q_buf); - status.Bits.RA_PROBLEM = 1; - motor_info->status.All = status.All; - send_mess(card, STOP_ALL, (char*) NULL); - /* Disable board. */ - motor_state[card] = (struct controller *) NULL; - return(rtn_state = 1); /* End move. */ - } - } - - if (motor_info->encoder_present == YES) - { - /* get 4 pieces of info from axis */ - send_recv_mess(card, "QA", (char *) MAXv_axis[signal], &q_buf[0], 1); - q_buf[4] = ','; - send_recv_mess(card, "EA", (char *) MAXv_axis[signal], &q_buf[5], 1); - } - else - { - /* get 2 pieces of info from axis */ - send_recv_mess(card, AXIS_INFO, (char *) MAXv_axis[signal], q_buf, 1); - } - - for (index = 0, p = epicsStrtok_r(q_buf, ",", &tok_save); p; - p = epicsStrtok_r(NULL, ",", &tok_save), index++) - { - switch (index) - { - case 0: /* axis status */ - ax_stat = (struct axis_status *) p; - - status.Bits.RA_DIRECTION = (ax_stat->direction == 'P') ? 1 : 0; - status.Bits.RA_HOME = (ax_stat->home == 'H') ? 1 : 0; - status.Bits.RA_DONE = (ax_stat->done == 'D') ? 1 : 0; - - if (ax_stat->overtravel == 'L') - { - ls_active = true; - if (status.Bits.RA_DIRECTION) - status.Bits.RA_PLUS_LS = 1; - else - status.Bits.RA_MINUS_LS = 1; - } - else - { - ls_active = false; - status.Bits.RA_PLUS_LS = 0; - status.Bits.RA_MINUS_LS = 0; - } - break; - - case 1: /* encoder status */ - en_stat = (struct encoder_status *) p; - - status.Bits.EA_SLIP = (en_stat->slip_enable == 'E') ? 1 : 0; - status.Bits.EA_POSITION = (en_stat->pos_enable == 'E') ? 1 : 0; - status.Bits.EA_SLIP_STALL = (en_stat->slip_detect == 'S') ? 1 : 0; - status.Bits.EA_HOME = (en_stat->axis_home == 'H') ? 1 : 0; - break; - - default: - break; - } - } - - /* motor pulse count (position) */ - motorData = pmotor->cmndPos[signal]; - - if (motorData == motor_info->position) - { - if (nodeptr != 0) /* Increment counter only if motor is moving. */ - motor_info->no_motion_count++; - } - else - { - motor_info->no_motion_count = 0; - motor_info->position = motorData; - } - - if (motor_info->no_motion_count > motionTO) - { - status.Bits.RA_PROBLEM = 1; - send_mess(card, AXIS_STOP, (char *) MAXv_axis[signal]); - motor_info->no_motion_count = 0; - errlogSevPrintf(errlogMinor, "Motor motion timeout ERROR on card: %d, signal: %d\n", - card, signal); - } - else if (pmotor->firmware_status.Bits.running == 0) - { - status.Bits.RA_PROBLEM = 1; - errlogPrintf(norunmsg, card, (unsigned int) pmotor->firmware_status.All); - } - else - status.Bits.RA_PROBLEM = 0; - - /* get command velocity */ - send_recv_mess(card, "RV", (char *) MAXv_axis[signal], q_buf, 1); - motor_info->velocity = atoi(q_buf); - - /* Get encoder position */ - if (absoluteAxis) - { - bool greyCode = (greycodeConfigFlags[card] & (1 << signal)); - - if (greyCode == true) - { - epicsUInt32 mask, num; - num = pmotor->absPos[signal]; - for (mask = num >> 1; mask != 0; mask = mask >> 1) - num = num ^ mask; - motorData = num; - } - else - motorData = pmotor->absPos[signal]; - } - else - motorData = pmotor->encPos[signal]; - - motor_info->encoder_position = motorData; - - if (nodeptr != NULL && ls_active == false) - { - struct motor_trans *trans = (struct motor_trans *) nodeptr->mrecord->dpvt; - if (trans->dpm == true) - { - errlogPrintf("Drive power failure at MAXv card#%d motor#%d\n", - card, signal); - } - } - - rtn_state = (!motor_info->no_motion_count || ls_active == true || - status.Bits.RA_DONE | status.Bits.RA_PROBLEM) ? 1 : 0; - - /* Test for post-move string. */ - if ((status.Bits.RA_DONE || ls_active == true) && nodeptr != 0 && - nodeptr->postmsgptr != 0) - { - char buffer[40]; - - /* Test for a "device directive" in the POST string. */ - if (nodeptr->postmsgptr[0] == '@') - { - bool errind = false; - char *end = strchr(&nodeptr->postmsgptr[1], '@'); - if (end == NULL) - errind = true; - else - { - DBADDR addr; - char *start, *tail; - int size = (end - &nodeptr->postmsgptr[0]) + 1; - - /* Copy device directive to buffer. */ - strncpy(buffer, nodeptr->postmsgptr, size); - buffer[size] = (char) NULL; - - if (strncmp(buffer, "@PUT(", 5) != 0) - goto errorexit; - - /* Point "start" to PV name argument. */ - tail = NULL; - start = epicsStrtok_r(&buffer[5], ",", &tail); - if (tail == NULL) - goto errorexit; - - if (dbNameToAddr(start, &addr)) /* Get address of PV. */ - { - errPrintf(-1, __FILE__, __LINE__, "Invalid PV name: %s", start); - goto errorexit; - } - - /* Point "start" to PV value argument. */ - start = epicsStrtok_r(NULL, ")", &tail); - if (dbPutField(&addr, DBR_STRING, start, 1L)) - { - errPrintf(-1, __FILE__, __LINE__, "invalid value: %s", start); - goto errorexit; - } - } - - if (errind == true) -errorexit: errMessage(-1, "Invalid device directive"); - end++; - strcpy(buffer, end); - } - else - strcpy(buffer, nodeptr->postmsgptr); - - strcpy(outbuf, buffer); - send_mess(card, outbuf, (char *) MAXv_axis[signal]); - nodeptr->postmsgptr = NULL; - } - - /* Bug fix for DC servo moving away from limit switch, but move is not far enough to - * get off limit switch; resulting in limit error. Fix is to force CDIR to match - * MSTA.RA_DIRECTION. - */ - if (ls_active == true && status.Bits.GAIN_SUPPORT && - status.Bits.EA_POSITION == 0 && nodeptr != 0) - { - struct motorRecord *mr = (struct motorRecord *) nodeptr->mrecord; - - if (mr->cdir != (short) status.Bits.RA_DIRECTION) - mr->cdir = status.Bits.RA_DIRECTION; - } - - motor_info->status.All = status.All; /* Update status from local copy. */ - return(rtn_state); -} - -/************************************************** - * send a message to the OMS board and get the reply - **************************************************/ -static int send_recv_mess(int card, char const * command, char *axis, char *buf, int nMessages) { - int retval; - - if (!epicsMutexTryLock(MUTEX(card))) { - Debug(1, "send_recv_mess: waiting for mutex\n"); - epicsMutexLock(MUTEX(card)); - } - retval = (int)send_mess(card, command, axis); - retval |= recv_mess(card, buf, nMessages); - epicsMutexUnlock(MUTEX(card)); - return(retval); -} - -/*****************************************************/ -/* send a message to the OMS board */ -/* send_mess() */ -/*****************************************************/ -static RTN_STATUS send_mess(int card, char const *com, char *name) -{ - volatile struct MAXv_motor *pmotor; - epicsInt16 putIndex; - char *pcmndbuf; - RTN_STATUS return_code; - int count; - - if (strlen(com) > MAX_MSG_SIZE) - { - errlogPrintf("drvMAXv.cc:send_mess(); message size violation.\n"); - return (ERROR); - } - - /* Check that card exists */ - if (!motor_state[card]) - { - errlogPrintf("drvMAXv.cc:send_mess() - invalid card #%d\n", card); - return (ERROR); - } - - pmotor = (struct MAXv_motor *) motor_state[card]->localaddr; - Debug(9, "send_mess: pmotor = %p\n", pmotor); - - if (!epicsMutexTryLock(MUTEX(card))) { - Debug(1, "send_mess: waiting for mutex\n"); - epicsMutexLock(MUTEX(card)); - } - - return_code = OK; - - Debug(9, "send_mess: checking card %d status\n", card); - - /* see if junk at input port - should not be any data available */ - if (pmotor->inGetIndex != pmotor->inPutIndex) - { - Debug(1, "send_mess - clearing data in buffer\n"); - recv_mess(card, cmndbuf, FLUSH); - } - - - if (name == NULL) - strcpy(cmndbuf, com); - else - { - strcpy(cmndbuf, "A"); - strcat(cmndbuf, name); - strcat(cmndbuf, " "); - strcat(cmndbuf, com); - } - - if (cmndbuf[strlen(cmndbuf) - 1] != ';') /* Terminate command with a ';'. */ - strcat(cmndbuf, ";"); - - Debug(9, "send_mess: ready to send message.\n"); - putIndex = pmotor->outPutIndex; - for (pcmndbuf = cmndbuf; *pcmndbuf != '\0'; pcmndbuf++) - { - pmotor->outBuffer[putIndex++] = *pcmndbuf; - if (putIndex >= BUFFER_SIZE) - putIndex = 0; - } - - Debug(4, "send_mess: sent card %d message:", card); - Debug(4, "%s\n", cmndbuf); - - pmotor->outPutIndex = putIndex; /* Message Sent */ - - for (count = 0; (pmotor->outPutIndex != pmotor->outGetIndex) && - (count < 1000); count++) - { -#ifdef DEBUG - epicsInt16 deltaIndex, delta; - - deltaIndex = pmotor->outPutIndex - pmotor->outGetIndex; - delta = (deltaIndex < 0) ? BUFFER_SIZE + deltaIndex : deltaIndex; - Debug(5, "send_mess: Waiting for ack: index delta=%d\n", delta); -#endif - epicsThreadSleep(epicsThreadSleepQuantum()); - }; - - if (count >= 1000) - { - errlogPrintf("\n*** MAXv card #%d communication timeout ***\n", card); - return_code = ERROR; - } - - epicsMutexUnlock(MUTEX(card)); - return (return_code); -} - -/* - * FUNCTION... recv_mess(int card, char *com, int amount) - * - * INPUT ARGUMENTS... - * card - - * *com - - * amount - - * - * LOGIC... - * IF controller card does not exist. - * ERROR Exit. - * ENDIF - * IF "amount" indicates buffer flush. - * WHILE characters left in input buffer. - * Remove characters from controller's input buffer. - * ENDWHILE - * NORMAL RETURN. - * ENDIF - * - * FOR each message requested (i.e. "amount"). - * Initialize head and tail pointers. - * Initialize local buffer "get" index. - * FOR - * IF characters left in controller's input buffer. - * - * ENDIF - * ENDFOR - * ENDFOR - * - */ -static int recv_mess(int card, char *com, int amount) -{ - volatile struct MAXv_motor *pmotor; - int itera; - char *bufptr; - - /* Check that card exists */ - if (!motor_state[card]) - { - Debug(1, "recv_mess - invalid card #%d\n", card); - return(-1); - } - - pmotor = (struct MAXv_motor *) motor_state[card]->localaddr; - - if (!epicsMutexTryLock(MUTEX(card))) { - Debug(1, "recv_mess: waiting for mutex\n"); - epicsMutexLock(MUTEX(card)); - } - - if (amount == -1) - { - if (pmotor->inGetIndex != pmotor->inPutIndex) - { - char junk[MAX_IDENT_LEN]; - - readbuf(pmotor, junk); - - Debug(1, "recv_mess(): flushed - %s\n", junk); - } - epicsMutexUnlock(MUTEX(card)); - return(0); - } - - bufptr = com; - *bufptr = (char) NULL; - - do - { - itera = 1; - double time = 0.0; - - while (pmotor->status1_flag.Bits.text_response == 0 && time < 0.100) - { - Debug(1, "recv_mess(): response wait - %d\n", itera); - time += quantum * itera; - epicsThreadSleep(quantum * itera); - itera++; - } - - if (pmotor->status1_flag.Bits.text_response == 0) - { - Debug(1, "Timeout occurred in recv_mess\n"); - *bufptr = '\0'; - epicsMutexUnlock(MUTEX(card)); - return(-1); - } - - bufptr = readbuf(pmotor, bufptr); - if (--amount > 0) - { - if (*(bufptr-1) == '\n') /* For ver:1.29 and before firmware, */ - *(bufptr-1) = ','; /* replace <0> with <,><0>. */ - else /* For ver:1.30 and after firmware, */ - *(bufptr++) = ','; /* replace with <,>. */ - } - } while (amount > 0); - - epicsMutexUnlock(MUTEX(card)); - Debug(4, "recv_mess(): card#%d - %s\n", card, com); - return(0); -} - -static char *readbuf(volatile struct MAXv_motor *pmotor, char *bufptr) -{ - STATUS1 flag1; - epicsUInt32 getIndex, putIndex; - int bufsize; - char *start, *end, *bufend; - - getIndex = pmotor->inGetIndex; - putIndex = pmotor->inPutIndex; - bufsize = putIndex - getIndex; - - start = (char *) &pmotor->inBuffer[getIndex]; - end = (char *) &pmotor->inBuffer[putIndex]; - - if (start < end) /* Test for message wraparound in buffer. */ - memcpy(bufptr, start, bufsize); - else if (start == end) /* Test for empty input buffer. */ - { - static char emptymsg[] = - "MAXv DPRAM input buffer empty; inGetIndex = %d inPutIndex = %d\n"; - - errlogPrintf(emptymsg, getIndex, putIndex); - return(bufptr); - } - else - { - int size; - - bufend = (char *) &pmotor->inBuffer[BUFFER_SIZE]; - size = bufend - start; - bufsize += BUFFER_SIZE; - - if (bufsize > MAX_IDENT_LEN) - { - errlogPrintf("\n*** MAXv readbuf() overrun ***; bufsize = %d\n\n", bufsize); - return(bufptr); - } - else - { - memcpy(bufptr, start, size); - memcpy((bufptr + size), (const char *) &pmotor->inBuffer[0], (bufsize - size)); - } - } - - getIndex += bufsize; - if (getIndex >= BUFFER_SIZE) - getIndex -= BUFFER_SIZE; - - bufptr += (bufsize - 1); - *bufptr = (char) NULL; - - while (getIndex != pmotor->inPutIndex) - { - Debug(1, "readbuf(): flushed - %d\n", pmotor->inBuffer[getIndex]); - if (++getIndex > BUFFER_SIZE) - getIndex = 0; - } - - pmotor->inGetIndex = getIndex; - flag1.All = pmotor->status1_flag.All; - pmotor->status1_flag.All = flag1.All; - pmotor->msg_semaphore = 0; - return(bufptr); -} - -/*****************************************************/ -/* Configuration function for module_types data */ -/* areas. MAXvSetup() */ -/*****************************************************/ -RTN_STATUS -MAXvSetup(int num_cards, /* maximum number of cards in rack */ - int addrs_type, /* VME address type; 16 - A16, 24 - A24 or 32 - A32. */ - unsigned int addrs, /* Base Address. */ - unsigned int vector, /* noninterrupting(0), valid vectors(64-255) */ - int int_level, /* interrupt level (2-6) */ - int scan_rate) /* 1 <= polling rate <= (1/epicsThreadSleepQuantum) */ -{ - int itera; - char **strptr; - RTN_STATUS rtncode = OK; - double frequency; - char errbase[] = "\nMAXvSetup: *** invalid "; - - if (initstring == NULL) - initstring = (char **) callocMustSucceed(1, - sizeof(char *) * MAXv_NUM_CARDS, "MAXvSetup() initstring"); - else - { - /* Deallocate memory for initialization strings. */ - for (itera = 0, strptr = &initstring[0]; itera < MAXv_num_cards; itera++, strptr++) - free(*strptr); - } - - if (num_cards < 1 || num_cards > MAXv_NUM_CARDS) - { - char format[] = "%snumber of cards specified = %d ***\n"; - MAXv_num_cards = MAXv_NUM_CARDS; - errlogPrintf(format, errbase, num_cards); - errlogPrintf(" *** using maximum number = %d ***\n", MAXv_NUM_CARDS); - epicsThreadSleep(5.0); - rtncode = ERROR; - } - else - MAXv_num_cards = num_cards; - - { - char addmsg[] = "%sA%d address *** = 0x%X.\n"; - switch (addrs_type) - { - case 16: - MAXv_ADDRS_TYPE = atVMEA16; - if ((epicsUInt32) addrs & 0xFFFF0FFF) - { - errlogPrintf(addmsg, errbase, 16, (epicsUInt32) addrs); - rtncode = ERROR; - } - else - { - MAXv_addrs = (char *) addrs; - MAXv_brd_size = 0x1000; - } - break; - case 24: - MAXv_ADDRS_TYPE = atVMEA24; - if ((epicsUInt32) addrs & 0xFF00FFFF) - { - errlogPrintf(addmsg, errbase, 24, (epicsUInt32) addrs); - rtncode = ERROR; - } - else - { - MAXv_addrs = (char *) addrs; - MAXv_brd_size = 0x10000; - } - break; - case 32: - MAXv_ADDRS_TYPE = atVMEA32; - if ((epicsUInt32) addrs & 0x00FFFFFF) - { - errlogPrintf(addmsg, errbase, 32, (epicsUInt32) addrs); - rtncode = ERROR; - } - else - { - MAXv_addrs = (char *) addrs; - MAXv_brd_size = 0x1000000; - } - break; - default: - { - char format[] = "%sVME address type = %d ***\n"; - errlogPrintf(format, errbase, addrs_type); - } - rtncode = ERROR; - break; - } - } - - if (rtncode == ERROR) - epicsThreadSleep(5.0); - - MAXvInterruptVector = vector; - if (vector < 64 || vector > 255) - { - if (vector != 0) - { - char format[] = "%sinterrupt vector = %d ***\n"; - MAXvInterruptVector = (unsigned) OMS_INT_VECTOR; - errlogPrintf(format, errbase, vector); - epicsThreadSleep(5.0); - rtncode = ERROR; - } - } - - if (int_level < 2 || int_level > 6) - { - char format[] = "%sinterrupt level = %d *** default = 5\n"; - omsInterruptLevel = OMS_INT_LEVEL; - errlogPrintf(format, errbase, int_level); - epicsThreadSleep(5.0); - rtncode = ERROR; - } - else - omsInterruptLevel = int_level; - - quantum = epicsThreadSleepQuantum(); - frequency = 1.0 / quantum; - - /* Set motor polling task rate */ - if (scan_rate >= 1 && scan_rate <= frequency) - targs.motor_scan_rate = scan_rate; - else - { - char format[] = "%spolling rate = %d ***\n"; - targs.motor_scan_rate = (int) frequency; - errlogPrintf(format, errbase, scan_rate); - epicsThreadSleep(5.0); - rtncode = ERROR; - } - - /* Allocate memory for initialization strings. */ - for (itera = 0, strptr = &initstring[0]; itera < MAXv_num_cards; itera++, strptr++) - { - *strptr = (char *) malloc(INITSTR_SIZE); - **strptr = (char) NULL; - } - - return(rtncode); -} - -RTN_VALUES MAXvConfig(int card, /* number of card being configured */ - const char *initstr, /* configuration string */ - int AbsConfig, /* absolute encoder configuration */ - int GreyConfig) /* absolute encoder grey code configuration */ -{ - if (card < 0 || card >= MAXv_num_cards) - { - errlogPrintf("MAXvConfig: invalid card %d\n", card); - epicsThreadSleep(5.0); - return(ERROR); - } - - if (strlen(initstr) > INITSTR_SIZE) - { - errlogPrintf("\n*** MAXvConfig ERROR ***\n"); - errlogPrintf("Configuration string: %d bytes > %d maximum.\n\n", (int)strlen(initstr), INITSTR_SIZE); - epicsThreadSleep(5.0); - return(ERROR); - } - strcpy(initstring[card], initstr); - - /* Save absolute encoder and grey code configuation flags */ - configurationFlags[card] = AbsConfig; - greycodeConfigFlags[card] = GreyConfig; - return(OK); -} - - -/*****************************************************/ -/* Interrupt service routine. */ -/* motorIsr() */ -/*****************************************************/ -static void motorIsr(int card) -{ - volatile struct controller *pmotorState; - volatile struct MAXv_motor *pmotor; - STATUS1 status1_flag; - static char errmsg1[] = "drvMAXv.cc:motorIsr: ***Invalid entry*** - card xx\n"; - static char errmsg2[] = "drvMAXv.cc:motorIsr: ***Command Error*** - card xx\n"; - static char CmndErrBuf[MAX_MSG_SIZE]; /* Hold the message that caused a Command Error here. */ - - if (card >= total_cards || (pmotorState = motor_state[card]) == NULL) - { - errmsg1[51-2] = '0' + card%10; - errmsg1[51-3] = '0' + (card/10)%10; - epicsInterruptContextMessage(errmsg1); - return; - } - - pmotor = (struct MAXv_motor *) (pmotorState->localaddr); - status1_flag.All = pmotor->status1_flag.All; - - /* Motion done handling */ - if (status1_flag.Bits.done != 0) - motor_sem.signal(); /* Wake up 'motor_task()' to issue callbacks */ - - if (status1_flag.Bits.cmndError) - { - errmsg2[51-2] = '0' + card%10; - errmsg2[51-3] = '0' + (card/10)%10; - epicsInterruptContextMessage(errmsg2); - strcpy(CmndErrBuf, cmndbuf); /* Copy message to static buffer. */ - strcat(CmndErrBuf,"\n\n"); - epicsInterruptContextMessage(CmndErrBuf); - } - - if (status1_flag.Bits.text_response != 0) /* Don't clear this. */ - status1_flag.Bits.text_response = 0; - - pmotor->status1_flag.All = status1_flag.All; /* Release IRQ's. */ -} - -static int motorIsrSetup(int card) -{ - volatile struct MAXv_motor *pmotor; - STATUS1 status1_irq; -#ifdef USE_DEVLIB - long status; -#endif - - Debug(5, "motorIsrSetup: Entry card#%d\n", card); - - pmotor = (struct MAXv_motor *) (motor_state[card]->localaddr); - -#ifdef USE_DEVLIB - - status = pdevLibVirtualOS->pDevConnectInterruptVME( - MAXvInterruptVector + card, -#if LT_EPICSBASE(3,14,8,0) - (void (*)()) motorIsr, -#else - (void (*)(void *)) motorIsr, -#endif - (void *) card); - - if (!RTN_SUCCESS(status)) - { - errPrintf(status, __FILE__, __LINE__, "Can't connect to vector %d\n", MAXvInterruptVector + card); - return (ERROR); - } - - status = devEnableInterruptLevel(OMS_INTERRUPT_TYPE, - omsInterruptLevel); - if (!RTN_SUCCESS(status)) - { - errPrintf(status, __FILE__, __LINE__, "Can't enable enterrupt level %d\n", omsInterruptLevel); - return (ERROR); - } - -#endif - - /* Setup card for interrupt-on-done */ - status1_irq.All = 0; - status1_irq.Bits.done = 0xFF; - status1_irq.Bits.cmndError = 1; - - pmotor->status1_irq_enable.All = status1_irq.All; /* Enable interrupts. */ - pmotor->status2_irq_enable = 0x0; - return (OK); -} - -/*****************************************************/ -/* initialize all software and hardware */ -/* motor_init() */ -/*****************************************************/ -static int motor_init() -{ - struct mess_info *motor_info; - volatile struct controller *pmotorState; - volatile struct MAXv_motor *pmotor; - struct MAXvController *pvtdata; - long status=0; - int card_index, motor_index, itera; - char axis_pos[MAX_IDENT_LEN], encoder_pos[MAX_IDENT_LEN], **strptr; - char *tok_save, *pos_ptr; - int total_encoders = 0, total_axis = 0, total_pidcnt = 0; - volatile void *localaddr=0; - void *probeAddr; - - tok_save = NULL; - - /* Check for setup */ - if (MAXv_num_cards <= 0) - { - Debug(1, "\nmotor_init: MAXv driver disabled\nMAXvSetup() is missing from startup script.\n"); - return(ERROR); - } - - /* allocate space for total number of motors */ - motor_state = (struct controller **) malloc(MAXv_num_cards * - sizeof(struct controller *)); - - /* allocate structure space for each motor present */ - - total_cards = MAXv_num_cards; - - if (epicsAtExit(MAXv_reset, NULL) == ERROR) - Debug(1, "MAXv motor_init: MAXv_reset disabled\n"); - - for (card_index = 0; card_index < MAXv_num_cards; card_index++) - { - epicsInt8 *startAddr; - epicsInt8 *endAddr; - bool wdtrip; - int rtn_code; - - Debug(2, "motor_init: card %d\n", card_index); - - probeAddr = MAXv_addrs + (card_index * MAXv_brd_size); - startAddr = (epicsInt8 *) probeAddr; - endAddr = startAddr + MAXv_brd_size; - - Debug(9, "motor_init: devNoResponseProbe() on addr %p\n", probeAddr); - /* Scan memory space to assure card id */ -#ifdef USE_DEVLIB - do - { - status = devNoResponseProbe(MAXv_ADDRS_TYPE, (unsigned int) startAddr, 2); - startAddr += (MAXv_brd_size / 10); - } while (PROBE_SUCCESS(status) && startAddr < endAddr); -#endif - if (!PROBE_SUCCESS(status)) - { - Debug(3, "motor_init: Card NOT found!\n"); - motor_state[card_index] = (struct controller *) NULL; - goto loopend; - } - -#ifdef USE_DEVLIB - status = devRegisterAddress(__FILE__, MAXv_ADDRS_TYPE, - (size_t) probeAddr, MAXv_brd_size, - (volatile void **) &localaddr); - Debug(9, "motor_init: devRegisterAddress() status = %d\n", (int) status); - if (!RTN_SUCCESS(status)) - { - errPrintf(status, __FILE__, __LINE__, "Can't register address 0x%x\n", - (unsigned int) probeAddr); - motor_state[card_index] = (struct controller *) NULL; - goto loopend; - } -#endif - - Debug(9, "motor_init: localaddr = %p\n", localaddr); - pmotor = (struct MAXv_motor *) localaddr; - - if (pmotor->firmware_status.Bits.running == 0) - { - errlogPrintf(norunmsg, card_index, (unsigned int) pmotor->firmware_status.All); - motor_state[card_index] = (struct controller *) NULL; - goto loopend; - } - - Debug(9, "motor_init: malloc'ing motor_state\n"); - motor_state[card_index] = (struct controller *) malloc(sizeof(struct controller)); - pmotorState = motor_state[card_index]; - pmotorState->localaddr = (char *) localaddr; - pmotorState->motor_in_motion = 0; - pmotorState->cmnd_response = false; - - pvtdata = (struct MAXvController *) malloc(sizeof(struct MAXvController)); - pvtdata->message_mutex = epicsMutexMustCreate(); - pmotorState->DevicePrivate = pvtdata; - - if (MAXvInterruptVector == 0) - pmotor->IACK_vector = 0; - else - pmotor->IACK_vector = MAXvInterruptVector + card_index; - - pmotor->status1_flag.All = 0xFFFFFFFF; - pmotor->status2_flag = 0xFFFFFFFF; - /* Disable all interrupts */ - pmotor->status1_irq_enable.All = 0; - pmotor->status2_irq_enable = 0; - - send_mess(card_index, ERROR_CLEAR, (char*) NULL); - send_mess(card_index, STOP_ALL, (char*) NULL); - - rtn_code = send_recv_mess(card_index, GET_IDENT, (char* ) NULL, (char *) pmotorState->ident, 1); - if (rtn_code != 0) - { - errlogPrintf("\n***MAXv card #%d Disabled*** not responding to commands!\n\n", card_index); - motor_state[card_index] = (struct controller *) NULL; - goto loopend; - } - Debug(3, "Identification = %s\n", pmotorState->ident); - - /* Save firmware version. */ - pos_ptr = strchr((char *)pmotorState->ident, ':'); - sscanf(++pos_ptr, "%f", &pvtdata->fwver); - - wdtrip = false; - - if (pvtdata->fwver >= 1.33) - { - send_recv_mess(card_index, "#WS", (char *) NULL, axis_pos, 1); - if (strcmp(axis_pos, "=0") != 0) - { - errlogPrintf(wdctrmsg, card_index, axis_pos); - epicsThreadSleep(2.0); - motor_state[card_index] = (struct controller *) NULL; - wdtrip = true; - } - } - - if (wdtrip == false) - { - send_mess(card_index, initstring[card_index], (char*) NULL); - - send_recv_mess(card_index, ALL_POS, (char *) NULL, axis_pos, 1); - - for (total_axis = 0, pos_ptr = epicsStrtok_r(axis_pos, ",", &tok_save); - pos_ptr; pos_ptr = epicsStrtok_r(NULL, ",", &tok_save), total_axis++) - { - pmotorState->motor_info[total_axis].motor_motion = NULL; - pmotorState->motor_info[total_axis].status.All = 0; - } - - Debug(3, "motor_init: Total axis = %d\n", total_axis); - pmotorState->total_axis = total_axis; - - for (total_encoders = total_pidcnt = 0, motor_index = 0; motor_index < total_axis; motor_index++) - { - motor_info = (struct mess_info *) &pmotorState->motor_info[motor_index]; - STATUS1 flag1; - - /* Test if motor has an encoder. */ - send_mess(card_index, ENCODER_QUERY, (char *) MAXv_axis[motor_index]); - while (!pmotor->status1_flag.Bits.done) /* Wait for command to complete. */ - epicsThreadSleep(quantum); - - if (pmotor->status1_flag.Bits.cmndError) - { - Debug(2, "motor_init: No encoder on axis %d\n", motor_index); - motor_info->encoder_present = NO; - flag1.All = pmotor->status1_flag.All; /* Clear command error. */ - pmotor->status1_flag.All = flag1.All; - } - else - { - total_encoders++; - motor_info->encoder_present = YES; - recv_mess(card_index, encoder_pos, 1); - } - - /* Test if motor has PID parameters. */ - send_mess(card_index, PID_QUERY, (char *) MAXv_axis[motor_index]); - while (!pmotor->status1_flag.Bits.done) /* Wait for command to complete. */ - epicsThreadSleep(quantum); - if (pmotor->status1_flag.Bits.cmndError) - { - Debug(2, "motor_init: No PID parameters on axis %d\n", motor_index); - motor_info->pid_present = NO; - flag1.All = pmotor->status1_flag.All; /* Clear command error. */ - pmotor->status1_flag.All = flag1.All; - } - else - { - total_pidcnt++; - motor_info->pid_present = YES; - recv_mess(card_index, encoder_pos, FLUSH); /* Flush response. */ - } - - // Set motor type. - if (motor_info->pid_present == YES) - pvtdata->typeID[motor_index] = PSM; - else if (motor_info->encoder_present == YES) - pvtdata->typeID[motor_index] = PSE; - else - pvtdata->typeID[motor_index] = PSO; - - if (pvtdata->fwver >= 1.30) - { - send_recv_mess(card_index, "LM?", (char *) MAXv_axis[motor_index], axis_pos, 1); - if (strcmp(axis_pos, "=f") == 0) /* If limit mode is set to "Off". */ - send_mess(card_index, "LMH", (char *) MAXv_axis[motor_index]); /* Set limit mode to "Hard". */ - } - } - - /* Enable interrupt-when-done if selected */ - if (MAXvInterruptVector) - { - if (motorIsrSetup(card_index) == ERROR) - errMessage(-1, "Interrupts Disabled!\n"); - } - - for (motor_index = 0; motor_index < total_axis; motor_index++) - { - motor_info = (struct mess_info *) &pmotorState->motor_info[motor_index]; - - motor_info->status.All = 0; - motor_info->no_motion_count = 0; - motor_info->encoder_position = 0; - motor_info->position = 0; - - if (motor_info->encoder_present == YES) - motor_info->status.Bits.EA_PRESENT = 1; - if (motor_info->pid_present == YES) - motor_info->status.Bits.GAIN_SUPPORT = 1; - - set_status(card_index, motor_index); - /* Is this needed??? */ - send_recv_mess(card_index, DONE_QUERY, (char *) MAXv_axis[motor_index], axis_pos, 1); - } - - Debug(2, "motor_init: Init Address=%p\n", localaddr); - Debug(3, "motor_init: Total encoders = %d\n", total_encoders); - Debug(3, "motor_init: Total with PID = %d\n", total_pidcnt); - } -loopend:; - } - - any_motor_in_motion = 0; - - mess_queue.head = (struct mess_node *) NULL; - mess_queue.tail = (struct mess_node *) NULL; - - free_list.head = (struct mess_node *) NULL; - free_list.tail = (struct mess_node *) NULL; - - Debug(3, "Motors initialized\n"); - - epicsThreadCreate((char *) "MAXv_motor", epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackMedium), - (EPICSTHREADFUNC) motor_task, (void *) &targs); - - Debug(3, "Started motor_task\n"); - - /* Deallocate memory for configuration strings. */ - for (itera = 0, strptr = &initstring[0]; itera < MAXv_num_cards; itera++, strptr++) - free(*strptr); - free(initstring); - initstring = NULL; - - return(0); -} - - -/* Disables interrupts. Called on CTL X reboot. */ - -static void MAXv_reset(void *arg) -{ - short card; - volatile struct MAXv_motor *pmotor; - - for (card = 0; card < total_cards; card++) - { - if (motor_state[card] != NULL) - { - pmotor = (struct MAXv_motor *) motor_state[card]->localaddr; - pmotor->status1_irq_enable.All = 0; - } - } -} - -extern "C" -{ - -// Oms Setup arguments - static const iocshArg setupArg0 = {"Max. controller count", iocshArgInt}; - static const iocshArg setupArg1 = {"VME address type", iocshArgInt}; - static const iocshArg setupArg2 = {"Base Address on 4K (0x1000) boundary", iocshArgInt}; - static const iocshArg setupArg3 = {"noninterrupting(0), valid vectors(64-255)", iocshArgInt}; - static const iocshArg setupArg4 = {"interrupt level (1-6)", iocshArgInt}; - static const iocshArg setupArg5 = {"polling rate (Hz)", iocshArgInt}; -// Oms Config arguments - static const iocshArg configArg0 = {"Card # being configured", iocshArgInt}; - static const iocshArg configArg1 = {"configuration string", iocshArgString}; - static const iocshArg configArg2 = {"absolute encoder flags (0/1 - incremental/absolute, 0x07 -> ZYX)", iocshArgInt}; - static const iocshArg configArg3 = {"grey code flags (0/1 - yes/no, 0x12 -> UY)", iocshArgInt}; - - static const iocshArg * const OmsSetupArgs[6] = {&setupArg0, &setupArg1, - &setupArg2, &setupArg3, &setupArg4, &setupArg5}; - static const iocshArg * const OmsConfigArgs[4] = {&configArg0, &configArg1, &configArg2, &configArg3}; - - static const iocshFuncDef setupMAXv = {"MAXvSetup", 6, OmsSetupArgs}; - - static const iocshFuncDef configMAXv = {"MAXvConfig", 4, OmsConfigArgs}; - - static void setupMAXvCallFunc(const iocshArgBuf *args) - { - MAXvSetup(args[0].ival, args[1].ival, args[2].ival, args[3].ival, args[4].ival, args[5].ival); - } - - static void configMAXvCallFunc(const iocshArgBuf *args) - { - MAXvConfig(args[0].ival, args[1].sval, args[2].ival, args[3].ival); - } - - static void OmsMAXvRegister(void) - { - iocshRegister(&setupMAXv, setupMAXvCallFunc); - iocshRegister(&configMAXv, configMAXvCallFunc); - } - - epicsExportRegistrar(OmsMAXvRegister); - -} // extern "C" diff --git a/motorApp/OmsSrc/drvMAXv.h b/motorApp/OmsSrc/drvMAXv.h deleted file mode 100644 index db648d02..00000000 --- a/motorApp/OmsSrc/drvMAXv.h +++ /dev/null @@ -1,196 +0,0 @@ -/* -FILENAME... drvMAXv.h -USAGE... OMS driver level "include" information that is specific to OMS - model MAXv. - -*/ - -/* - * Original Author: Ron Sluiter - * Date: 04/05/04 - * Current Author: Ron Sluiter - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - * 01 04-05-04 rls Copied for drvOms58.h - * 02 10-26-11 rls motor_init() sets motor typeID as boot-up. Used by device - * support to allow MRES and ERES to be opposite sign. - * - */ - -#ifndef INCdrvMAXvh -#define INCdrvMAXvh 1 - -#include "drvOmsCom.h" -#include - -/* - * MAXv default profile - */ - -#define MAXv_NUM_CARDS 15 - -#define BUFFER_SIZE 1024 - - -enum MotorTypes {PSO, // Stepper; w/o encoder - PSE, // Stepper; with encoder - PSM}; // Servo - -struct MAXvController -{ - MotorTypes typeID[8]; - float fwver; /* firmware version */ - epicsMutexId message_mutex; -}; - - -/* MAXv DUAL-PORT MEMORY MAP */ - - -/* Limit Switch Status - Offset = 0x40 */ -typedef union -{ - epicsUInt32 All; - struct - { - unsigned int s_minus :1; - unsigned int r_minus :1; - unsigned int v_minus :1; - unsigned int u_minus :1; - unsigned int t_minus :1; - unsigned int z_minus :1; - unsigned int y_minus :1; - unsigned int x_minus :1; - unsigned int s_plus :1; - unsigned int r_plus :1; - unsigned int v_plus :1; - unsigned int u_plus :1; - unsigned int t_plus :1; - unsigned int z_plus :1; - unsigned int y_plus :1; - unsigned int x_plus :1; - } Bits; -} LIMIT_SWITCH; - -/* Home Switch Status - Offset = 0x44 */ -typedef union -{ - epicsUInt32 All; - struct - { - unsigned int home_s :1; /* status of S axis */ - unsigned int home_r :1; /* status of R axis */ - unsigned int home_v :1; /* status of V axis */ - unsigned int home_u :1; /* status of U axis */ - unsigned int home_t :1; /* status of T axis */ - unsigned int home_z :1; /* status of Z axis */ - unsigned int home_y :1; /* status of Y axis */ - unsigned int home_x :1; /* status of X axis */ - } Bits; -} HOME_SWITCH; - -/* Firmware status - Offset = 0x48 */ -typedef union -{ - epicsUInt32 All; - struct - { - unsigned int na19 :13; /* N/A bits 19-31 */ - unsigned int factoryparm_loaded :1; - unsigned int altparm_loaded :1; - unsigned int defaultparm_loaded :1; - unsigned int altprgm_err :1; - unsigned int altparm_chksum_err :1; - unsigned int prgm_err :1; - unsigned int parm_chksum_err :1; - unsigned int na10 :2; /* N/A bits 10-11 */ - unsigned int program_error :1; - unsigned int flash_chksum_err :1; - unsigned int na3 :5; /* N/A bits 3-7 */ - unsigned int running :1; - unsigned int initializing :1; - unsigned int not_downloaded :1; - } Bits; -} FIRMWARE_STATUS; - - -/* Status#1 - Offset = 0xFC0 */ -typedef union -{ - epicsUInt32 All; - struct - { - unsigned int na3 :5; /* N/A bits 27-31. */ - unsigned int data_avail :1; - unsigned int text_response :1; - unsigned int cmndError :1; /* Command error dectect */ - unsigned int slip :8; - unsigned int overtravel :8; - unsigned int done :8; - } Bits; -} STATUS1; - - -/* OMS VME dual port memory map */ -struct MAXv_motor -{ - epicsUInt32 cmndPos[8]; - epicsUInt32 encPos[8]; - LIMIT_SWITCH limit_switch; - HOME_SWITCH home_switch; - FIRMWARE_STATUS firmware_status; - epicsUInt32 direct_cmnd_mbox; - epicsUInt32 position_req_mbox; - epicsUInt32 coherent_cmndPos[8]; - epicsUInt32 coherent_encPos[8]; - epicsUInt32 msg_semaphore; - epicsUInt32 queue_flush_mbox; - epicsUInt32 gpio; - epicsUInt32 naA0[2]; /* N/A byte offset 0xA0 - 0xA7. */ - epicsUInt32 absPos[8]; - epicsUInt32 naC8[9]; /* N/A byte offset 0xC8 - 0xEB. */ - epicsUInt32 flash_pgm_ptr; - epicsUInt32 outPutIndex; - epicsUInt32 outGetIndex; - epicsUInt32 inPutIndex; - epicsUInt32 inGetIndex; - epicsUInt8 outBuffer[BUFFER_SIZE]; - epicsUInt8 inBuffer[BUFFER_SIZE]; - epicsUInt8 utility[BUFFER_SIZE]; - epicsUInt32 naD00[176]; /* N/A byte offset 0xD00 - 0xFBF. */ - STATUS1 status1_flag; - STATUS1 status1_irq_enable; - epicsUInt32 status2_flag; - epicsUInt32 status2_irq_enable; - epicsUInt32 IACK_vector; - epicsUInt32 config_switch; - epicsUInt32 AM_register; - epicsUInt32 naFDC[7]; - epicsUInt32 FIFO_status_cntrl; - epicsUInt32 FIFO_date; - -}; - -#endif /* INCdrvMAXvh */ diff --git a/motorApp/OmsSrc/drvOms.cc b/motorApp/OmsSrc/drvOms.cc deleted file mode 100644 index 47e4494f..00000000 --- a/motorApp/OmsSrc/drvOms.cc +++ /dev/null @@ -1,1277 +0,0 @@ -/* -FILENAME... drvOms.cc -USAGE... Driver level support for OMS models VME8, VME44, VS4 and VX2. - -*/ - -/* - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * - * NOTES - * ----- - * Verified with firmware: - * - VME44 ver 1.97-4E - * - VME8 ver 1.97-8 - * ver 2.16-8 - * - VS4-040 ver 1.04 - * - VX2-006 ver 1.05 (1.04 has control register initialization problem) - * - * - * Modification Log: - * ----------------- - * .00 02-22-02 rls - "total_cards" changed from total detected to total - * cards that "memory is allocated for". This allows - * boards after the "hole" to work. - * .01 06-05-03 rls - Convert to R3.14.x. - * .02 06-05-03 rls - extended device directive support to PREM and POST. - * .03 10-23-03 rls - VX2 spurious interrupt fix; support transmit buffer - * empty interrupt in omsPut() and motorIsr(). - * .04 10-28-03 rls - moved OMS specific "irqdatastr" from motordrvCom.h - * drvOms.h and DevicePrivate. - * - removed "max_io_tries" from timeout calculations. - * - changed omsGet() timeout argument to type bool. - * - changed recv_rng and send_rng from C to C++ interface. - * .05 12-03-03 rls - update rate bug fix. - * .06 12-12-03 rls - Converted MSTA #define's to bit field. - * - Two lines of code must be selected based on either - * Tornado 2.0.2 (default) or Tornado 2.2. If Tornado - * 2.2 is selected, EPICS base patches must be applied as - * described in; - * http://www.aps.anl.gov/upd/people/sluiter/epics/motor/R5-2/Problems.html - * .07 02-03-04 rls - Eliminate erroneous "Motor motion timeout ERROR". - * .08 03-02-04 rls - Reduce omsGet() timeout from 1sec. to 250msec. - * .09 09-20-04 rls - support for 32axes/controller. - * .10 12-06-04 rls - Windows compiler support. - * - eliminate calls to devConnectInterrupt() due to C++ - * problems with devLib.h; i.e. "sorry, not implemented: - * `tree_list' not supported..." compiler error message. - * .11 03-23-05 rls - Make OSI. - * .12 05-02-05 rls - Bug fix for stale data delay; set delay = 10ms. - * .13 03-14-08 rls - 64-bit compatiability. - * - changed IRS to task comm. mechanism from epicsRingPointer - * to epicsRingByte. - * .14 06-18-09 rls - Make omsSetup() error messages more prominent. - * .15 03-15-10 rls - sprintf() not callable from any OS ISR. - * .16 04-12-10 rls - enable interrupts after encoder check in motor_init() so - * user does not see "motorIsr: command error" messages at - * iocInit time. - * .17 07-26-12 rls - Added reboot flag to IRQ control register. Driver - * sets IRQ_RESET_ID bit on; set_status() and send_mess() - * read IRQ register and disable board if flag is off. - * .18 11-15-03 rls - Added bus flushing read on exit from ISR to prevent - * "out of order transactions". - */ - -/*========================stepper motor driver ======================== - - function: - Allow users to queue messages to axis on a OMS stepper - motor controller board. Each axis of every board available can - be accessed independantly. - - public functions: - motor_init() - Initialize the driver task and structures for all - boards available for the system. - private functions: - send_mess() - Send a message to the OMS board. - recv_mess() - Receive a message from the OMS board. - - -========================stepper motor driver ========================*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "motor.h" -#include "drvOms.h" -#include "epicsExport.h" - -/* Define for return test on devNoResponseProbe() */ -#define PROBE_SUCCESS(STATUS) ((STATUS)==S_dev_addressOverlap) - -#define CMD_CLEAR '\030' /* Control-X, clears command errors only */ - -#define ALL_INFO "QA RP RE EA" /* jps: move QA to top. */ -#define AXIS_INFO "QA RP" /* jps: move QA to top. */ -#define ENCODER_QUERY "EA" -#define DONE_QUERY "RA" - -/*----------------debugging-----------------*/ -volatile int drvOMSdebug = 0; -extern "C" {epicsExportAddress(int, drvOMSdebug);} -static inline void Debug(int level, const char *format, ...) { - #ifdef DEBUG - if (level < drvOMSdebug) { - va_list pVar; - va_start(pVar, format); - vprintf(format, pVar); - va_end(pVar); - } - #endif -} - -/* Global data. */ -int oms44_num_cards = 0; - -/* Local data required for every driver; see "motordrvComCode.h" */ -#include "motordrvComCode.h" - - -/* --- Local data common to all OMS drivers. --- */ -static char *oms_addrs = 0x0; -static volatile unsigned omsInterruptVector = 0; -static volatile epicsUInt8 omsInterruptLevel = OMS_INT_LEVEL; -static volatile int motionTO = 10; -static char *oms_axis[] = {"X", "Y", "Z", "T", "U", "V", "R", "S"}; -static double quantum; - -/*----------------functions-----------------*/ - -/* Common local function declarations. */ -static long report(int); -static long init(); -static void query_done(int, int, struct mess_node *); -static int set_status(int, int); -static RTN_STATUS send_mess(int, char const *, char *); -static int recv_mess(int, char *, int); -static void motorIsr(int); -static int motor_init(); -static void oms_reset(void *); - -static int omsGet(int card, char *pcom, bool timeout); -static RTN_STATUS omsPut(int card, char *pcom); -static int omsError(int card); -static int motorIsrEnable(int card); -static void motorIsrDisable(int card); - -struct driver_table oms_access = -{ - NULL, - motor_send, - motor_free, - motor_card_info, - motor_axis_info, - &mess_queue, - &queue_lock, - &free_list, - &freelist_lock, - &motor_sem, - &motor_state, - &total_cards, - &any_motor_in_motion, - send_mess, - recv_mess, - set_status, - query_done, - NULL, - &initialized, - oms_axis -}; - -struct drvOms_drvet -{ - long number; - long (*report) (int); - long (*init) (void); -} drvOms = {2, report, init}; - -extern "C" {epicsExportAddress(drvet, drvOms);} - -static struct thread_args targs = {SCAN_RATE, &oms_access, 0.010}; -static char rebootmsg[] = "\n\n*** OMS card #%d Disabled *** Reboot Detected.\n\n"; - -/*----------------functions-----------------*/ - -static long report(int level) -{ - int card; - - if (oms44_num_cards <= 0) - printf(" No VME8/44 controllers configured.\n"); - else - { - for (card = 0; card < oms44_num_cards; card++) - if (motor_state[card]) - printf(" Oms VME8/44 motor card %d @ %p, id: %s \n", card, - motor_state[card]->localaddr, motor_state[card]->ident); - } - return(0); -} - -static long init() -{ - initialized = true; /* Indicate that driver is initialized. */ - (void) motor_init(); - return((long) 0); -} - - -static void query_done(int card, int axis, struct mess_node *nodeptr) -{ - char buffer[40]; - - send_mess(card, DONE_QUERY, oms_axis[axis]); - recv_mess(card, buffer, 1); - - if (nodeptr->status.Bits.RA_PROBLEM) - send_mess(card, AXIS_STOP, oms_axis[axis]); -} - - -static int set_status(int card, int signal) -{ - struct mess_info *motor_info; - struct mess_node *nodeptr; - char *p, *tok_save; - struct axis_status *ax_stat; - struct encoder_status *en_stat; - char q_buf[50], outbuf[50]; - int index, motorData; - int rtn_state; - bool ls_active = false; - msta_field status; - struct controller *pmotorState; - struct vmex_motor *pmotor; - - if ((pmotorState = motor_state[card]) == NULL || - (pmotor = (struct vmex_motor *) pmotorState->localaddr) == NULL) - return(rtn_state = 1); /* End move. */ - - motor_info = &(pmotorState->motor_info[signal]); - nodeptr = motor_info->motor_motion; - status.All = motor_info->status.All; - - if ((pmotor->control & IRQ_RESET_ID) != 0x01) /* Test if board has rebooted. */ - { - errlogPrintf(rebootmsg, card); - status.Bits.RA_PROBLEM = 1; - motor_info->status.All = status.All; - /* Disable board. */ - motor_state[card] = (struct controller *) NULL; - return(rtn_state = 1); /* End move. */ - } - - if (motor_state[card]->motor_info[signal].encoder_present == YES) - { - /* get 4 peices of info from axis */ - send_mess(card, ALL_INFO, oms_axis[signal]); - recv_mess(card, q_buf, 4); - } - else - { - send_mess(card, AXIS_INFO, oms_axis[signal]); - recv_mess(card, q_buf, 2); - } - - Debug(5, "info = (%s)\n", q_buf); - - for (index = 0, p = epicsStrtok_r(q_buf, ",", &tok_save); p; - p = epicsStrtok_r(NULL, ",", &tok_save), index++) - { - switch (index) - { - case 0: /* axis status */ - ax_stat = (struct axis_status *) p; - - status.Bits.RA_DIRECTION = (ax_stat->direction == 'P') ? 1 : 0; - status.Bits.RA_DONE = (ax_stat->done == 'D') ? 1 : 0; - status.Bits.RA_HOME = (ax_stat->home == 'H') ? 1 : 0; - - if (ax_stat->overtravel == 'L') - { - ls_active = true; - if (status.Bits.RA_DIRECTION) - status.Bits.RA_PLUS_LS = 1; - else - status.Bits.RA_MINUS_LS = 1; - } - else - { - ls_active = false; - status.Bits.RA_PLUS_LS = 0; - status.Bits.RA_MINUS_LS = 0; - } - - break; - case 1: /* motor pulse count (position) */ - sscanf(p, "%index", &motorData); - - if (motorData == motor_info->position) - { - if (nodeptr != 0) /* Increment counter only if motor is moving. */ - motor_info->no_motion_count++; - } - else - { - motor_info->no_motion_count = 0; - motor_info->position = motorData; - } - - if (motor_info->no_motion_count > motionTO) - { - status.Bits.RA_PROBLEM = 1; - send_mess(card, AXIS_STOP, oms_axis[signal]); - motor_info->no_motion_count = 0; - errlogSevPrintf(errlogMinor, "Motor motion timeout ERROR on card: %d, signal: %d\n", - card, signal); - } - else - status.Bits.RA_PROBLEM = 0; - - break; - case 2: /* encoder pulse count (position) */ - { - int temp; - - sscanf(p, "%index", &temp); - motor_info->encoder_position = (epicsInt32) temp; - } - break; - case 3: /* encoder status */ - en_stat = (struct encoder_status *) p; - status.Bits.EA_SLIP = (en_stat->slip_enable == 'E') ? 1 : 0; - status.Bits.EA_POSITION = (en_stat->pos_enable == 'E') ? 1 : 0; - status.Bits.EA_SLIP_STALL = (en_stat->slip_detect == 'S') ? 1 : 0; - status.Bits.EA_HOME = (en_stat->axis_home == 'H') ? 1 : 0; - break; - default: - break; - } - } - - /* - * jps: Velocity should be set based on the actual velocity returned from - * the 'RV' command (See drvOms58.c). But the polling task does not have - * time to request additional information so the velocity is set to - * indicate moving or not-moving. - */ - if (status.Bits.RA_DONE) - motor_info->velocity = 0; - else - motor_info->velocity = 1; - - if (!(status.Bits.RA_DIRECTION)) - motor_info->velocity *= -1; - - rtn_state = (!motor_info->no_motion_count || ls_active == true || - status.Bits.RA_DONE | status.Bits.RA_PROBLEM) ? 1 : 0; - - /* Test for post-move string. */ - if ((status.Bits.RA_DONE || ls_active == true) && (nodeptr != 0) && - (nodeptr->postmsgptr != 0)) - { - char buffer[40]; - - /* Test for a "device directive" in the POST string. */ - if (nodeptr->postmsgptr[0] == '@') - { - bool errind = false; - char *end = strchr(&nodeptr->postmsgptr[1], '@'); - if (end == NULL) - errind = true; - else - { - DBADDR addr; - char *start, *tail; - int size = (end - &nodeptr->postmsgptr[0]) + 1; - - /* Copy device directive to buffer. */ - strncpy(buffer, nodeptr->postmsgptr, size); - buffer[size] = (char) NULL; - - if (strncmp(buffer, "@PUT(", 5) != 0) - goto errorexit; - - /* Point "start" to PV name argument. */ - tail = NULL; - start = epicsStrtok_r(&buffer[5], ",", &tail); - if (tail == NULL) - goto errorexit; - - if (dbNameToAddr(start, &addr)) /* Get address of PV. */ - { - errPrintf(-1, __FILE__, __LINE__, "Invalid PV name: %s", start); - goto errorexit; - } - - /* Point "start" to PV value argument. */ - start = epicsStrtok_r(NULL, ")", &tail); - if (dbPutField(&addr, DBR_STRING, start, 1L)) - { - errPrintf(-1, __FILE__, __LINE__, "invalid value: %s", start); - goto errorexit; - } - } - - if (errind == true) -errorexit: errMessage(-1, "Invalid device directive"); - end++; - strcpy(buffer, end); - } - else - strcpy(buffer, nodeptr->postmsgptr); - - strcpy(outbuf, buffer); - send_mess(card, outbuf, oms_axis[signal]); - nodeptr->postmsgptr = NULL; - } - - motor_info->status.All = status.All; /* Update status from local copy. */ - return(rtn_state); -} - - -/*****************************************************/ -/* send a message to the OMS board */ -/* send_mess() */ -/*****************************************************/ -static RTN_STATUS send_mess(int card, char const *com, char *name) -{ - char outbuf[MAX_MSG_SIZE]; - RTN_STATUS return_code; - volatile struct controller *pmotorState; - volatile struct vmex_motor *pmotor; - - if (strlen(com) > MAX_MSG_SIZE) - { - errlogPrintf("drvOms.cc:send_mess(); message size violation.\n"); - return(ERROR); - } - - /* Check that card exists */ - if ((pmotorState = motor_state[card]) == NULL) - { - errlogPrintf("drvOms.cc:send_mess() - invalid card #%d\n", card); - return(ERROR); - } - - pmotor = (struct vmex_motor *) pmotorState->localaddr; - - if ((pmotor->control & IRQ_RESET_ID) != 0x01) /* Test if board has rebooted. */ - { - errlogPrintf(rebootmsg, card); - /* Disable board. */ - motor_state[card] = (struct controller *) NULL; - return(ERROR); - } - - /* Check/Clear command errors */ - omsError(card); - - /* Flush receive buffer */ - recv_mess(card, (char *) NULL, -1); - - if (name == NULL) - strcpy(outbuf, com); - else - { - strcpy(outbuf, "A"); - strcat(outbuf, name); - strcat(outbuf, " "); - strcat(outbuf, com); - } - strcat(outbuf, "\n"); /* Add the command line terminator. */ - - Debug(9, "send_mess: ready to send message.\n"); - - return_code = omsPut(card, outbuf); - - if (return_code == OK) - { - Debug(4, "sent message: (%s)\n", outbuf); - } - else - { - Debug(4, "unable to send message (%s)\n", outbuf); - } - return(return_code); -} - - -/* - * FUNCTION... recv_mess(int card, char *com, int amount) - * - * INPUT ARGUMENTS... - * card - controller card # (0,1,...). - * *com - caller's response buffer. - * amount | -1 = flush controller's output buffer. - * | >= 1 = the # of command responses to retrieve into caller's - * response buffer. - * - * LOGIC... - * IF controller card does not exist. - * ERROR RETURN. - * ENDIF - * IF "amount" indicates buffer flush. - * WHILE characters left in input buffer. - * Call omsGet(). - * ENDWHILE - * ENDIF - * - * FOR each message requested (i.e. "amount"). - * Initialize head and tail pointers. - * Initialize retry counter and state indicator. - * WHILE retry count not exhausted, AND, state indicator is NOT at END. - * IF characters left in controller's input buffer. - * Process input character. - * ELSE IF command error occured - call omsError(). - * ERROR RETURN. - * ENDIF - * ENDWHILE - * IF retry count exhausted. - * Terminate receive buffer. - * ERROR RETURN. - * ENDIF - * Terminate command response. - * ENDFOR - * - * IF commands processed. - * Terminate response buffer. - * ELSE - * Clear response buffer. - * ENDIF - * NORMAL RETURN. - */ - -static int recv_mess(int card, char *com, int amount) -{ - int i, trys; - char junk; - char inchar; - int piece, head_size, tail_size; - - inchar = '\0'; - - /* Check that card exists */ - if (card >= total_cards) - { - Debug(1, "recv_mess - invalid card #%d\n", card); - return(-1); - } - - if (amount == -1) - { - /* Process request to flush receive queue */ - Debug(7, "recv flush -------------"); - while (omsGet(card, &junk, false)) - { - Debug(7, "%inchar", junk); - } - Debug(7, " -------------"); - return(0); - } - - for (i = 0; amount > 0; amount--) - { - Debug(7, "-------------"); - head_size = 0; - tail_size = 0; - - for (piece = 0, trys = 0; piece < 3 && trys < 3; trys++) - { - if (omsGet(card, &inchar, true)) - { - Debug(7, "%02x", inchar); - - switch (piece) - { - case 0: /* header */ - if (inchar == '\n' || inchar == '\r') - head_size++; - else - { - piece++; - com[i++] = inchar; - } - break; - case 1: /* body */ - if (inchar == '\n' || inchar == '\r') - { - piece++; - tail_size++; - } - else - com[i++] = inchar; - break; - - case 2: /* trailer */ - tail_size++; - if (tail_size >= head_size) - piece++; - break; - } - - trys = 0; - } - else if (omsError(card)) - /* Command error detected - abort recv */ - return(-1); - } - Debug(7, "-------------\n"); - if (trys >= 3) - { - Debug(1, "Timeout occurred in recv_mess\n"); - com[i] = '\0'; - return(-1); - } - com[i++] = ','; - } - - if (i > 0) - com[i - 1] = '\0'; - else - com[i] = '\0'; - - Debug(4, "recv_mess: card %d, msg: (%s)\n", card, com); - return(0); -} - - -/*****************************************************/ -/* Get next character from OMS input buffer */ -/* omsGet() */ -/*****************************************************/ -static int omsGet(int card, char *pchar, bool timeout) -{ - volatile struct controller *pmotorState; - volatile struct vmex_motor *pmotor; - struct irqdatastr *irqdata; - int getCnt = 0; - int retry = 0; - - pmotorState = motor_state[card]; - irqdata = (struct irqdatastr *) pmotorState->DevicePrivate; - - if (irqdata->irqEnable) - { - /* Get character from isr - if available */ - while (epicsRingBytesIsEmpty(irqdata->recv_rng) && timeout == true && retry < 5) - { - irqdata->recv_sem->wait(0.05); /* Wait 250ms for character */ - retry ++; - } - if (!epicsRingBytesIsEmpty(irqdata->recv_rng)) - { - epicsRingBytesGet(irqdata->recv_rng, pchar, 1); - getCnt = 1; - } - } - else - { - int maxtrys = (int) (0.250 / quantum); /* Wait 250ms for character */ - - /* Direct read from card */ - pmotor = (struct vmex_motor *) pmotorState->localaddr; - - if (timeout == true) - while (retry++ < maxtrys && !(pmotor->status & STAT_INPUT_BUF_FULL)) - { - Debug(5, "omsGet: wait count = %d\n", retry); - epicsThreadSleep(quantum); - } - - if (pmotor->status & STAT_INPUT_BUF_FULL) - { - getCnt++; - *pchar = pmotor->data; - } - } - return(getCnt); -} - -/*****************************************************/ -/* Send Message to OMS */ -/* omsPut() */ -/*****************************************************/ -static RTN_STATUS omsPut(int card, char *pmess) -{ - volatile struct controller *pmotorState; - volatile struct vmex_motor *pmotor; - struct irqdatastr *irqdata; - int key, msgsize; - - if ((pmotorState = motor_state[card]) == NULL) - return(ERROR); - irqdata = (struct irqdatastr *) pmotorState->DevicePrivate; - pmotor = (struct vmex_motor *) pmotorState->localaddr; - msgsize = strlen(pmess); - - if (irqdata->irqEnable) - { - /* Put string into isr transmitt buffer */ - if (epicsRingBytesPut(irqdata->send_rng, pmess, msgsize) != msgsize) - { - errlogPrintf("omsPut: card %d send ring full!\n", card); - return(ERROR); - } - - /* Turn-on transmit buffer interrupt */ - key = epicsInterruptLock(); - pmotor->control |= IRQ_TRANS_BUF; - epicsInterruptUnlock(key); - } - else - { - char *putptr; - - /* Send next message */ - for (putptr = pmess; *putptr != '\0'; putptr++) - { - int trys = 0; - int maxtrys = (int) (0.01 / quantum); - - while (!(pmotor->status & STAT_TRANS_BUF_EMPTY)) - { - if (trys > maxtrys) /* Set timeout to 0.01 sec. */ - { - Debug(1, "omsPut: Time_out occurred in send\n"); - return(ERROR); - } - if (pmotor->status & STAT_ERROR) - { - Debug(1, "omsPut: error occurred in send\n"); - } - trys++; - Debug(5, "omsPut: wait count = %d\n", trys); - epicsThreadSleep(quantum); - } - pmotor->data = *putptr; - } - } - return(OK); -} - - -/*****************************************************/ -/* Clear OMS errors */ -/* omsClearErrors() */ -/*****************************************************/ -static int omsError(int card) -{ - volatile struct controller *pmotorState; - volatile struct vmex_motor *pmotor; - struct irqdatastr *irqdata; - int rtnStat = FALSE; - - pmotorState = motor_state[card]; - irqdata = (struct irqdatastr *) pmotorState->DevicePrivate; - pmotor = (struct vmex_motor *) pmotorState->localaddr; - - if (irqdata->irqEnable) - { - /* Check status of last message */ - if (irqdata->irqErrno & STAT_ERROR) - { - /* Error on the card is cleared by the ISR */ - irqdata->irqErrno &= ~STAT_ERROR; - rtnStat = TRUE; - } - } - else - { - int i; - char const *p; - - /* Check/Clear command error from last message */ - if ((pmotor->status) & STAT_ERROR) - { - Debug(1, "omsPut: Error detected! 0x%02x\n", pmotor->status); - for (p = ERROR_CLEAR; *p != '\0'; p++) - { - while (!(pmotor->status & STAT_TRANS_BUF_EMPTY)); - pmotor->data = *p; - } - for (i = 0; i < 20000; i++); - rtnStat = TRUE; - } - } - return(rtnStat); -} - - -/*****************************************************/ -/* Interrupt service routine. */ -/* motorIsr() */ -/*****************************************************/ -static void motorIsr(int card) -{ - volatile struct controller *pmotorState; - volatile struct vmex_motor *pmotor; - struct irqdatastr *irqdata; - epicsUInt8 control; - epicsUInt8 status; - epicsUInt8 doneFlags; - char dataChar; - static char errmsg1[] = "\ndrvOms.cc:motorIsr: Invalid entry - card xx\n"; - static char errmsg2[] = "\ndrvOms.cc:motorIsr: command error - card xx\n"; - static char errmsg3[] = "\ndrvOms.cc:motorIsr: Rx ring overflow - card xx\n"; - - if (card >= total_cards || (pmotorState = motor_state[card]) == NULL) - { - errmsg1[45-2] = '0' + card%10; - errmsg1[45-3] = '0' + (card/10)%10; - epicsInterruptContextMessage(errmsg1); - return; - } - - irqdata = (struct irqdatastr *) pmotorState->DevicePrivate; - pmotor = (struct vmex_motor *) (pmotorState->localaddr); - - /* Save interrupt state */ - control = pmotor->control; - - /* Status register - clear irqs on read. */ - status = pmotor->status; - - /* Done register - clears on read */ - doneFlags = pmotor->done; - - /* Determine cause of entry */ - - /* Motion done handling */ - if (status & STAT_DONE) - /* Wake up polling task 'motor_task()' to issue callbacks */ - motor_sem.signal(); - - /* If command error is present - clear it */ - if (status & STAT_ERROR) - { - pmotor->data = (epicsUInt8) CMD_CLEAR; - errmsg2[45-2] = '0' + card%10; - errmsg2[45-3] = '0' + (card/10)%10; - epicsInterruptContextMessage(errmsg2); - irqdata->irqErrno |= STAT_ERROR; - } - - /* Send message */ - if (status & STAT_TRANS_BUF_EMPTY) - { - if (epicsRingBytesIsEmpty(irqdata->send_rng)) - control &= ~IRQ_TRANS_BUF; /* Transmit done - disable irq */ - else - { - epicsRingBytesGet(irqdata->send_rng, &dataChar, 1); - pmotor->data = dataChar; - } - } - - /* Read Response */ - if (status & STAT_INPUT_BUF_FULL) - { - dataChar = pmotor->data; - - if (epicsRingBytesPut(irqdata->recv_rng, &dataChar, 1) == 0) - { - errmsg3[48-2] = '0' + card%10; - errmsg3[48-3] = '0' + (card/10)%10; - epicsInterruptContextMessage(errmsg3); - irqdata->irqErrno |= STAT_INPUT_BUF_FULL; - } - irqdata->recv_sem->signal(); - } - pmotor->control = control; /* Update-interrupt state. */ - control = pmotor->control; /* Read it back to flush last write cycle. */ -} - -static int motorIsrEnable(int card) -{ - volatile struct controller *pmotorState; - volatile struct vmex_motor *pmotor; - struct irqdatastr *irqdata; - epicsUInt8 cardStatus; - - Debug(5, "motorIsrEnable: Entry card#%d\n", card); - - pmotorState = motor_state[card]; - irqdata = (struct irqdatastr *) pmotorState->DevicePrivate; - pmotor = (struct vmex_motor *) (pmotorState->localaddr); - -#ifdef vxWorks - { - long status; - status = pdevLibVirtualOS->pDevConnectInterruptVME( - omsInterruptVector + card, -#if LT_EPICSBASE(3,14,8,0) - (void (*)()) motorIsr, -#else - (void (*)(void *)) motorIsr, -#endif - (void *) card); - - if (!RTN_SUCCESS(status)) - { - errPrintf(status, __FILE__, __LINE__, - "Can't connect to vector %d\n", - omsInterruptVector + card); - irqdata->irqEnable = FALSE; /* Interrupts disable on card */ - pmotor->control = IRQ_RESET_ID; - return(ERROR); - } - - status = devEnableInterruptLevel(OMS_INTERRUPT_TYPE, - omsInterruptLevel); - if (!RTN_SUCCESS(status)) - { - errPrintf(status, __FILE__, __LINE__, - "Can't enable enterrupt level %d\n", - omsInterruptLevel); - irqdata->irqEnable = FALSE; /* Interrupts disable on card */ - pmotor->control = IRQ_RESET_ID; - return(ERROR); - } - } -#endif - - /* Setup card for interrupt-on-done */ - pmotor->vector = omsInterruptVector + card; - - irqdata->recv_rng = epicsRingBytesCreate(OMS_RESP_Q_SZ); - irqdata->recv_sem = new epicsEvent(epicsEventEmpty); - - irqdata->send_rng = epicsRingBytesCreate(MAX_MSG_SIZE * 2); - - irqdata->irqEnable = TRUE; - irqdata->irqErrno = 0; - - /* Clear board status */ - cardStatus = pmotor->status; - - /* enable interrupt-when-done and input-buffer-full interrupts */ - pmotor->control = (IRQ_ENABLE_ALL | IRQ_RESET_ID); - return(OK); -} - -static void motorIsrDisable(int card) -{ - volatile struct controller *pmotorState; - volatile struct vmex_motor *pmotor; - struct irqdatastr *irqdata; - long status; - - Debug(5, "motorIsrDisable: Entry card#%d\n", card); - - pmotorState = motor_state[card]; - irqdata = (struct irqdatastr *) pmotorState->DevicePrivate; - pmotor = (struct vmex_motor *) (pmotorState->localaddr); - - /* Disable interrupts */ - pmotor->control = IRQ_RESET_ID; - -#ifdef vxWorks - status = pdevLibVirtualOS->pDevDisconnectInterruptVME(omsInterruptVector + card, (void (*)(void *)) motorIsr); -#endif - - if (!RTN_SUCCESS(status)) - errPrintf(status, __FILE__, __LINE__, "Can't disconnect vector %d\n", - omsInterruptVector + card); - - /* Remove interrupt control functions */ - irqdata->irqEnable = FALSE; - irqdata->irqErrno = 0; - epicsRingBytesDelete(irqdata->recv_rng); - epicsRingBytesDelete(irqdata->send_rng); - delete irqdata->recv_sem; -} - - -/*****************************************************/ -/* Configuration function for module_types data */ -/* areas. omsSetup() */ -/*****************************************************/ -RTN_STATUS -omsSetup(int num_cards, /* maximum number of cards in rack */ - void *addrs, /* Base Address(see README for details) */ - unsigned vector,/* noninterrupting(0), valid vectors(64-255) */ - int int_level, /* interrupt level (1-6) */ - int scan_rate) /* polling rate - 1-60 Hz */ -{ - RTN_STATUS rtncode = OK; - char errbase[] = "\nomsSetup: *** invalid "; - - if (num_cards < 1 || num_cards > OMS_NUM_CARDS) - { - char format[] = "%snumber of cards specified = %d ***\n"; - oms44_num_cards = OMS_NUM_CARDS; - errlogPrintf(format, errbase, num_cards); - errlogPrintf(" *** using maximum number = %d ***\n", OMS_NUM_CARDS); - epicsThreadSleep(5.0); - rtncode = ERROR; - } - else - oms44_num_cards = num_cards; - - /* Check boundary(16byte) on base address */ -#ifdef __LP64__ - if ((motorUInt64) addrs & 0xF) -#else - if ((epicsUInt32) addrs & 0xF) -#endif - { - } - else - oms_addrs = (char *) addrs; - - omsInterruptVector = vector; - if (vector < 64 || vector > 255) - { - if (vector != 0) - { - char format[] = "%s interrupt vector %d ***\n"; - omsInterruptVector = (unsigned) OMS_INT_VECTOR; - errlogPrintf(format, errbase, vector); - epicsThreadSleep(5.0); - rtncode = ERROR; - } - } - - if (int_level < 1 || int_level > 6) - { - char format[] = "%s interrupt level %d ***\n"; - omsInterruptLevel = OMS_INT_LEVEL; - errlogPrintf(format, errbase, int_level); - epicsThreadSleep(5.0); - rtncode = ERROR; - } - else - omsInterruptLevel = int_level; - - /* Set motor polling task rate */ - if (scan_rate >= 1 && scan_rate <= MAX_SCAN_RATE) - targs.motor_scan_rate = scan_rate; - else - { - char format[] = "%s invalid poll rate - %d HZ\n"; - targs.motor_scan_rate = SCAN_RATE; - errlogPrintf(format, errbase, scan_rate); - epicsThreadSleep(5.0); - rtncode = ERROR; - } - return(rtncode); -} - -/*****************************************************/ -/* initialize all software and hardware */ -/* motor_init() */ -/*****************************************************/ -static int motor_init() -{ - volatile struct controller *pmotorState; - volatile struct vmex_motor *pmotor; - long status = 0; - int card_index, motor_index; - char axis_pos[50], encoder_pos[50]; - char *tok_save, *pos_ptr; - int total_encoders = 0, total_axis = 0; - volatile void *localaddr; - void *probeAddr; - - tok_save = NULL; - quantum = epicsThreadSleepQuantum(); - - /* Check for setup */ - if (oms44_num_cards <= 0) - { - Debug(1, "motor_init: *OMS driver disabled* \n omsSetup() is missing from startup script.\n"); - return(ERROR); - } - - /* allocate space for total number of motors */ - motor_state = (struct controller **) malloc(oms44_num_cards * - sizeof(struct controller *)); - - /* allocate structure space for each motor present */ - - total_cards = oms44_num_cards; - - if (epicsAtExit(oms_reset, NULL) == ERROR) - Debug(1, "vme8/44 motor_init: oms_reset disabled\n"); - - for (card_index = 0; card_index < oms44_num_cards; card_index++) - { - epicsInt8 *startAddr; - epicsInt8 *endAddr; - - Debug(2, "motor_init: card %d\n", card_index); - - probeAddr = oms_addrs + (card_index * OMS_BRD_SIZE); - startAddr = (epicsInt8 *) probeAddr + 1; - endAddr = startAddr + OMS_BRD_SIZE; - - Debug(9, "motor_init: devNoResponseProbe() on addr %p\n", probeAddr); - /* Scan memory space to assure card id */ -#ifdef vxWorks - do - { - status = devNoResponseProbe(OMS_ADDRS_TYPE, (unsigned int) startAddr, 1); - startAddr += 0x2; - } while (PROBE_SUCCESS(status) && startAddr < endAddr); -#endif - if (PROBE_SUCCESS(status)) - { - struct irqdatastr *irqdata; - -#ifdef vxWorks - status = devRegisterAddress(__FILE__, OMS_ADDRS_TYPE, - (size_t) probeAddr, OMS_BRD_SIZE, - (volatile void **) &localaddr); - Debug(9, "motor_init: devRegisterAddress() status = %d\n", - (int) status); - if (!RTN_SUCCESS(status)) - { - errPrintf(status, __FILE__, __LINE__, - "Can't register address 0x%x\n", (unsigned) probeAddr); - return(ERROR); - } -#endif - Debug(9, "motor_init: localaddr = %p\n", localaddr); - pmotor = (struct vmex_motor *) localaddr; - - Debug(9, "motor_init: malloc'ing motor_state\n"); - motor_state[card_index] = (struct controller *) malloc(sizeof(struct controller)); - pmotorState = motor_state[card_index]; - pmotorState->localaddr = (char *) localaddr; - pmotorState->motor_in_motion = 0; - pmotorState->cmnd_response = false; - - /* Disable Interrupts */ - irqdata = (struct irqdatastr *) malloc(sizeof(struct irqdatastr)); - pmotorState->DevicePrivate = irqdata; - irqdata->irqEnable = FALSE; - pmotor->control = IRQ_RESET_ID; - - send_mess(card_index, "EF", (char*) NULL); - send_mess(card_index, ERROR_CLEAR, (char*) NULL); - send_mess(card_index, STOP_ALL, (char*) NULL); - - send_mess(card_index, GET_IDENT, (char*) NULL); - - recv_mess(card_index, (char *) pmotorState->ident, 1); - Debug(3, "Identification = %s\n", pmotorState->ident); - - send_mess(card_index, ALL_POS, (char*) NULL); - recv_mess(card_index, axis_pos, 1); - - for (total_axis = 0, pos_ptr = epicsStrtok_r(axis_pos, ",", &tok_save); - pos_ptr; - pos_ptr = epicsStrtok_r(NULL, ",", &tok_save), total_axis++) - { - pmotorState->motor_info[total_axis].motor_motion = NULL; - pmotorState->motor_info[total_axis].status.All = 0; - } - - Debug(3, "Total axis = %d\n", total_axis); - pmotorState->total_axis = total_axis; - - for (total_encoders = 0, motor_index = 0; motor_index < total_axis; motor_index++) - { - send_mess(card_index, ENCODER_QUERY, oms_axis[motor_index]); - if (recv_mess(card_index, encoder_pos, 1) == -1) - { - /* Command error - no encoder */ - Debug(2, "No encoder on %d\n", motor_index); - pmotorState->motor_info[motor_index].encoder_present = NO; - } - else - { - total_encoders++; - pmotorState->motor_info[motor_index].encoder_present = YES; - } - } - - /* Enable interrupt-when-done if selected. */ - - if (omsInterruptVector) - { - if (motorIsrEnable(card_index) == ERROR) - errPrintf(0, __FILE__, __LINE__, "Interrupts Disabled!\n"); - } - - for (motor_index = 0; motor_index < total_axis; motor_index++) - { - pmotorState->motor_info[motor_index].status.All = 0; - pmotorState->motor_info[motor_index].no_motion_count = 0; - pmotorState->motor_info[motor_index].encoder_position = 0; - pmotorState->motor_info[motor_index].position = 0; - - if (pmotorState->motor_info[motor_index].encoder_present == YES) - pmotorState->motor_info[motor_index].status.Bits.EA_PRESENT = 1; - set_status(card_index, motor_index); - } - - Debug(2, "Init Address=%p\n", localaddr); - Debug(3, "Total encoders = %d\n\n", total_encoders); - } - else - { - Debug(3, "motor_init: Card NOT found!\n"); - motor_state[card_index] = (struct controller *) NULL; - } - } - - any_motor_in_motion = 0; - - mess_queue.head = (struct mess_node *) NULL; - mess_queue.tail = (struct mess_node *) NULL; - - free_list.head = (struct mess_node *) NULL; - free_list.tail = (struct mess_node *) NULL; - - Debug(3, "Motors initialized\n"); - - epicsThreadCreate((const char *) "Oms_motor", epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackMedium), - (EPICSTHREADFUNC) motor_task, (void *) &targs); - - Debug(3, "Started motor_task\n"); - return(0); -} - -/* Disables interrupts. Called on CTL X reboot. */ - -static void oms_reset(void *arg) -{ - short card; - struct vmex_motor *pmotor; - - for (card = 0; card < total_cards; card++) - { - if (motor_state[card] != NULL) - { - pmotor = (struct vmex_motor *) motor_state[card]->localaddr; - pmotor->control = IRQ_RESET_ID; /* Disable all interrupts. */ - } - } -} - -/*---------------------------------------------------------------------*/ diff --git a/motorApp/OmsSrc/drvOms.h b/motorApp/OmsSrc/drvOms.h deleted file mode 100644 index 6a86a49a..00000000 --- a/motorApp/OmsSrc/drvOms.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -FILENAME... drvOms.h -USAGE... This file contains OMS driver "include" information that is - specific to OMS models VME8 and VME44. - -*/ - -/* - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - * .00 10-23-03 rls - VX2 spurious interrupt fix; enable all interrupts, including - * transmit buffer empty. - * .01 10-28-03 rls - moved OMS specific "irqdatastr" from motordrvCom.h to here. - */ - -#ifndef INCdrvOmsh -#define INCdrvOmsh 1 - -#include "drvOmsCom.h" -#include "epicsRingBytes.h" - -/* - * VME8/44 default profile - */ - -#define OMS_NUM_CARDS 8 -#define OMS_NUM_CHANNELS 8 -#define OMS_NUM_ADDRS 0xFC00 -#define OMS_BRD_SIZE 0x10 /* card address boundary */ -#define OMS_RESP_Q_SZ 0x100 /* maximum oms response message size */ - -/* status register */ -#define STAT_IRQ 0x80 -#define STAT_TRANS_BUF_EMPTY 0x40 -#define STAT_INPUT_BUF_FULL 0x20 -#define STAT_DONE 0x10 -#define STAT_OVERTRAVEL 0x08 -#define STAT_ENCODER_REQ 0x04 -#define STAT_INIT 0x02 -#define STAT_ERROR 0x01 - -/* done flag register */ -#define DONE_X 0x01 -#define DONE_Y 0x02 -#define DONE_Z 0x04 -#define DONE_T 0x08 -#define DONE_U 0x10 -#define DONE_V 0x20 -#define DONE_R 0x40 -#define DONE_S 0x80 - -/* interrupt control register */ -#define IRQ_ENABLE 0x80 -#define IRQ_TRANS_BUF 0x40 -#define IRQ_INPUT_BUF 0x20 -#define IRQ_DONE 0x10 -#define IRQ_RESET_ID 0x01 - -#define IRQ_ENABLE_ALL (IRQ_ENABLE|IRQ_TRANS_BUF|IRQ_INPUT_BUF|IRQ_DONE) - -struct vmex_motor -{ - epicsUInt8 unused0; - epicsUInt8 data; - epicsUInt8 unused1; - epicsUInt8 done; - epicsUInt8 unused2; - epicsUInt8 control; - epicsUInt8 unused3; - epicsUInt8 status; - epicsUInt8 unused4; - epicsUInt8 vector; - epicsUInt8 unused5[6]; -}; - -struct irqdatastr /* Used only for VME44. */ -{ - /* Interrupt Handling control elements */ - int irqErrno; /* Error indicator from isr */ - epicsUInt8 irqEnable; - epicsRingBytesId recv_rng; /* message receiving control */ - epicsEvent *recv_sem; - epicsRingBytesId send_rng; /* message transmitting control */ -}; - -#endif /* INCdrvOmsh */ diff --git a/motorApp/OmsSrc/drvOms58.cc b/motorApp/OmsSrc/drvOms58.cc deleted file mode 100644 index f2d8261e..00000000 --- a/motorApp/OmsSrc/drvOms58.cc +++ /dev/null @@ -1,1387 +0,0 @@ -/* -FILENAME... drvOms58.cc -USAGE... Motor record driver level support for OMS model VME58. - -*/ - -/* - * Original Author: Jim Kowalkowski - * Current Author: Joe Sullivan - * Date: 11/14/94 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * NOTES - * ----- - * Verified with firmware: - * - VME58 ver 2.16-8 - * - VME58 ver 2.24-8 - * - VME58 ver 2.24-8S - * - VME58 ver 2.24-4E - * - VME58 ver 2.35-8 - * - VME58 ver 2.41-8 - * - VME58 ver 2.42-8 - * - * Modification Log: - * ----------------- - * .01 01-18-93 jbk initialized - * .02 11-14-94 jps copy drvOms.c and modify to point to vme58 driver - * ... - * .14 02-10-95 jps first released version w/interrupt supprt - * .15 02-16-95 jps add better simulation mode support - * .16 03-10-95 jps limit switch handling improvements - * .17 04-11-95 jps misc. fixes - * .18 09-27-95 jps fix GET_INFO latency bug, add axis argument to - * set_status() create add debug verbosity of 3 - * .19 05-03-96 jps convert 32bit card accesses to 16bit - vme58PCB - * version D does not support 32bit accesses. - * .20 06-20-96 jps add more security to message parameters (card #) - * .20a 02-19-97 tmm fixed for EPICS 3.13 - * .21 01-20-00 rls Update bit collision check and wait. Problem - * with old position data returned after Done - * detected when moving multiple axes on same - * controller board. Fix: Update shared memory - * data after Done detected via ASCII controller - * commands. To avoid collisions, skip writing to - * control reg. from motorIsr() if update bit is - * true. - * .22 02-22-02 rls - start_status() was not checking for a valid - * motor_state[card] pointer. This causes a bus error if - * the controller array has holes in it. - * - "total_cards" changed from total detected to total - * cards that "memory is allocated for". This allows - * boards after the "hole" to work. - * .23 06-04-03 rls Convert to R3.14.x. - * .24 06-04-03 rls extended device directive support to PREM and POST. - * .25 12-12-03 rls - Converted MSTA #define's to bit field. - * - One line of code must be selected based on either - * Tornado 2.0.2 (default) or Tornado 2.2. If Tornado - * 2.2 is selected, EPICS base patches must be applied as - * described in; - * http://www.aps.anl.gov/upd/people/sluiter/epics/motor/R5-2/Problems.html - * .26 02-03-04 rls - Eliminate erroneous "Motor motion timeout ERROR". - * .27 07-16-04 rls - removed unused Setup() argument. - * .28 09-20-04 rls - support for 32axes/controller. - * .29 12-06-04 rls - Windows compiler support. - * - eliminate calls to devConnectInterrupt() due to C++ - * problems with devLib.h; i.e. "sorry, not implemented: - * `tree_list' not supported..." compiler error message. - * .30 03-23-05 rls - Make OSI. - * .31 05-02-05 rls - Bug fix for stale data delay; set delay = 10ms. - * .32 08-16-07 rls - "stale data" problem was caused by communicating via the - * ASCII commands while the DPRAM was updating. - * - set "stale data delay" to zero. - * - remove "Work around for intermittent wrong LS status" for - * version 2.35 firmware. - * - modify start_status() to wait for update before exiting. - * .33 02-06-08 rls - restored "update delay" for 2.24-8S and all 2.35 - * firmware versions. - * For details see README item #2 under R6-4 Modification - * Log. - * .34 02-07-08 rls - switched to logMsg for VxWorks build in ISR, rather than - * errlogPrintf(). No info with errlogPrintf() from ISR. - * .35 02-27-08 rls - replaced errlogPrintf calls in ISR with - * epicsInterruptContextMessage calls. - * .36 03-14-08 rls - 64-bit compatiability. - * .37 02-05-09 rls - Have start_status() start ALL updates before waiting. - * .38 06-18-09 rls - Make oms58Setup() error messages more prominent. - * .39 03-15-10 rls - sprintf() not callable from any OS ISR. - * .40 01-26-11 rls - added reboot flag to DPRAM R/W reserved area. Driver - * sets flag to 0x4321; set_status() disables board if flag - * does not read 0x4321. - * .41 10-20-11 rls - Added counter in send_mess() to prevent endless loop - * after VME58 reboot. - * .42 07-26-12 rls - Added reboot test to send_mess(). - * .43 02-21-16 rls - Added code to send_mess() that test for a VME58 reboot - * after a motion related (ST, MA, MR) command. Found new - * VME58 failure mode where board reboots after the 1st - * motion related command. Since delay between motion - * command and reboot test must be long enough to avoid a - * VMEbus error, delay is excessive for normal operation. - * Hence, the oms58_reboot_test external variable. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "motorRecord.h" /* For Driver Power Monitor feature only. */ -#include "motor.h" -#include "motordevCom.h" /* For Driver Power Monitor feature only. */ -#include "drvOms58.h" - -#include "epicsExport.h" -#include "iocsh.h" - -#define PRIVATE_FUNCTIONS 1 /* normal:1, debug:0 */ - -/* Define for return test on devNoResponseProbe() */ -#define PROBE_SUCCESS(STATUS) ((STATUS)==S_dev_addressOverlap) - -/* jps: INFO messages - add RV and move QA to top */ -#define ALL_INFO "QA EA" -#define AXIS_INFO "QA" -#define ENCODER_QUERY "EA ID" -#define AXIS_CLEAR "CA" /* Clear done of addressed axis */ -#define DONE_QUERY "RA" /* ?? Is this needed?? */ -#define PID_QUERY "KK2 ID" - - -/*----------------debugging-----------------*/ -volatile int drvOms58debug = 0; -extern "C" {epicsExportAddress(int, drvOms58debug);} -static inline void Debug(int level, const char *format, ...) { - #ifdef DEBUG - if (level < drvOms58debug) { - va_list pVar; - va_start(pVar, format); - vprintf(format, pVar); - va_end(pVar); - } - #endif -} - -#define pack2x16(p) ((epicsUInt32)(((p[0])<<16)|(p[1]))) - -/* Global data. */ -int oms58_num_cards = 0; -int oms58_reboot_test = 0; - -/* Local data required for every driver; see "motordrvComCode.h" */ -#include "motordrvComCode.h" - - -/* --- Local data common to all OMS drivers. --- */ -static char *oms_addrs = 0x0; -static volatile unsigned omsInterruptVector = 0; -static volatile epicsUInt8 omsInterruptLevel = OMS_INT_LEVEL; -static volatile int max_io_tries = MAX_COUNT; -static volatile int motionTO = 10; -static char *oms58_axis[] = {"X", "Y", "Z", "T", "U", "V", "R", "S"}; -static double quantum; - -/*----------------functions-----------------*/ - -/* Common local function declarations. */ -static long report(int); -static long init(); -static void query_done(int, int, struct mess_node *); -static int set_status(int, int); -static RTN_STATUS send_mess(int, char const *, char *); -static int recv_mess(int, char *, int); -static void motorIsr(int card); -static int motor_init(); -static void oms_reset(void *); - -static void start_status(int card); -static int motorIsrSetup(int card); - -struct driver_table oms58_access = -{ - NULL, - motor_send, - motor_free, - motor_card_info, - motor_axis_info, - &mess_queue, - &queue_lock, - &free_list, - &freelist_lock, - &motor_sem, - &motor_state, - &total_cards, - &any_motor_in_motion, - send_mess, - recv_mess, - set_status, - query_done, - start_status, - &initialized, - oms58_axis -}; - -struct drvOms58_drvet -{ - long number; - long (*report) (int); - long (*init) (void); -} drvOms58 = {2, report, init}; - -extern "C" {epicsExportAddress(drvet, drvOms58);} - -static char rebootmsg[] = "\n\n*** VME58 card #%d Disabled *** Reboot Detected.\n\n"; - -static struct thread_args targs = {SCAN_RATE, &oms58_access, 0.000}; - -/*----------------functions-----------------*/ - -static long report(int level) -{ - int card; - - if (oms58_num_cards <= 0) - printf(" No VME58 controllers configured.\n"); - else - { - for (card = 0; card < oms58_num_cards; card++) - { - struct controller *brdptr = motor_state[card]; - - if (brdptr == NULL) - printf(" Oms Vme58 motor card #%d not found.\n", card); - else - printf(" Oms Vme58 motor card #%d @ %p, id: %s \n", card, - brdptr->localaddr, brdptr->ident); - } - } - return(0); -} - -static long init() -{ - initialized = true; /* Indicate that driver is initialized. */ - (void) motor_init(); - return((long) 0); -} - - -static void query_done(int card, int axis, struct mess_node *nodeptr) -{ - char buffer[40]; - - send_mess(card, DONE_QUERY, oms58_axis[axis]); - recv_mess(card, buffer, 1); - if (nodeptr->status.Bits.RA_PROBLEM) - send_mess(card, AXIS_STOP, oms58_axis[axis]); -} - - -/********************************************************* - * Start card data area update. - * Each card will take 800-900us to complete update. - * start_status(int card) - * if card == -1 then start all cards - *********************************************************/ -static void start_status(int card) -{ - volatile struct vmex_motor *pmotor; - CNTRL_REG cntrlReg; - int index; - - if (card >= 0) - { - if (motor_state[card] != NULL && - (pmotor = (struct vmex_motor *) motor_state[card]->localaddr) != NULL) - { - /* Wait Forever for controller to update. */ - cntrlReg.All = pmotor->control.cntrlReg; - while (cntrlReg.Bits.update != 0) - { - Debug(1, "start_status(): Update Wait: card #%d\n", card); - epicsThreadSleep(quantum); - cntrlReg.All = pmotor->control.cntrlReg; - }; - - cntrlReg.Bits.update = 1; - pmotor->control.cntrlReg = cntrlReg.All; - - /* Wait Forever for controller to update. */ - cntrlReg.All = pmotor->control.cntrlReg; - while (cntrlReg.Bits.update != 0) - { - Debug(1, "start_status: DPRAM delay.\n"); - epicsThreadSleep(quantum); - cntrlReg.All = pmotor->control.cntrlReg; - } - } - } - else - { - /* Start all cards updating. */ - for (index = 0; index < total_cards; index++) - { - if (motor_state[index] != NULL && - (pmotor = (struct vmex_motor *) motor_state[index]->localaddr) != NULL) - { - /* Wait Forever for controller to update. */ - cntrlReg.All = pmotor->control.cntrlReg; - while (cntrlReg.Bits.update != 0) - { - Debug(1, "start_status(): Waiting to start update: card #%d\n", index); - epicsThreadSleep(quantum); - cntrlReg.All = pmotor->control.cntrlReg; - }; - - cntrlReg.Bits.update = 1; - pmotor->control.cntrlReg = cntrlReg.All; - } - } - /* Wait for all cards to complete update. */ - for (index = 0; index < total_cards; index++) - { - if (motor_state[index] != NULL && - (pmotor = (struct vmex_motor *) motor_state[index]->localaddr) != NULL) - { - /* Wait Forever for controller to update. */ - cntrlReg.All = pmotor->control.cntrlReg; - while (cntrlReg.Bits.update != 0) - { - Debug(1, "start_status: DPRAM delay.\n"); - epicsThreadSleep(quantum); - cntrlReg.All = pmotor->control.cntrlReg; - } - } - } - } -} - -/****************************************************************************** -* FUNCTION NAME: set_status -* -* ARGUMETS Type I/O Description -* -------- ---- --- ----------- -* -* card int I Controller card index #. -* signal int I Motor index. -* -* LOGIC -* Initialize. -* IF encoder present. -* Get axis and encoder information. -* ELSE -* Get axis information. -* ENDIF -* -* Process controller response strings. -* -* ... -* ... -* IF "motor-in-motion" (i.e., nodeptr != 0), AND, no limit switch error. -* IF drive power monitoring enabled. -* ... -* ENDIF -* ENDIF -* -* IF no motion, OR, status indicates limit switch error, OR, motor done, OR, -* controller problem. -* Set return state to "callback record". -* ELSE -* Set return state to skip "record callback". -* ENDIF -* IF status indicates DONE/LIMIT, AND, "motor-in-motion" (nodeptr != 0), AND, -* post-move message is not null. -* Send post-move message to controller. -* Clear post-move message pointer. -* ENDIF -* EXIT with return state indicator. -******************************************************************************/ - -static int set_status(int card, int signal) -{ - struct mess_info *motor_info; - struct mess_node *nodeptr; - volatile struct vmex_motor *pmotor; - CNTRL_REG cntrlReg; - volatile MOTOR_DATA_REGS *pmotorData; - epicsInt32 motorData; - /* Message parsing variables */ - char *p, *tok_save; - struct axis_status *ax_stat; - struct encoder_status *en_stat; - char q_buf[50], outbuf[50]; - int index; - bool ls_active = false; - bool got_encoder; - msta_field status; - - int rtn_state; - - motor_info = &(motor_state[card]->motor_info[signal]); - nodeptr = motor_info->motor_motion; - pmotor = (struct vmex_motor *) motor_state[card]->localaddr; - status.All = motor_info->status.All; - - if (pmotor->rebootind != 0x4321) /* Test if board has rebooted. */ - { - errlogPrintf(rebootmsg, card); - status.Bits.RA_PROBLEM = 1; - motor_info->status.All = status.All; - /* Disable board. */ - motor_state[card] = (struct controller *) NULL; - return(rtn_state = 1); /* End move. */ - } - - if (motor_info->encoder_present == YES) - { - /* get 4 peices of info from axis */ - send_mess(card, ALL_INFO, oms58_axis[signal]); - recv_mess(card, q_buf, 2); - got_encoder = true; - } - else - { - /* get 2 peices of info from axis */ - send_mess(card, AXIS_INFO, oms58_axis[signal]); - recv_mess(card, q_buf, 1); - got_encoder = false; - } - - for (index = 0, p = epicsStrtok_r(q_buf, ",", &tok_save); p; - p = epicsStrtok_r(NULL, ",", &tok_save), index++) - { - switch (index) - { - case 0: /* axis status */ - ax_stat = (struct axis_status *) p; - - status.Bits.RA_DIRECTION = (ax_stat->direction == 'P') ? 1 : 0; - status.Bits.RA_HOME = (ax_stat->home == 'H') ? 1 : 0; - - if (ax_stat->done == 'D') - { - /* Request Data Area Update after DONE detected so that both - * ASCII command data and shared memory data match. */ - start_status(card); - status.Bits.RA_DONE = 1; - } - else - status.Bits.RA_DONE = 0; - - if (ax_stat->overtravel == 'L') - { - ls_active = true; - if (status.Bits.RA_DIRECTION) - status.Bits.RA_PLUS_LS = 1; - else - status.Bits.RA_MINUS_LS = 1; - } - else - { - ls_active = false; - status.Bits.RA_PLUS_LS = 0; - status.Bits.RA_MINUS_LS = 0; - } - break; - case 1: /* encoder status */ - en_stat = (struct encoder_status *) p; - - status.Bits.EA_SLIP = (en_stat->slip_enable == 'E') ? 1 : 0; - status.Bits.EA_POSITION = (en_stat->pos_enable == 'E') ? 1 : 0; - status.Bits.EA_SLIP_STALL = (en_stat->slip_detect == 'S') ? 1 : 0; - status.Bits.EA_HOME = (en_stat->axis_home == 'H') ? 1 : 0; - break; - default: - break; - } - } - - - /* Setup mask for data-ready detection */ - cntrlReg.All = 0; - cntrlReg.Bits.update = 1; - - /* Wait for data area update to complete on card */ - while (cntrlReg.All & pmotor->control.cntrlReg) - { - Debug(5, "set_status: DPRAM delay.\n"); - epicsThreadSleep(quantum); - } - - pmotorData = &pmotor->data[signal]; - - /* Get motor position - word access only */ - motorData = pack2x16(pmotorData->cmndPos); - - if (motorData == motor_info->position) - { - if (nodeptr != 0) /* Increment counter only if motor is moving. */ - motor_info->no_motion_count++; - } - else - { - motor_info->position = motorData; - motor_info->no_motion_count = 0; - } - - if (motor_info->no_motion_count > motionTO) - { - status.Bits.RA_PROBLEM = 1; - send_mess(card, AXIS_STOP, oms58_axis[signal]); - motor_info->no_motion_count = 0; - errlogSevPrintf(errlogMinor, "Motor motion timeout ERROR on card: %d, signal: %d\n", - card, signal); - } - else - status.Bits.RA_PROBLEM = 0; - - /* get command velocity - word access only */ - motorData = pack2x16(pmotorData->cmndVel); - - motor_info->velocity = motorData; - - if (!(status.Bits.RA_DIRECTION)) - motor_info->velocity *= -1; - - /* Get encoder position */ - motorData = pack2x16(pmotorData->encPos); - - motor_info->encoder_position = motorData; - - if (nodeptr != NULL && ls_active == false) - { - struct motor_trans *trans = (struct motor_trans *) nodeptr->mrecord->dpvt; - if (trans->dpm == true) - { - unsigned char bitselect; - unsigned char inputs = pmotor->control.ioLowReg; - bitselect = (1 << signal); - if ((inputs & bitselect) == 0) - { - status.Bits.RA_PLUS_LS = 1; /* Turn on both limit switches. */ - status.Bits.RA_MINUS_LS = 1; - errlogPrintf("Drive power failure at VME58 card#%d motor#%d\n", - card, signal); - } - } - } - - rtn_state = (!motor_info->no_motion_count || ls_active == true || - status.Bits.RA_DONE || status.Bits.RA_PROBLEM) ? 1 : 0; - - /* Test for post-move string. */ - if ((status.Bits.RA_DONE || ls_active == true) && nodeptr != 0 && - nodeptr->postmsgptr != 0) - { - char buffer[40]; - - /* Test for a "device directive" in the POST string. */ - if (nodeptr->postmsgptr[0] == '@') - { - bool errind = false; - char *end = strchr(&nodeptr->postmsgptr[1], '@'); - if (end == NULL) - errind = true; - else - { - DBADDR addr; - char *start, *tail; - int size = (end - &nodeptr->postmsgptr[0]) + 1; - - /* Copy device directive to buffer. */ - strncpy(buffer, nodeptr->postmsgptr, size); - buffer[size] = (char) NULL; - - if (strncmp(buffer, "@PUT(", 5) != 0) - goto errorexit; - - /* Point "start" to PV name argument. */ - tail = NULL; - start = epicsStrtok_r(&buffer[5], ",", &tail); - if (tail == NULL) - goto errorexit; - - if (dbNameToAddr(start, &addr)) /* Get address of PV. */ - { - errPrintf(-1, __FILE__, __LINE__, "Invalid PV name: %s", start); - goto errorexit; - } - - /* Point "start" to PV value argument. */ - start = epicsStrtok_r(NULL, ")", &tail); - if (dbPutField(&addr, DBR_STRING, start, 1L)) - { - errPrintf(-1, __FILE__, __LINE__, "invalid value: %s", start); - goto errorexit; - } - } - - if (errind == true) -errorexit: errMessage(-1, "Invalid device directive"); - end++; - strcpy(buffer, end); - } - else - strcpy(buffer, nodeptr->postmsgptr); - - strcpy(outbuf, buffer); - send_mess(card, outbuf, oms58_axis[signal]); - nodeptr->postmsgptr = NULL; - } - - /* Bug fix for DC servo moving away from limit switch, but move is not far enough to - * get off limit switch; resulting in limit error. Fix is to force CDIR to match - * MSTA.RA_DIRECTION. - */ - if (ls_active == true && status.Bits.GAIN_SUPPORT && - status.Bits.EA_POSITION == 0 && nodeptr != 0) - { - struct motorRecord *mr = (struct motorRecord *) nodeptr->mrecord; - - if (mr->cdir != (short) status.Bits.RA_DIRECTION) - mr->cdir = status.Bits.RA_DIRECTION; - } - - motor_info->status.All = status.All; /* Update status from local copy. */ - return(rtn_state); -} - - -/*****************************************************/ -/* send a message to the OMS board */ -/* send_mess() */ -/*****************************************************/ -static RTN_STATUS send_mess(int card, char const *com, char *name) -{ - volatile struct vmex_motor *pmotor; - epicsInt16 putIndex; - char outbuf[MAX_MSG_SIZE], *p; - RTN_STATUS return_code; - int count; - - if (strlen(com) > MAX_MSG_SIZE) - { - errlogPrintf("drvOms58.cc:send_mess(); message size violation.\n"); - return(ERROR); - } - - /* Check that card exists */ - if (!motor_state[card]) - { - errlogPrintf("drvOms58.cc:send_mess() - invalid card #%d\n", card); - return(ERROR); - } - - pmotor = (struct vmex_motor *) motor_state[card]->localaddr; - - if (pmotor->rebootind != 0x4321) /* Test if board has rebooted. */ - { - errlogPrintf(rebootmsg, card); - /* Disable board. */ - motor_state[card] = (struct controller *) NULL; - return(ERROR); - } - - return_code = OK; - - Debug(9, "send_mess: checking card %d status\n", card); - -/* jps: Command error handling has been moved to motorIsr() */ -/* Debug(1, "Command error detected! 0x%02x on send_mess\n", status.All); */ - - /* see if junk at input port - should not be any data available */ - if (pmotor->inGetIndex != pmotor->inPutIndex) - { - Debug(1, "send_mess - clearing data in buffer\n"); - recv_mess(card, NULL, -1); - } - - - if (name == NULL) - strcpy(outbuf, com); - else - { - strcpy(outbuf, "A"); - strcat(outbuf, name); - strcat(outbuf, " "); - strcat(outbuf, com); - } - strcat(outbuf, "\n"); /* Add the command line terminator. */ - - Debug(9, "send_mess: ready to send message.\n"); - putIndex = pmotor->outPutIndex; - for (p = outbuf; *p != '\0'; p++) - { - pmotor->outBuffer[putIndex++] = *p; - if (putIndex >= BUFFER_SIZE) - putIndex = 0; - } - - Debug(4, "send_mess: sent card %d message:", card); - Debug(4, "%s\n", outbuf); - - pmotor->outPutIndex = putIndex; /* Send message. */ - - if (oms58_reboot_test != 0) /* Test if board has rebooted after sending message. */ - { - epicsThreadSleep(0.300); - if (pmotor->rebootind != 0x4321) - { - errlogPrintf(rebootmsg, card); - /* Disable board. */ - motor_state[card] = (struct controller *)NULL; - epicsThreadSleep(1.0); - return (ERROR); - } - } - - for (count = 0; (putIndex != pmotor->outGetIndex) && (count < 1000); count++) - { -#ifdef DEBUG - epicsInt16 deltaIndex, delta; - - deltaIndex = pmotor->outPutIndex - pmotor->outGetIndex; - delta = (deltaIndex < 0) ? BUFFER_SIZE + deltaIndex : deltaIndex; - Debug(5, "send_mess(): buffer wait; index delta=%d\n", delta); -#endif - epicsThreadSleep(quantum); - }; - - if (count >= 1000) - { - errlogPrintf("\n\n*** VME58 card #%d communication timeout ***\n\n", card); - return_code = ERROR; - } - - return(return_code); -} - -/* - * FUNCTION... recv_mess(int card, char *com, int amount) - * - * INPUT ARGUMENTS... - * card - - * *com - - * amount - - * - * LOGIC... - * IF controller card does not exist. - * ERROR Exit. - * ENDIF - * IF "amount" indicates buffer flush. - * WHILE characters left in input buffer. - * Remove characters from controller's input buffer. - * ENDWHILE - * NORMAL RETURN. - * ENDIF - * - * FOR each message requested (i.e. "amount"). - * Initialize head and tail pointers. - * Initialize local buffer "get" index. - * FOR - * IF characters left in controller's input buffer. - * - * ENDIF - * ENDFOR - * ENDFOR - * - */ -static int recv_mess(int card, char *com, int amount) -{ - volatile struct vmex_motor *pmotor; - epicsInt16 getIndex; - int i, trys; - char junk; - unsigned char inchar; - int piece, head_size, tail_size; - - /* Check that card exists */ - if (!motor_state[card]) - { - Debug(1, "resv_mess - invalid card #%d\n", card); - return(-1); - } - - pmotor = (struct vmex_motor *) motor_state[card]->localaddr; - - if (amount == -1) - { - Debug(7, "-------------"); - getIndex = pmotor->inGetIndex; - for (i = 0, trys = 0; trys < max_io_tries; trys++) - { - while (getIndex != pmotor->inPutIndex) - { - junk = pmotor->inBuffer[getIndex++]; - /* handle circular buffer */ - if (getIndex >= BUFFER_SIZE) - getIndex = 0; - - Debug(7, "%c", junk); - trys = 0; - i++; - } - } - pmotor->inGetIndex = getIndex; - - Debug(7, "-------------"); - Debug(1, "\nrecv_mess - cleared %d error data\n", i); - return(0); - } - - for (i = 0; amount > 0; amount--) - { - Debug(7, "-------------"); - head_size = 0; - tail_size = 0; - - getIndex = pmotor->inGetIndex; - - for (piece = 0, trys = 0; piece < 3 && trys < max_io_tries; trys++) - { - if (getIndex != pmotor->inPutIndex) - { - inchar = pmotor->inBuffer[getIndex++]; - if (getIndex >= BUFFER_SIZE) - getIndex = 0; - - Debug(7, "%02x", inchar); - - switch (piece) - { - case 0: /* header */ - if (inchar == '\n' || inchar == '\r') - head_size++; - else - { - piece++; - com[i++] = inchar; - } - break; - case 1: /* body */ - if (inchar == '\n' || inchar == '\r') - { - piece++; - tail_size++; - } - else - com[i++] = inchar; - break; - - case 2: /* trailer */ - tail_size++; - if (tail_size >= head_size) - piece++; - break; - } - trys = 0; - } - } - pmotor->inGetIndex = getIndex; - - Debug(7, "-------------\n"); - if (trys >= max_io_tries) - { - Debug(1, "Timeout occurred in recv_mess\n"); - com[i] = '\0'; - - /* ----------------extra junk-------------- */ - /* jps: command error now cleared by motorIsr() */ - /* ----------------extra junk-------------- */ - - return(-1); - } - com[i++] = ','; - } - - if (i > 0) - com[i - 1] = '\0'; - else - com[i] = '\0'; - - Debug(4, "recv_mess: card %d", card); - Debug(4, " com %s\n", com); - return(0); -} - - -/*****************************************************/ -/* Configuration function for module_types data */ -/* areas. omsSetup() */ -/*****************************************************/ -RTN_STATUS -oms58Setup(int num_cards, /* maximum number of cards in rack */ - void *addrs, /* Base Address(0x0-0xb000 on 4K boundary) */ - unsigned vector, /* noninterrupting(0), valid vectors(64-255) */ - int int_level, /* interrupt level (1-6) */ - int scan_rate) /* polling rate - 1-60 Hz */ -{ - RTN_STATUS rtncode = OK; - char errbase[] = "\noms58Setup: *** invalid "; - - if (num_cards < 1 || num_cards > OMS_NUM_CARDS) - { - char format[] = "%snumber of cards specified = %d ***\n"; - oms58_num_cards = OMS_NUM_CARDS; - errlogPrintf(format, errbase, num_cards); - errlogPrintf(" *** using maximum number = %d ***\n", OMS_NUM_CARDS); - epicsThreadSleep(5.0); - rtncode = ERROR; - } - else - oms58_num_cards = num_cards; - - /* Check range and boundary(4K) on base address */ -#ifdef __LP64__ - if (addrs > (void *) 0xF000 || ((motorUInt64) addrs & 0xFFF)) -#else - if (addrs > (void *) 0xF000 || ((epicsUInt32) addrs & 0xFFF)) -#endif - { - char format[] = "%sbase address = %p ***\n"; - oms_addrs = (char *) OMS_NUM_ADDRS; - errlogPrintf(format, errbase, addrs); - epicsThreadSleep(5.0); - rtncode = ERROR; - } - else - oms_addrs = (char *) addrs; - - omsInterruptVector = vector; - if (vector < 64 || vector > 255) - { - if (vector != 0) - { - char format[] = "%sinterrupt vector = %d ***\n"; - omsInterruptVector = (unsigned) OMS_INT_VECTOR; - errlogPrintf(format, errbase, vector); - epicsThreadSleep(5.0); - rtncode = ERROR; - } - } - - if (int_level < 1 || int_level > 6) - { - char format[] = "%sinterrupt level = %d ***\n"; - omsInterruptLevel = OMS_INT_LEVEL; - errlogPrintf(format, errbase, int_level); - epicsThreadSleep(5.0); - rtncode = ERROR; - } - else - omsInterruptLevel = int_level; - - /* Set motor polling task rate */ - if (scan_rate >= 1 && scan_rate <= 60) - targs.motor_scan_rate = scan_rate; - else - { - char format[] = "%spolling rate = %d Hz ***\n"; - targs.motor_scan_rate = SCAN_RATE; - errlogPrintf(format, errbase, scan_rate); - epicsThreadSleep(5.0); - rtncode = ERROR; - } - - return(rtncode); -} - - -/*****************************************************/ -/* Interrupt service routine. */ -/* motorIsr() */ -/*****************************************************/ -static void motorIsr(int card) -{ - volatile struct controller *pmotorState; - volatile struct vmex_motor *pmotor; - STATUS_REG statusBuf; - epicsUInt8 doneFlags, userIO, slipFlags, limitFlags, cntrlReg; - static char errmsg1[] = "\ndrvOms58.cc:motorIsr: Invalid entry - card xx\n"; - static char errmsg2[] = "\ndrvOms58.cc:motorIsr: command error - card xx\n"; - - if (card >= total_cards || (pmotorState = motor_state[card]) == NULL) - { - errmsg1[47-2] = '0' + card%10; - errmsg1[47-3] = '0' + (card/10)%10; - epicsInterruptContextMessage(errmsg1); - return; - } - - pmotor = (struct vmex_motor *) (pmotorState->localaddr); - - /* Status register - clear irqs on read. */ - statusBuf.All = pmotor->control.statusReg; - - /* Done register - clears on read */ - doneFlags = pmotor->control.doneReg; - - /* UserIO register - clears on read */ - userIO = pmotor->control.ioLowReg; - -/* Questioniable Fix for undefined problem Starts Here. The following - * code is meant to fix a problem that exhibted "spurious" interrupts - * and "stuck in the Oms ISR" behavior. -*/ - /* Slip detection - clear on read */ - slipFlags = pmotor->control.slipReg; - - /* Overtravel - clear on read */ - limitFlags = pmotor->control.limitReg; - - /* Only write control register if update bit is false. */ - /* Assure proper control register settings */ - cntrlReg = pmotor->control.cntrlReg; - if ((cntrlReg & 0x01) == 0) - pmotor->control.cntrlReg = (epicsUInt8) 0x90; -/* Questioniable Fix for undefined problem Ends Here. */ - - /* Motion done handling */ - if (statusBuf.Bits.done) - /* Wake up polling task 'motor_task()' to issue callbacks */ - motor_sem.signal(); - - if (statusBuf.Bits.cmndError) - { - errmsg2[47-2] = '0' + card%10; - errmsg2[47-3] = '0' + (card/10)%10; - epicsInterruptContextMessage(errmsg2); - } -} - -static int motorIsrSetup(int card) -{ -#ifdef vxWorks - volatile struct vmex_motor *pmotor; - long status; - CNTRL_REG cntrlBuf; - - Debug(5, "motorIsrSetup: Entry card#%d\n", card); - - pmotor = (struct vmex_motor *) (motor_state[card]->localaddr); - - status = pdevLibVirtualOS->pDevConnectInterruptVME(omsInterruptVector + card, -#if LT_EPICSBASE(3,14,8,0) - (void (*)()) motorIsr, -#else - (void (*)(void *)) motorIsr, -#endif - (void *) card); - - if (!RTN_SUCCESS(status)) - { - errPrintf(status, __FILE__, __LINE__, "Can't connect to vector %d\n", omsInterruptVector + card); - omsInterruptVector = 0; /* Disable interrupts */ - cntrlBuf.All = 0; - pmotor->control.cntrlReg = cntrlBuf.All; - return(ERROR); - } - - status = devEnableInterruptLevel(OMS_INTERRUPT_TYPE, - omsInterruptLevel); - if (!RTN_SUCCESS(status)) - { - errPrintf(status, __FILE__, __LINE__, "Can't enable enterrupt level %d\n", omsInterruptLevel); - omsInterruptVector = 0; /* Disable interrupts */ - cntrlBuf.All = 0; - pmotor->control.cntrlReg = cntrlBuf.All; - return(ERROR); - } - - /* Setup card for interrupt-on-done */ - pmotor->control.intVector = omsInterruptVector + card; - - /* enable interrupt-when-done irq */ - cntrlBuf.All = 0; - cntrlBuf.Bits.doneIntEna = 1; - cntrlBuf.Bits.intReqEna = 1; - - pmotor->control.cntrlReg = cntrlBuf.All; -#endif - return(OK); -} - -/*****************************************************/ -/* initialize all software and hardware */ -/* motor_init() */ -/*****************************************************/ -static int motor_init() -{ - volatile struct controller *pmotorState; - volatile struct vmex_motor *pmotor; - STATUS_REG statusReg; - epicsInt8 omsReg; - long status; - int card_index, motor_index; - char axis_pos[50], encoder_pos[50]; - char *tok_save, *pos_ptr; - int total_encoders = 0, total_axis = 0, total_pidcnt = 0; - volatile void *localaddr; - void *probeAddr; - - tok_save = NULL; - quantum = epicsThreadSleepQuantum(); - - /* Check for setup */ - if (oms58_num_cards <= 0) - { - Debug(1, "motor_init: *OMS58 driver disabled* \n oms58Setup() is missing from startup script.\n"); - return(ERROR); - } - - /* allocate space for total number of motors */ - motor_state = (struct controller **) malloc(oms58_num_cards * - sizeof(struct controller *)); - - /* allocate structure space for each motor present */ - - total_cards = oms58_num_cards; - - if (epicsAtExit(oms_reset, NULL) == ERROR) - Debug(1, "vme58 motor_init: oms_reset disabled\n"); - - for (card_index = 0; card_index < oms58_num_cards; card_index++) - { - epicsInt8 *startAddr; - epicsInt8 *endAddr; - - Debug(2, "motor_init: card %d\n", card_index); - - probeAddr = oms_addrs + (card_index * OMS_BRD_SIZE); - startAddr = (epicsInt8 *) probeAddr; - endAddr = startAddr + OMS_BRD_SIZE; - - Debug(9, "motor_init: devNoResponseProbe() on addr %p\n", probeAddr); - /* Scan memory space to assure card id */ -#ifdef vxWorks - do - { - status = devNoResponseProbe(OMS_ADDRS_TYPE, (unsigned int) startAddr, 2); - startAddr += 0x100; - } while (PROBE_SUCCESS(status) && startAddr < endAddr); -#endif - if (PROBE_SUCCESS(status)) - { -#ifdef vxWorks - status = devRegisterAddress(__FILE__, OMS_ADDRS_TYPE, - (size_t) probeAddr, OMS_BRD_SIZE, - (volatile void **) &localaddr); - Debug(9, "motor_init: devRegisterAddress() status = %d\n", (int) status); - if (!RTN_SUCCESS(status)) - { - errPrintf(status, __FILE__, __LINE__, "Can't register address 0x%x\n", - (unsigned int) probeAddr); - return(ERROR); - } -#endif - Debug(9, "motor_init: localaddr = %p\n", localaddr); - pmotor = (struct vmex_motor *) localaddr; - - Debug(9, "motor_init: malloc'ing motor_state\n"); - motor_state[card_index] = (struct controller *) malloc(sizeof(struct controller)); - pmotorState = motor_state[card_index]; - pmotorState->localaddr = (char *) localaddr; - pmotorState->motor_in_motion = 0; - pmotorState->cmnd_response = false; - - pmotor->control.cntrlReg = 0; /* Disable all interrupts */ - pmotor->rebootind = 0x4321; /* Set reboot indicator (before send_mess call). */ - - send_mess(card_index, "EF", (char*) NULL); - send_mess(card_index, ERROR_CLEAR, (char*) NULL); - send_mess(card_index, STOP_ALL, (char*) NULL); - - send_mess(card_index, GET_IDENT, (char*) NULL); - recv_mess(card_index, (char *) pmotorState->ident, 1); - Debug(3, "Identification = %s\n", pmotorState->ident); - - send_mess(card_index, ALL_POS, (char*) NULL); - recv_mess(card_index, axis_pos, 1); - - for (total_axis = 0, pos_ptr = epicsStrtok_r(axis_pos, ",", &tok_save); - pos_ptr; pos_ptr = epicsStrtok_r(NULL, ",", &tok_save), total_axis++) - { - pmotorState->motor_info[total_axis].motor_motion = NULL; - pmotorState->motor_info[total_axis].status.All = 0; - } - - Debug(3, "motor_init: Total axis = %d\n", total_axis); - pmotorState->total_axis = total_axis; - - /* Assure done is cleared */ - statusReg.All = pmotor->control.statusReg; - omsReg = pmotor->control.doneReg; - for (total_encoders = total_pidcnt = 0, motor_index = 0; motor_index < total_axis; motor_index++) - { - /* Test if motor has an encoder. */ - send_mess(card_index, ENCODER_QUERY, oms58_axis[motor_index]); - while (!pmotor->control.doneReg) /* Wait for command to complete. */ - epicsThreadSleep(quantum * 2.0); - - statusReg.All = pmotor->control.statusReg; - - if (statusReg.Bits.cmndError) - { - Debug(2, "motor_init: No encoder on axis %d\n", motor_index); - pmotorState->motor_info[motor_index].encoder_present = NO; - } - else - { - total_encoders++; - pmotorState->motor_info[motor_index].encoder_present = YES; - recv_mess(card_index, encoder_pos, 1); - } - - /* Test if motor has PID parameters. */ - send_mess(card_index, PID_QUERY, oms58_axis[motor_index]); - do /* Wait for command to complete. */ - { - epicsThreadSleep(quantum); - statusReg.All = pmotor->control.statusReg; - } while (statusReg.Bits.done == 0); - - - if (statusReg.Bits.cmndError) - { - Debug(2, "motor_init: No PID parameters on axis %d\n", motor_index); - pmotorState->motor_info[motor_index].pid_present = NO; - } - else - { - total_pidcnt++; - pmotorState->motor_info[motor_index].pid_present = YES; - } - } - - /* Enable interrupt-when-done if selected */ - if (omsInterruptVector) - { - if (motorIsrSetup(card_index) == ERROR) - errPrintf(0, __FILE__, __LINE__, "Interrupts Disabled!\n"); - } - - start_status(card_index); - for (motor_index = 0; motor_index < total_axis; motor_index++) - { - pmotorState->motor_info[motor_index].status.All = 0; - pmotorState->motor_info[motor_index].no_motion_count = 0; - pmotorState->motor_info[motor_index].encoder_position = 0; - pmotorState->motor_info[motor_index].position = 0; - - if (pmotorState->motor_info[motor_index].encoder_present == YES) - pmotorState->motor_info[motor_index].status.Bits.EA_PRESENT = 1; - if (pmotorState->motor_info[motor_index].pid_present == YES) - pmotorState->motor_info[motor_index].status.Bits.GAIN_SUPPORT = 1; - - set_status(card_index, motor_index); - - send_mess(card_index, DONE_QUERY, oms58_axis[motor_index]); /* Is this needed??? */ - recv_mess(card_index, axis_pos, 1); - } - - Debug(2, "motor_init: Init Address=%p\n", localaddr); - Debug(3, "motor_init: Total encoders = %d\n", total_encoders); - Debug(3, "motor_init: Total with PID = %d\n", total_pidcnt); - } - else - { - Debug(3, "motor_init: Card NOT found!\n"); - motor_state[card_index] = (struct controller *) NULL; - } - } - - any_motor_in_motion = 0; - - mess_queue.head = (struct mess_node *) NULL; - mess_queue.tail = (struct mess_node *) NULL; - - free_list.head = (struct mess_node *) NULL; - free_list.tail = (struct mess_node *) NULL; - - Debug(3, "Motors initialized\n"); - - -#if (CPU == PPC604 || CPU == PPC603) - /* Work around for intermittent wrong LP data. */ - for (card_index = 0; card_index < oms58_num_cards; card_index++) - { - char *ident_ptr = motor_state[card_index]->ident; - if (strncmp(ident_ptr, "VME58 ver 2.35", 14) == 0) - targs.update_delay = quantum * 2.0; - - if (strncmp(ident_ptr, "VME58 ver 2.24-8S", 17) == 0) - { - double delay = 0.002; /* Set update delay > 2 ms. */ - if (quantum * 2.0 > delay) - delay = quantum * 2.0; - targs.update_delay = delay; - } - } -#endif - - epicsThreadCreate((char *) "Oms58_motor", epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackMedium), - (EPICSTHREADFUNC) motor_task, (void *) &targs); - - Debug(3, "Started motor_task\n"); - return(0); -} - - -/* Disables interrupts. Called on CTL X reboot. */ - -static void oms_reset(void *arg) -{ - short card; - volatile struct vmex_motor *pmotor; - CNTRL_REG cntrlBuf; - - for (card = 0; card < total_cards; card++) - { - if (motor_state[card] != NULL) - { - pmotor = (struct vmex_motor *) motor_state[card]->localaddr; - cntrlBuf.All = pmotor->control.cntrlReg; - cntrlBuf.Bits.intReqEna = 0; - pmotor->control.cntrlReg = cntrlBuf.All; - } - } -} - - -/* Epics iocsh bindings */ - -static const iocshArg oms58Arg0 = {"num_card", iocshArgInt}; -static const iocshArg oms58Arg1 = {"addrs", iocshArgInt}; -static const iocshArg oms58Arg2 = {"vector", iocshArgInt}; -static const iocshArg oms58Arg3 = {"int_level", iocshArgInt}; -static const iocshArg oms58Arg4 = {"scan_rate", iocshArgInt}; - -static const iocshArg* const oms58Args[5] = {&oms58Arg0, &oms58Arg1, &oms58Arg2, &oms58Arg3, &oms58Arg4}; - -static const iocshFuncDef oms58FuncDef = {"oms58Setup", 5, oms58Args}; - -static void oms58CallFunc(const iocshArgBuf* args) -{ - oms58Setup(args[0].ival, (void*) args[1].ival, (unsigned) args[2].ival, args[3].ival, args[4].ival); -} - -void oms58Registrar(void) -{ - iocshRegister(&oms58FuncDef, &oms58CallFunc); -} - -extern "C"{ -epicsExportRegistrar(oms58Registrar); -} - -/*---------------------------------------------------------------------*/ diff --git a/motorApp/OmsSrc/drvOms58.h b/motorApp/OmsSrc/drvOms58.h deleted file mode 100644 index bb1b85a8..00000000 --- a/motorApp/OmsSrc/drvOms58.h +++ /dev/null @@ -1,263 +0,0 @@ -/* -FILENAME... drvOms58.h -USAGE... OMS driver level "include" information that is specific to OMS - model VME58. - -*/ - -/* - * Original Author: Jim Kowalkowski - * Current Author: Joe Sullivan - * Date: 11/14/94 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - * .01 01-18-93 jbk initialized - * .02 11-14-94 jps copy drvOms.c and modify to point to vme58 driver - * ... - * .06 12-07-94 jps first released version w/interrupt supprt - * .07 12-20-94 jps rearrange the device init routines - * .08 05-03-96 jps convert 32bit card accesses to 16bit - vme58PCB - * version D does not support 32bit accesses. - * .09 05-09-97 jps increase maximum card count to 15 - * .10 08-22-01 rls "int" type specifications for all bit-fields. - * .11 03-21-05 rls replace VxWorks specific "uint16_t" with "epicsUInt16". - * .12 01-26-11 rls added reboot flag in DPRAM R/W reserved area. - * - */ - -#ifndef INCdrvOms58h -#define INCdrvOms58h 1 - -#include "drvOmsCom.h" - -/* - * VME58 default profile - */ - -#define OMS_NUM_CARDS 15 -#define OMS_NUM_CHANNELS 8 -#define OMS_NUM_ADDRS 0x4000 -#define OMS_BRD_SIZE 0x1000 /* card address boundary */ - -#define BUFFER_SIZE 256 - -/* Board control register structures */ - - -/* VME58 DUAL-PORT MEMORY MAP */ -typedef struct -{ - epicsUInt16 encPos[2]; - epicsUInt16 cmndPos[2]; - epicsUInt16 cmndVel[2]; - epicsUInt16 accel[2]; - epicsUInt16 maxVel[2]; - epicsUInt16 baseVel[2]; - epicsUInt16 dFltrGain[2]; - epicsUInt16 dFltrPole[2]; - epicsUInt16 dFltrZero[2]; - epicsUInt16 reserved[46]; -} MOTOR_DATA_REGS; - -/* Definitions for VME58 I/O Registers */ - -/* Control Register - Offset = 0x0FE1 */ -typedef union -{ - epicsUInt8 All; - struct - { - unsigned int intReqEna :1; /* Master interrupt request enable */ - unsigned int ioIntEna :1; /* I/O bits 0 and 1 interrupt enable */ - unsigned int directInEna:1; /* Interrupt request to the VME58 ? */ - unsigned int doneIntEna :1; /* Done detect interrupt enable */ - unsigned int otIntEna :1; /* Overtravel detect interrupt enable */ - unsigned int slipIntEna :1; /* Encoder slip detect interrupt enable */ - unsigned int :1; /* Unused */ - unsigned int update :1; /* Data area update request */ - } Bits; -} CNTRL_REG; - -/* Status Register - Offset = 0x0FE3 */ -typedef union -{ - epicsUInt8 All; - struct - { - unsigned int interrupt :1; /* Interrupt dectect */ - unsigned int directIn :1; /* Direct input interrupt detect */ - unsigned int directOut :1; /* Direct ouput interrupt detect */ - unsigned int done :1; /* Motion done detect */ - unsigned int overtravel :1; /* Overtravel detect */ - unsigned int encoderSlip:1; /* Encoder slip detect */ - unsigned int cardOK :1; /* Powerup initilization complete */ - unsigned int cmndError :1; /* Command error dectect */ - } Bits; -} STATUS_REG; - -/* I/O Register(0-7) - Offset = 0x0FE5 */ -typedef union -{ - epicsUInt8 All; - struct - { - unsigned int io_7 :1; /* Bit 7 */ - unsigned int io_6 :1; /* Bit 6 */ - unsigned int io_5 :1; /* Bit 5 */ - unsigned int io_4 :1; /* Bit 4 */ - unsigned int io_3 :1; /* Bit 3 */ - unsigned int io_2 :1; /* Bit 2 */ - unsigned int io_1 :1; /* Bit 1 */ - unsigned int io_0 :1; /* Bit 0 */ - } Bits; -} IO_LOW_REG; - -/* Slip Flag Register - Offset = 0x0FE7 */ -typedef union -{ - epicsUInt8 All; - struct - { - unsigned int slip_s :1; /* status of S axis */ - unsigned int slip_r :1; /* status of R axis */ - unsigned int slip_v :1; /* status of V axis */ - unsigned int slip_u :1; /* status of U axis */ - unsigned int slip_t :1; /* status of T axis */ - unsigned int slip_z :1; /* status of Z axis */ - unsigned int slip_y :1; /* status of Y axis */ - unsigned int slip_x :1; /* status of X axis */ - } Bits; -} SLIP_REG; - -/* Done Flag Register - Offset = 0x0FE9 */ -typedef union -{ - epicsUInt8 All; - struct - { - unsigned int done_s :1; /* status of S axis */ - unsigned int done_r :1; /* status of R axis */ - unsigned int done_v :1; /* status of V axis */ - unsigned int done_u :1; /* status of U axis */ - unsigned int done_t :1; /* status of T axis */ - unsigned int done_z :1; /* status of Z axis */ - unsigned int done_y :1; /* status of Y axis */ - unsigned int done_x :1; /* status of X axis */ - } Bits; -} DONE_REG; - -/* I/O High Register(8-13) - Offset = 0x0FEB */ -typedef union -{ - epicsUInt8 All; - struct - { - unsigned int :1; /* Unused */ - unsigned int :1; /* Unused */ - unsigned int io_13 :1; /* Bit 13 */ - unsigned int io_12 :1; /* Bit 12 */ - unsigned int io_11 :1; /* Bit 11 */ - unsigned int io_10 :1; /* Bit 10 */ - unsigned int io_9 :1; /* Bit 9 */ - unsigned int io_8 :1; /* Bit 8 */ - } Bits; -} IO_HIGH_REG; - - -/* Limit Switch Status Register - Offset = 0x0FED */ -typedef union -{ - epicsUInt8 All; - struct - { - unsigned int limit_s :1; /* status of S axis */ - unsigned int limit_r :1; /* status of R axis */ - unsigned int limit_v :1; /* status of V axis */ - unsigned int limit_u :1; /* status of U axis */ - unsigned int limit_t :1; /* status of T axis */ - unsigned int limit_z :1; /* status of Z axis */ - unsigned int limit_y :1; /* status of Y axis */ - unsigned int limit_x :1; /* status of X axis */ - } Bits; -} LIMIT_REG; - -/* Home Switch Status Register - Offset = 0x0FEF */ -typedef union -{ - epicsUInt8 All; - struct - { - unsigned int home_s :1; /* status of S axis */ - unsigned int home_r :1; /* status of R axis */ - unsigned int home_v :1; /* status of V axis */ - unsigned int home_u :1; /* status of U axis */ - unsigned int home_t :1; /* status of T axis */ - unsigned int home_z :1; /* status of Z axis */ - unsigned int home_y :1; /* status of Y axis */ - unsigned int home_x :1; /* status of X axis */ - } Bits; -} HOME_REG; - -typedef struct -{ - epicsUInt8 unused00; - epicsUInt8 cntrlReg; /* Control Register - Read/Write */ - epicsUInt8 unused02; - epicsUInt8 statusReg; /* Status Register - Read */ - epicsUInt8 unused04; - epicsUInt8 ioLowReg; /* IO bits 0-7 status register - Read */ - epicsUInt8 unused06; - epicsUInt8 slipReg; /* Encoder slip status register - Read */ - epicsUInt8 unused08; - epicsUInt8 doneReg; /* Axis done status register - Read */ - epicsUInt8 unused0A; - epicsUInt8 ioHighReg; /* IO bits 8-13 status register - Read */ - epicsUInt8 unused0C; - epicsUInt8 limitReg; /* Limit switch status register - Read */ - epicsUInt8 unused0E; - epicsUInt8 homeReg; /* Home switch status register - Read */ - epicsUInt8 unusedF0; - epicsUInt8 intVector; /* Interrupt vector */ -} MOTOR_CNTRL_REGS; - - -/* OMS VME dual port memory map */ -struct vmex_motor -{ /* Offset */ - epicsInt16 inPutIndex; /* 0x0000 */ - epicsInt16 outGetIndex; /* 0x0002 */ - epicsInt16 inBuffer[BUFFER_SIZE]; /* 0x0004 */ - epicsInt16 reserved0[254]; /* 0x0204 */ - MOTOR_DATA_REGS data[OMS_NUM_CHANNELS]; /* 0x0400 */ - epicsInt16 outPutIndex; /* 0x0800 */ - epicsInt16 inGetIndex; /* 0x0802 */ - epicsInt16 outBuffer[BUFFER_SIZE]; /* 0x0804 */ - epicsInt16 rebootind; /* 0x0A04 - used by driver to - * test for board reboot. */ - epicsInt16 reserved1[749]; /* 0x0A06 */ - MOTOR_CNTRL_REGS control; /* 0x0FE0 */ -}; - -#endif /* INCdrvOms58h */ diff --git a/motorApp/OmsSrc/drvOmsCom.h b/motorApp/OmsSrc/drvOmsCom.h deleted file mode 100644 index 6e837de5..00000000 --- a/motorApp/OmsSrc/drvOmsCom.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -FILENAME... drvOmsCom.h -USAGE... This file contains OMS driver "include" information - that is common to all OMS models. - -*/ - -/* - * Original Author: Ron Sluiter - * Date: 12/18/98 - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - */ - -#ifndef INCdrvOmsComh -#define INCdrvOmsComh 1 - -#include "motordrvCom.h" - -#ifdef __LP64__ -typedef long long motorUInt64; -#endif - -/* Default profile. */ - -#define OMS_INTERRUPT_TYPE intVME -#define OMS_ADDRS_TYPE atVMEA16 -#define OMS_INT_VECTOR 180 /* default interrupt vector (64-255) */ -#define OMS_INT_LEVEL 5 /* default interrupt level (1-6) */ - -/* OMS Command strings. */ -#define AXIS_STOP "ST" -#define GET_IDENT "WY" -#define ERROR_CLEAR "IC" -#define STOP_ALL "AA SA" -#define ALL_POS "AA RP" - -struct encoder_status -{ - char slip_enable; - char pos_enable; - char slip_detect; - char pos_dead; - char axis_home; - char unused; -}; - -#endif /* INCdrvOmsComh */ diff --git a/motorApp/OmsSrc/drvOmsPC68.cc b/motorApp/OmsSrc/drvOmsPC68.cc deleted file mode 100644 index 1582ccdd..00000000 --- a/motorApp/OmsSrc/drvOmsPC68.cc +++ /dev/null @@ -1,960 +0,0 @@ -/* -FILENAME... drvOmsPC68.cc -USAGE... Motor record driver level support for OMS PC68 serial device. - -*/ - -/* - * Original Author: Brian Tieman - * Current Author: Ron Sluiter - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * - * NOTES - * ----- - * Verified with firmware: - * - PC78 ver 1.14-46 - * - PC68 ver 6.51-2008 - * - The data parameter passed to asynCallback() is represented as follows: - * - * +-------------------------------------+ - * | Interrupt counter | Status | Done | - * +-------------------------------------+ - * - * Where: - * - Interrupt counter - 16bits - Number of interrupts - * - Status register - 8bits - Status information - * - Done register - 8bits - Axis done status - * - * More information can be found in the User Manual, ICMS document APS_1251701. - * - * - * Modification Log: - * ----------------- - * .01 02/07/06 dmk - modified motor_init() to skip the encoder query if the - * controller has been configured for no encoder. - * .02 04/24/06 rls - support for both PC68 and PC78. - * - test for encoder support. - * - test for servo support. - * .03 08/11/06 rls - work around for erroneous response after response to - * "?KP" command at boot-up; resulted in 1st axis having - * same position (RP command) as last axis. - * .04 02/09/07 dmk - modified to support interrupts. - * .05 02/15/08 dmk - removed unnecessary variants in asynCallback() and - * added notes. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "motor.h" -#include "drvOmsPC68Com.h" -#include "epicsExport.h" - -#define PC68_MAX_NUM_CARDS (10) /* Maximum # of cards. */ -#define BUFF_SIZE (100) /* Maximum length of command string */ - -#define TIMEOUT (2.0) /* Command timeout in sec. */ - -/*----------------debugging-----------------*/ -volatile int drvOmsPC68debug = 0; -extern "C" {epicsExportAddress(int, drvOmsPC68debug);} -static inline void Debug(int level, const char *format, ...) { - #ifdef DEBUG - if (level < drvOmsPC68debug) { - va_list pVar; - va_start(pVar, format); - vprintf(format, pVar); - va_end(pVar); - } - #endif -} - -/* --- Global data. --- */ -int OmsPC68_num_cards = 0; - -/* Local data required for every driver; see "motordrvComCode.h" */ -#include "motordrvComCode.h" - -static volatile int motionTO = 10; - -//OmsPC68 generic controller commands -static char *oms_axis[] = {"X", "Y", "Z", "T", "U", "V", "R", "S"}; - - -/*----------------functions-----------------*/ -static int recv_mess(int, char *, int); -static RTN_STATUS send_mess(int, char const *, char *name); -static void start_status(int card); -static int set_status(int card, int signal); -static long report(int level); -static long init(); -static int motor_init(); -static void query_done(int, int, struct mess_node *); - -/*----------------functions-----------------*/ -static int omsGet(int card, char *pcom); - -struct driver_table OmsPC68_access = -{ - motor_init, - motor_send, - motor_free, - motor_card_info, - motor_axis_info, - &mess_queue, - &queue_lock, - &free_list, - &freelist_lock, - &motor_sem, - &motor_state, - &total_cards, - &any_motor_in_motion, - send_mess, - recv_mess, - set_status, - query_done, - start_status, - &initialized, - oms_axis -}; - -struct -{ - long number; - long (*report) (int); - long (*init) (void); -} drvOmsPC68 = {2, report, init}; - -extern "C" {epicsExportAddress(drvet, drvOmsPC68);} - -static struct thread_args targs = {SCAN_RATE, &OmsPC68_access, 0.0}; - -//_____________________________________________________________________________ -/********************************************************* - * Print out driver status report - *********************************************************/ -static long report(int level) -{ - int card; - - if (OmsPC68_num_cards <= 0) - printf(" No MDrive controllers configured.\n"); - else - { - for (card = 0; card < OmsPC68_num_cards; card++) - { - struct controller *brdptr = motor_state[card]; - - if (brdptr == NULL) - printf(" PC68 controller %d connection failed.\n", card); - else - { - struct OmsPC68controller *cntrl; - - cntrl = (struct OmsPC68controller *) brdptr->DevicePrivate; - printf(" PC68 controller #%d, port=%s, id: %s - err %d\n", card, - cntrl->asyn_port, brdptr->ident,cntrl->errcnt); - } - } - } - return(OK); -} - - -//_____________________________________________________________________________ - -static long init() -{ - /* Check for setup */ - if (OmsPC68_num_cards <= 0) - { - Debug(1, "init(): OmsPC68 driver disabled.\n"); - Debug(1, "init(): OmsPC68Setup() missing from startup script.\n"); - } - - motor_init (); - initialized = true; - return(0); -} - -//_____________________________________________________________________________ - -static void query_done(int card, int axis, struct mess_node *nodeptr) -{ -} - -/********************************************************* - * Read the status and position of all motors on a card - * start_status(int card) - * if card == -1 then start all cards - *********************************************************/ -static void start_status(int card) -{ -} -//_____________________________________________________________________________ -/************************************************************** - * Parse status and position strings for a card and signal - * set_status() - ************************************************************/ -static int set_status(int card, int signal) -{ - struct OmsPC68controller *cntrl; - struct mess_info *motor_info; - struct mess_node *nodeptr; - char *p, *tok_save; - struct axis_status *ax_stat; - struct encoder_status *en_stat; - char q_buf[50], outbuf[50]; - int index, motorData, rtn_state; - bool ls_active = false; - msta_field status; - - cntrl = (struct OmsPC68controller *) motor_state[card]->DevicePrivate; - motor_info = &(motor_state[card]->motor_info[signal]); - nodeptr = motor_info->motor_motion; - status.All = motor_info->status.All; - - if (cntrl->status != NORMAL) - recv_mess(card, q_buf, FLUSH); - - if (motor_state[card]->motor_info[signal].encoder_present == YES) - { - /* get 4 peices of info from axis */ - send_mess(card, ALL_INFO, oms_axis[signal]); - rtn_state = recv_mess(card, q_buf, 4); - } - else - { - send_mess(card, AXIS_INFO, oms_axis[signal]); - rtn_state = recv_mess(card, q_buf, 2); - } - - if (rtn_state > 0) - { - cntrl->status = NORMAL; - status.Bits.CNTRL_COMM_ERR = 0; - } - else - { - if (cntrl->status == NORMAL) - { - cntrl->status = RETRY; - rtn_state = OK; - goto exit; - } - else - { - cntrl->status = COMM_ERR; - status.Bits.CNTRL_COMM_ERR = 1; - status.Bits.RA_PROBLEM = 1; - rtn_state = 1; - goto exit; - } - } - - Debug(5, "info = (%s)\n", q_buf); - - for (index = 0, p = epicsStrtok_r(q_buf, ",", &tok_save); p; - p = epicsStrtok_r(NULL, ",", &tok_save), index++) - { - switch (index) - { - case 0: - /* axis status */ - ax_stat = (struct axis_status *) p; - - status.Bits.RA_DIRECTION = (ax_stat->direction == 'P') ? 1 : 0; - status.Bits.RA_DONE = (ax_stat->done == 'D') ? 1 : 0; - status.Bits.RA_HOME = (ax_stat->home == 'H') ? 1 : 0; - - if (ax_stat->overtravel == 'L') - { - ls_active = true; - if (status.Bits.RA_DIRECTION) - status.Bits.RA_PLUS_LS = 1; - else - status.Bits.RA_MINUS_LS = 1; - } - else - { - ls_active = false; - status.Bits.RA_PLUS_LS = 0; - status.Bits.RA_MINUS_LS = 0; - } - - break; - case 1: - /* motor pulse count (position) */ - sscanf(p, "%index", &motorData); - - if (motorData == motor_info->position) - { - /* Increment counter only if motor is moving. */ - if (nodeptr != 0) - motor_info->no_motion_count++; - } - else - { - motor_info->no_motion_count = 0; - motor_info->position = motorData; - } - - if (motor_info->no_motion_count > motionTO) - { - status.Bits.RA_PROBLEM = 1; - send_mess(card, AXIS_STOP, oms_axis[signal]); - motor_info->no_motion_count = 0; - errlogSevPrintf(errlogMinor, - "Motor motion timeout ERROR on card: %d, signal: %d\n", card, - signal); - } - else - status.Bits.RA_PROBLEM = 0; - - break; - case 2: - { - /* encoder pulse count (position) */ - int temp; - - sscanf(p, "%index", &temp); - motor_info->encoder_position = (epicsInt32) temp; - } - break; - case 3: - /* encoder status */ - en_stat = (struct encoder_status *) p; - status.Bits.EA_SLIP = (en_stat->slip_enable == 'E') ? 1 : 0; - status.Bits.EA_POSITION = (en_stat->pos_enable == 'E') ? 1 : 0; - status.Bits.EA_SLIP_STALL = (en_stat->slip_detect == 'S') ? 1 : 0; - status.Bits.EA_HOME = (en_stat->axis_home == 'H') ? 1 : 0; - break; - default: - break; - } - } - - /* - * jps: Velocity should be set based on the actual velocity returned from - * the 'RV' command (See drvOms58.c). But the polling task does not have - * time to request additional information so the velocity is set to - * indicate moving or not-moving. - */ - if (status.Bits.RA_DONE) - motor_info->velocity = 0; - else - motor_info->velocity = 1; - - if (!(status.Bits.RA_DIRECTION)) - motor_info->velocity *= -1; - - rtn_state = (!motor_info->no_motion_count || ls_active == true || - status.Bits.RA_DONE | status.Bits.RA_PROBLEM) ? 1 : 0; - - /* Test for post-move string. */ - if ((status.Bits.RA_DONE || ls_active == true) && (nodeptr != 0) && - (nodeptr->postmsgptr != 0)) - { - char buffer[40]; - - /* Test for a "device directive" in the POST string. */ - if (nodeptr->postmsgptr[0] == '@') - { - bool errind = false; - char *end = strchr(&nodeptr->postmsgptr[1], '@'); - - if (end == NULL) - errind = true; - else - { - DBADDR addr; - char *start, *tail; - int size = (end - &nodeptr->postmsgptr[0]) + 1; - - /* Copy device directive to buffer. */ - strncpy(buffer, nodeptr->postmsgptr, size); - buffer[size] = '\0'; - - if (strncmp(buffer, "@PUT(", 5) != 0) - goto errorexit; - - /* Point "start" to PV name argument. */ - tail = NULL; - start = epicsStrtok_r(&buffer[5], ",", &tail); - if (tail == NULL) - goto errorexit; - - if (dbNameToAddr(start, &addr)) /* Get address of PV. */ - { - errPrintf(-1, __FILE__, __LINE__, "Invalid PV name: %s", - start); - goto errorexit; - } - - /* Point "start" to PV value argument. */ - start = epicsStrtok_r(NULL, ")", &tail); - if (dbPutField(&addr, DBR_STRING, start, 1L)) - { - errPrintf(-1, __FILE__, __LINE__, "invalid value: %s", - start); - goto errorexit; - } - } - - if (errind == true) -errorexit: errMessage(-1, "Invalid device directive"); - end++; - strcpy(buffer, end); - } - else - strcpy(buffer, nodeptr->postmsgptr); - - strcpy(outbuf, buffer); - send_mess(card, outbuf, oms_axis[signal]); - nodeptr->postmsgptr = NULL; - } - -exit: - motor_info->status.All = status.All; /* Update status from local copy. */ - return(rtn_state); -} - - -//_____________________________________________________________________________ -/*****************************************************/ -/* send a message to the OmsPC68 board */ -/* send_mess() */ -/*****************************************************/ -static RTN_STATUS send_mess(int card, char const *com, char *name) -{ - struct OmsPC68controller *cntrl; - size_t size, - nwrite; - int error_code; - char outbuf[MAX_MSG_SIZE]; - - if (!motor_state[card]) - { - errlogPrintf("drvOmsPC68.c:send_mess() - invalid card #%d\n", card); - return(ERROR); - } - - if (name == NULL) - strcpy(outbuf, com); - else - { - strcpy(outbuf, "A"); - strcat(outbuf, name); - strcat(outbuf, " "); - strcat(outbuf, com); - } - - size = strlen (outbuf); - if (size > MAX_MSG_SIZE) - { - errlogMessage("drvOmsPC68.c:send_mess(); message size violation.\n"); - return(ERROR); - } - else - if (size == 0) /* Normal exit on empty input message. */ - return(OK); - - Debug(2, "send_mess(): message = %s\n", com); - - cntrl = (struct OmsPC68controller *) motor_state[card]->DevicePrivate; - - error_code = cntrl->pasynOctet->write(cntrl->octetPvt,cntrl->pasynUser,outbuf,size,&nwrite); - if (error_code == OK) - { - Debug(4, "sent message: (%s)\n", outbuf); - } - else - { - Debug(4, "unable to send message (%s)\n", outbuf); - } - return(OK); -} - - -/* - * FUNCTION... recv_mess(int card, char *com, int amount) - * - * INPUT ARGUMENTS... - * card - controller card # (0,1,...). - * *com - caller's response buffer. - * amount | -1 = flush controller's output buffer. - * | >= 1 = the # of command responses to retrieve into caller's - * response buffer. - * - * LOGIC... - * IF controller card does not exist. - * ERROR RETURN. - * ENDIF - * IF "amount" indicates buffer flush. - * WHILE characters left in input buffer. - * Call omsGet(). - * ENDWHILE - * ENDIF - * - * FOR each message requested (i.e. "amount"). - * Initialize head and tail pointers. - * Initialize retry counter and state indicator. - * WHILE retry count not exhausted, AND, state indicator is NOT at END. - * IF characters left in controller's input buffer. - * Process input character. - * ELSE IF command error occured - call omsError(). - * ERROR RETURN. - * ENDIF - * ENDWHILE - * IF retry count exhausted. - * Terminate receive buffer. - * ERROR RETURN. - * ENDIF - * Terminate command response. - * ENDFOR - * - * IF commands processed. - * Terminate response buffer. - * ELSE - * Clear response buffer. - * ENDIF - * NORMAL RETURN. - */ - -static int recv_mess(int card, char *com, int amount) -{ - struct OmsPC68controller *cntrl; - int itera, trys, piece, head_size, tail_size; - char inchar; - - inchar = '\0'; - - /* Check that card exists */ - if (card >= total_cards) - { - Debug(1, "recv_mess - invalid card #%d\n", card); - return(-1); - } - - if (amount == -1) - { - /* Process request to flush receive queue */ - Debug(7, "recv flush -------------"); - cntrl = (struct OmsPC68controller *) motor_state[card]->DevicePrivate; - cntrl->pasynOctet->flush(cntrl->octetPvt,cntrl->pasynUser); - return(0); - } - - for (itera = 0; amount > 0; amount--) - { - Debug(7, "-------------"); - head_size = 0; - tail_size = 0; - - for (piece = 0, trys = 0; piece < 3 && trys < 3; trys++) - { - if (omsGet(card, &inchar)) - { - Debug(7, "%02x", inchar); - - switch (piece) - { - case 0: /* header */ - if (inchar == '\n' || inchar == '\r') - head_size++; - else if ((inchar == '#') || //command error - (inchar == '$') || //motor slip - (inchar == '@') || //over travel - (inchar == '!')) //done - { - if (inchar == '#') - { - Debug(4, "command error: card %d\n", card); - return(-1); - } - head_size++; - } - else - { - piece++; - com[itera++] = inchar; - } - break; - case 1: /* body */ - if (inchar == '\n' || inchar == '\r') - { - piece++; - tail_size++; - } - else - com[itera++] = inchar; - break; - - case 2: /* trailer */ - tail_size++; - if (tail_size >= head_size) - piece++; - break; - } - - trys = 0; - } - } - Debug(7, "-------------\n"); - if (trys >= 3) - { - Debug(1, "Timeout occurred in recv_mess\n"); - com[itera] = '\0'; - return(0); - } - com[itera++] = ','; - } - - if (itera > 0) - com[itera - 1] = '\0'; - else - com[itera] = '\0'; - - Debug(4, "recv_mess: card %d, msg: (%s)\n", card, com); - return(itera); -} - - -/*****************************************************/ -/* Get next character from OMS input buffer */ -/* omsGet() */ -/*****************************************************/ -static int omsGet(int card, char *pchar) -{ - int eomReason; - size_t nread; - asynStatus status; - struct OmsPC68controller *cntrl; - - cntrl = (struct OmsPC68controller *) motor_state[card]->DevicePrivate; - status = cntrl->pasynOctet->read(cntrl->octetPvt,cntrl->pasynUser,pchar,1,&nread,&eomReason); - - return(nread); -} - -static void asynCallback(void *drvPvt,asynUser *pasynUser,char *data,size_t len, int eomReason) -{ - int d,stat; - OmsPC68controller* pcntrl; - struct controller* pstate; - - pcntrl = (OmsPC68controller*)drvPvt; - pstate = motor_state[pcntrl->card]; - - if( pcntrl->card >= total_cards || pstate == NULL ) - { - errlogPrintf("Invalid entry-card #%d\n", pcntrl->card); - return; - } - - d = *(int*)data; - stat = (d & 0x0000FF00) >> 8; - - if( stat & STAT_DONE ) - if( stat & STAT_ERROR_MSK ) - ++pcntrl->errcnt; - else - motor_sem.signal(); - -//printf("drvOmsPC68:asynCallback - card %2.2d, error %d, status 0x%8.8X\n",pcntrl->card,pcntrl->errcnt,d); - -} -//_____________________________________________________________________________ -/*****************************************************/ -/* initialize all software and hardware */ -/* This is called from the initialization routine in */ -/* device support. */ -/* motor_init() */ -/*****************************************************/ -static int motor_init() -{ - volatile struct controller* pmotorState; - struct OmsPC68controller* cntrl; - int card_index, status, success_rtn, total_axis, motor_index; - char axis_pos[50], encoder_pos[50], *tok_save, *pos_ptr; - asynUser *pasynUser; - asynInterface *pasynInterface; - - /* Check for setup */ - if (OmsPC68_num_cards <= 0) - { - Debug(1, "motor_init: OmsPC68 driver disabled* \n"); - Debug(1, "motor_init: OmsPC68Setup() is missing from startup script.\n"); - return(ERROR); - } - - total_cards = OmsPC68_num_cards; - - for (card_index=0;card_indexDevicePrivate; - - pasynUser = pasynManager->createAsynUser(0,0); - pasynUser->userPvt = cntrl; - cntrl->pasynUser = pasynUser; - - success_rtn = pasynManager->connectDevice(pasynUser,cntrl->asyn_port,0); - if( success_rtn ) - { - Debug(1,"can't connect to port %s: %s\n",cntrl->asyn_port,pasynUser->errorMessage); - return(ERROR); - } - - pasynInterface = pasynManager->findInterface(pasynUser,asynOctetType,1); - if( pasynInterface ) - { - cntrl->pasynOctet = (asynOctet*)pasynInterface->pinterface; - cntrl->octetPvt = pasynInterface->drvPvt; - } - else - { - Debug(1,"%s driver not supported\n",asynOctetType); - return(ERROR); - } - - success_rtn = cntrl->pasynOctet->registerInterruptUser(cntrl->octetPvt,pasynUser,asynCallback,cntrl,&cntrl->registrarPvt); - if( success_rtn ) - { - Debug(1,"registerInterruptUser failed - %s: %s\n",cntrl->asyn_port,pasynUser->errorMessage); - return(ERROR); - } - - if (success_rtn == asynSuccess) - { - int retry = 0; - - /* Send a message to the board, see if it exists */ - /* flush any junk at input port - should be no data available */ - cntrl->pasynOctet->flush(cntrl->octetPvt,cntrl->pasynUser); - - /* Try 3 times to connect to controller. */ - do - { - send_mess (card_index, GET_IDENT, (char*) NULL); - status = recv_mess(card_index, (char *) pmotorState->ident, 1); - retry++; - } while (status == 0 && retry < 3); - - Debug(3, "Identification = %s\n", pmotorState->ident); - } - - if (success_rtn == asynSuccess && status > 0) - { - pmotorState->motor_in_motion = 0; - pmotorState->cmnd_response = false; - - send_mess (card_index, ECHO_OFF, (char*) NULL); - send_mess (card_index, ERROR_CLEAR, (char*) NULL); - send_mess (card_index, STOP_ALL, (char*) NULL); - - send_mess (card_index, ALL_POS, (char*) NULL); - recv_mess (card_index, axis_pos, 1); - - for (total_axis = 0, pos_ptr = epicsStrtok_r(axis_pos, ",", &tok_save); - pos_ptr; pos_ptr = epicsStrtok_r(NULL, ",", &tok_save), - total_axis++) - { - pmotorState->motor_info[total_axis].motor_motion = NULL; - pmotorState->motor_info[total_axis].status.All = 0; - } - - Debug(3, "Total axis = %d\n", total_axis); - pmotorState->total_axis = total_axis; - - for (motor_index = 0; motor_index < total_axis; motor_index++) - { - send_mess(card_index, ENCODER_QUERY, oms_axis[motor_index]); - if (recv_mess(card_index, encoder_pos, 1) == -1) - pmotorState->motor_info[motor_index].encoder_present = NO; - else - pmotorState->motor_info[motor_index].encoder_present = YES; - - /* Test if motor has PID parameters. */ - send_mess(card_index, PID_QUERY, oms_axis[motor_index]); - if (recv_mess(card_index, encoder_pos, 1) == -1) - pmotorState->motor_info[motor_index].pid_present = NO; - else - pmotorState->motor_info[motor_index].pid_present = YES; - } - - /* Testing for PID parameters (?KP) causes erroneous response from - * "report position" command at boot-up. Work around is the following - * dummy communication transaction. - */ - - send_mess (card_index, ALL_POS, (char*) NULL); - recv_mess (card_index, axis_pos, 1); - - for (motor_index=0;motor_indexmotor_info[motor_index].status.All = 0; - pmotorState->motor_info[motor_index].no_motion_count = 0; - pmotorState->motor_info[motor_index].encoder_position = 0; - pmotorState->motor_info[motor_index].position = 0; - - if (pmotorState->motor_info[motor_index].encoder_present == YES) - pmotorState->motor_info[motor_index].status.Bits.EA_PRESENT = 1; - if (pmotorState->motor_info[motor_index].pid_present == YES) - pmotorState->motor_info[motor_index].status.Bits.GAIN_SUPPORT = 1; - - set_status (card_index, motor_index); - } - } - else - motor_state[card_index] = (struct controller *) NULL; - } - - any_motor_in_motion = 0; - - mess_queue.head = (struct mess_node *) NULL; - mess_queue.tail = (struct mess_node *) NULL; - - free_list.head = (struct mess_node *) NULL; - free_list.tail = (struct mess_node *) NULL; - - Debug(3, "Motors initialized\n"); - epicsThreadCreate((char *) "OmsPC68_motor", epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackMedium), - (EPICSTHREADFUNC) motor_task, (void *) &targs); - Debug(3, "Started motor_task\n"); - - return(0); -} - -//_____________________________________________________________________________ -/*****************************************************/ -/* Setup system configuration */ -/* OmsPC68Setup() */ -/*****************************************************/ -RTN_STATUS OmsPC68Setup (int num_cards, int scan_rate) -{ - int itera; - - if (num_cards < 1 || num_cards > PC68_MAX_NUM_CARDS) - OmsPC68_num_cards = PC68_MAX_NUM_CARDS; - else - OmsPC68_num_cards = num_cards; - - /* Set motor polling task rate */ - if (scan_rate >= 1 && scan_rate <= 60) - targs.motor_scan_rate = scan_rate; - else - targs.motor_scan_rate = SCAN_RATE; - - /* - * Allocate space for motor_state structures. Note this must be done - * before OmsPC68Config is called, so it cannot be done in motor_init() - * This means that we must allocate space for a card without knowing - * if it really exists, which is not a serious problem - */ - motor_state = (struct controller **) - malloc(OmsPC68_num_cards * sizeof(struct controller *)); - - for (itera = 0; itera < OmsPC68_num_cards; itera++) - motor_state[itera] = (struct controller *) NULL; - - return(OK); -} -//___________________________________________ -/*******************************************/ -/* Configure a controller */ -/* OmsPC68Config() */ -/* */ -/* Recieves: */ -/* card - card being configured */ -/* name - asyn port name */ -/*******************************************/ -RTN_STATUS OmsPC68Config(int card, const char *name) -{ - struct OmsPC68controller *cntrl; - - if (card < 0 || card >= OmsPC68_num_cards) - return(ERROR); - - motor_state[card] = (struct controller*)calloc(1,sizeof(struct controller)); - motor_state[card]->DevicePrivate = calloc(1,sizeof(struct OmsPC68controller)); - cntrl = (struct OmsPC68controller*) motor_state[card]->DevicePrivate; - - cntrl->card = card; - strcpy(cntrl->asyn_port,name); - return(OK); -} - - -extern "C" -{ - -// Setup arguments - static const iocshArg setupArg0 = {"Maximum # of cards", iocshArgInt}; - static const iocshArg setupArg1 = {"Polling rate (HZ)", iocshArgInt}; -// Config arguments - static const iocshArg configArg0 = {"Card# being configured", iocshArgInt}; - static const iocshArg configArg1 = {"asyn port name", iocshArgString}; - - static const iocshArg *const SetupArgs[2] = {&setupArg0, &setupArg1}; - static const iocshArg *const ConfigArgs[2] = {&configArg0, &configArg1}; - - static const iocshFuncDef setupOmsPC68 = {"OmsPC68Setup", 2, SetupArgs}; - static const iocshFuncDef configOmsPC68 = {"OmsPC68Config", 2, ConfigArgs}; - - static void setupOmsPC68CallFunc(const iocshArgBuf *args) - { - OmsPC68Setup(args[0].ival, args[1].ival); - } - static void configOmsPC68CallFunc (const iocshArgBuf *args) - { - OmsPC68Config(args[0].ival, args[1].sval); - } - - static void OmsPC68Register(void) - { - iocshRegister(&setupOmsPC68, setupOmsPC68CallFunc); - iocshRegister(&configOmsPC68, configOmsPC68CallFunc); - } - - epicsExportRegistrar(OmsPC68Register); - -} // extern "C" - - -//_____________________________________________________________________________ diff --git a/motorApp/OmsSrc/drvOmsPC68Com.h b/motorApp/OmsSrc/drvOmsPC68Com.h deleted file mode 100644 index 95b05353..00000000 --- a/motorApp/OmsSrc/drvOmsPC68Com.h +++ /dev/null @@ -1,107 +0,0 @@ -/* -FILENAME... drvOmsPC68Com.h -USAGE... This file contains information common to all OMS PC68/78 controllers. - -*/ - -/* - * Original Author: Brian Tieman - * Current Author: Ron Sluiter - * - * Experimental Physics and Industrial Control System (EPICS) - * - * Copyright 1991, the Regents of the University of California, - * and the University of Chicago Board of Governors. - * - * This software was produced under U.S. Government contracts: - * (W-7405-ENG-36) at the Los Alamos National Laboratory, - * and (W-31-109-ENG-38) at Argonne National Laboratory. - * - * Initial development by: - * The Controls and Automation Group (AT-8) - * Ground Test Accelerator - * Accelerator Technology Division - * Los Alamos National Laboratory - * - * Co-developed with - * The Controls and Computing Group - * Accelerator Systems Division - * Advanced Photon Source - * Argonne National Laboratory - * - * Modification Log: - * ----------------- - */ - -#ifndef INCdrvOmsPC68Comh -#define INCdrvOmsPC68Comh 1 - -#include "motor.h" -#include "motordrvCom.h" -#include "asynDriver.h" -#include "asynOctet.h" - -/* status register */ -#define STAT_IRQ 0x80 -#define STAT_TRANS_BUF_EMPTY 0x40 -#define STAT_INPUT_BUF_FULL 0x20 -#define STAT_DONE 0x10 -#define STAT_OVERTRAVEL 0x08 -#define STAT_ENCODER_REQ 0x04 -#define STAT_UNUSED 0x02 -#define STAT_ERROR 0x01 -#define STAT_ERROR_MSK 0x0F - -/* done flag register */ -#define DONE_X 0x01 -#define DONE_Y 0x02 -#define DONE_Z 0x04 -#define DONE_T 0x08 -#define DONE_U 0x10 -#define DONE_V 0x20 -#define DONE_R 0x40 -#define DONE_S 0x80 - -/* OmsPC68 specific data is stored in this structure. */ -struct OmsPC68controller -{ - int card; - int errcnt; - char asyn_port[80]; /* asyn port name */ - CommStatus status; /* Controller communication status. */ - asynUser* pasynUser; - asynOctet* pasynOctet; - void* octetPvt; - void* registrarPvt; -}; - - -struct encoder_status -{ - char slip_enable; - char pos_enable; - char slip_detect; - char pos_dead; - char axis_home; - char unused; -}; - - -#define ECHO_OFF "EF" -#define AXIS_STOP "ST" -#define GET_IDENT "WY" -#define ERROR_CLEAR "IC" -#define STOP_ALL "AA SA" -#define ALL_POS "AA RP" -#define ALL_INFO "QA RP RE EA" -#define AXIS_INFO "QA RP" -#define ENCODER_QUERY "EA" -#define DONE_QUERY "RA" -#define PID_QUERY "?KP" - -/* Function prototypes. */ -extern RTN_STATUS OmsPC68Setup(int, int); -extern RTN_STATUS OmsPC68Config(int, const char *); - -#endif /* INCdrvOmsPC68Comh */ - diff --git a/motorExApp/NoAsyn/Makefile b/motorExApp/NoAsyn/Makefile index c2dc6937..fc1730fc 100644 --- a/motorExApp/NoAsyn/Makefile +++ b/motorExApp/NoAsyn/Makefile @@ -35,7 +35,6 @@ NoAsynVx_SRCS += NoAsynVx_registerRecordDeviceDriver.cpp #!COMMONLIBS += MXmotor COMMONLIBS += softMotor ifeq ($(OS_CLASS), vxWorks) -COMMONLIBS += oms COMMONLIBS += DeltaTau endif COMMONLIBS += motor diff --git a/motorExApp/NoAsyn/MiscVx.dbd b/motorExApp/NoAsyn/MiscVx.dbd index c170aee0..3bd03290 100644 --- a/motorExApp/NoAsyn/MiscVx.dbd +++ b/motorExApp/NoAsyn/MiscVx.dbd @@ -1,15 +1,3 @@ -# Oregon Micro Systems VME8/44 driver support. -device(motor,VME_IO,devOMS,"OMS VME8/44") -driver(drvOms) - -# Oregon Micro Systems VME58 driver support. -device(motor,VME_IO,devOms58,"OMS VME58") -driver(drvOms58) - -# Oregon Micro Systems MAXv driver support. -device(motor,VME_IO,devMAXv,"OMS MAXv") -driver(drvMAXv) - registrar(motorUtilRegister) variable(motorRecordDebug) #variable(motordrvComdebug) diff --git a/motorExApp/WithAsyn/Makefile b/motorExApp/WithAsyn/Makefile index 4f80cdc5..a0fb6c62 100644 --- a/motorExApp/WithAsyn/Makefile +++ b/motorExApp/WithAsyn/Makefile @@ -21,7 +21,6 @@ ifdef SNCSEQ COMMONDBDS += devAerotechSeq.dbd endif COMMONDBDS += devPIMotor.dbd -COMMONDBDS += devOms.dbd COMMONDBDS += devSoftMotor.dbd COMMONDBDS += motorSimSupport.dbd COMMONDBDS += devSmartMotorMotor.dbd @@ -69,7 +68,6 @@ WithAsyn_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary COMMONLIBS += Aerotech COMMONLIBS += Attocube -COMMONLIBS += oms COMMONLIBS += Mclennan COMMONLIBS += Micos COMMONLIBS += MicroMo