From a9aa090bda1876ea35be92e5fe5e4ec161fb8e1f Mon Sep 17 00:00:00 2001 From: Bruno Martins Date: Wed, 10 Apr 2019 13:03:01 -0400 Subject: [PATCH] New upstream version 6.11 --- .ci/travis-prepare.sh | 164 + .gitattributes | 5 + .gitignore | 17 + .travis.yml | 27 + README | 79 +- README.md | 17 + configure/RELEASE | 5 +- {documentation => docs}/Doxyfile | 4 + {documentation => docs}/EnsemblePSOFly.txt | 0 {documentation => docs}/Makefile | 0 docs/Problems.html | 1060 + docs/README.md | 8 + docs/epics_logo.gif | Bin 0 -> 1820 bytes docs/index.html | 618 + .../motorDeviceDriver.html | 172 +- {documentation => docs}/motorRecord.html | 67 +- {documentation => docs}/motor_files.html | 0 {documentation => docs}/motor_notes.txt | 2 +- {documentation => docs}/motor_release.html | 186 +- docs/presentations/MotorRec2015.pptx | Bin 0 -> 389029 bytes {documentation => docs}/trajectoryScan.html | 12 +- .../IDL_trajectory_actual.png | Bin .../IDL_trajectory_errors.png | Bin .../trajectoryScan_files}/trajectoryPlot1.png | Bin .../trajectoryScan_files}/trajectoryPlot2.png | Bin .../trajectoryScan_files}/trajectoryScan.png | Bin .../trajectoryScanDebug.png | Bin documentation/MotorRec.ppt | Bin 730624 -> 0 bytes iocBoot/iocNewFocus874x/Makefile | 6 + .../newfocus8742.asyn.motor.substitutions | 8 + .../newfocus8742.asyn.st.cmd.linux-x86 | 67 + iocBoot/iocNoAsyn/st.cmd.Vx | 4 +- iocBoot/iocWithAsyn/motor.cmd.ANF2 | 107 + iocBoot/iocWithAsyn/motor.substitutions.ANF2 | 54 + iocBoot/iocWithAsyn/motor.substitutions.ANG1 | 17 + .../iocWithAsyn/motor.substitutions.CONEX-PP | 9 + .../iocWithAsyn/motor.substitutions.script | 15 + iocBoot/iocWithAsyn/scripts/softMotor.lua | 67 + iocBoot/iocWithAsyn/scripts/vmc.lua | 66 + iocBoot/iocWithAsyn/st.cmd.ANG1 | 74 + iocBoot/iocWithAsyn/st.cmd.CONEX-PP | 45 + iocBoot/iocWithAsyn/st.cmd.script | 18 + iocBoot/iocWithAsyn/st.cmd.xps6 | 46 + iocsh/ACS_MCB4B.iocsh | 25 + iocsh/EXAMPLE_motorSim.substitutions | 7 + iocsh/McClennan_PM304.iocsh | 31 + iocsh/Newfocus_PMNC87xx.iocsh | 37 + iocsh/Newport_ESP300.iocsh | 30 + iocsh/Newport_MM4000.iocsh | 32 + iocsh/Newport_PM500.iocsh | 30 + iocsh/PI_C630.iocsh | 49 + iocsh/PI_C867.iocsh | 28 + iocsh/PI_E710.iocsh | 31 + iocsh/PI_E816.iocsh | 30 + iocsh/allstop.iocsh | 10 + iocsh/motorSim.iocsh | 34 + motorApp/AMCISrc/AMCISupport.dbd | 2 + motorApp/AMCISrc/ANF2Driver.cpp | 1088 + motorApp/AMCISrc/ANF2Driver.h | 151 + motorApp/AMCISrc/ANF2Support.dbd | 2 + motorApp/AMCISrc/ANG1Driver.cpp | 640 + motorApp/AMCISrc/ANG1Driver.h | 88 + motorApp/AMCISrc/ANG1Support.dbd | 2 + motorApp/AMCISrc/Makefile | 30 + motorApp/AMCISrc/README | 49 + motorApp/AMCISrc/README_ANF2.md | 70 + motorApp/AcsSrc/AcsRegister.cc | 3 - motorApp/AcsSrc/AcsRegister.h | 3 - motorApp/AcsSrc/devMCB4B.cc | 7 +- motorApp/AcsSrc/drvMCB4B.cc | 4 +- motorApp/AcsTech80Src/ACSTech80Register.cc | 3 - motorApp/AcsTech80Src/devSPiiPlus.cc | 11 +- motorApp/AcsTech80Src/drvSPiiPlus.cc | 8 +- motorApp/AcsTech80Src/drvSPiiPlus.h | 3 - motorApp/AerotechSrc/AerotechRegister.cc | 44 +- motorApp/AerotechSrc/AerotechRegister.h | 4 - .../AerotechSrc/EnsembleCommonStructures.h | 927 + motorApp/AerotechSrc/EnsembleParameterId.h | 877 + motorApp/AerotechSrc/Makefile | 7 + motorApp/AerotechSrc/ParameterId.h | 1536 +- motorApp/AerotechSrc/README | 9 + motorApp/AerotechSrc/devAerotech.dbd | 1 - motorApp/AerotechSrc/devAerotechSeq.dbd | 1 + motorApp/AerotechSrc/devSoloist.cc | 12 +- motorApp/AerotechSrc/doCommand.ab | 470 +- motorApp/AerotechSrc/drvA3200Asyn.cc | 1558 +- motorApp/AerotechSrc/drvA3200Asyn.h | 22 +- motorApp/AerotechSrc/drvEnsembleAsyn.cc | 43 +- motorApp/AerotechSrc/drvEnsembleAsyn.h | 4 - motorApp/AerotechSrc/drvSoloist.cc | 36 +- motorApp/AerotechSrc/drvSoloist.h | 4 - motorApp/AttocubeSrc/drvANC150Asyn.cc | 3 - motorApp/Db/ANF2Aux.template | 28 + motorApp/Db/EnsemblePSOFly.db | 36 +- motorApp/Db/Makefile | 3 + motorApp/Db/ScriptMotorReload.db | 9 + motorApp/Db/XPSAuxAo.db | 30 +- motorApp/Db/XPSPositionCompare.db | 131 + motorApp/Db/XPSPositionCompare_settings.req | 6 + motorApp/Db/asyn_auto_power.db | 90 + motorApp/Db/asyn_motor.db | 34 + motorApp/Db/asyn_motor_settings.req | 4 - motorApp/Db/basic_asyn_motor.db | 34 + motorApp/Db/basic_motor_settings.req | 5 +- motorApp/Db/motor.db | 2 +- motorApp/Db/motor_settings.req | 4 - motorApp/Db/profileMoveAxis.template | 33 - motorApp/Db/trajectoryScan.db | 4 + motorApp/Db/trajectoryScan_settings.req | 3 +- motorApp/DeltaTauSrc/devPmac.cc | 12 +- motorApp/DeltaTauSrc/drvPmac.cc | 25 +- motorApp/DeltaTauSrc/drvPmac.h | 3 - motorApp/FaulhaberSrc/devMCDC2805.cc | 11 +- motorApp/FaulhaberSrc/drvMCDC2805.cc | 6 +- motorApp/FaulhaberSrc/drvMCDC2805.h | 3 - motorApp/HytecSrc/HytecMotorDriver.cpp | 5 +- motorApp/HytecSrc/README_Hy8601Asyn | 164 +- motorApp/ImsSrc/ImsMDrivePlusMotorAxis.cpp | 3 +- .../ImsSrc/ImsMDrivePlusMotorController.cpp | 7 +- motorApp/ImsSrc/ImsRegister.cc | 3 - motorApp/ImsSrc/devIM483PL.cc | 12 +- motorApp/ImsSrc/devIM483SM.cc | 12 +- motorApp/ImsSrc/devMDrive.cc | 12 +- motorApp/ImsSrc/drvIM483.h | 4 - motorApp/ImsSrc/drvIM483PL.cc | 6 +- motorApp/ImsSrc/drvIM483SM.cc | 22 +- motorApp/ImsSrc/drvMDrive.cc | 6 +- motorApp/KohzuSrc/devSC800.cc | 13 +- motorApp/KohzuSrc/drvSC800.cc | 14 +- motorApp/KohzuSrc/drvSC800.h | 4 - motorApp/MXmotorSrc/MXRegister.cc | 3 - motorApp/MXmotorSrc/MXmotor.h | 3 - motorApp/MXmotorSrc/devMXmotor.cc | 11 +- motorApp/MXmotorSrc/drvMXmotor.cc | 4 - motorApp/Makefile | 12 + motorApp/MclennanSrc/MclennanRegister.cc | 3 - motorApp/MclennanSrc/devPM304.cc | 7 +- motorApp/MclennanSrc/drvPM304.cc | 4 +- motorApp/MicosSrc/MicosRegister.cc | 3 - motorApp/MicosSrc/devMicos.cc | 7 +- motorApp/MicosSrc/drvMicos.cc | 4 +- motorApp/MicroMoSrc/MicroMoRegister.cc | 3 - motorApp/MicroMoSrc/devMVP2001.cc | 10 +- motorApp/MicroMoSrc/drvMVP2001.cc | 25 +- motorApp/MicroMoSrc/drvMVP2001.h | 3 - motorApp/MicronixSrc/MMC200Driver.cpp | 3 + motorApp/MotorSimSrc/devMotorSim.c | 3 + motorApp/MotorSimSrc/drvMotorSim.c | 3 - motorApp/MotorSimSrc/motorSimDriver.cpp | 27 +- motorApp/MotorSimSrc/motorSimDriver.h | 3 + motorApp/MotorSrc/README | 17 +- motorApp/MotorSrc/asynMotorAxis.cpp | 76 +- motorApp/MotorSrc/asynMotorAxis.h | 167 +- motorApp/MotorSrc/asynMotorController.cpp | 109 +- motorApp/MotorSrc/asynMotorController.h | 616 +- motorApp/MotorSrc/devMotorAsyn.c | 24 +- motorApp/MotorSrc/drvMotorAsyn.c | 3 - motorApp/MotorSrc/motor.h | 9 +- motorApp/MotorSrc/motorRecord.cc | 379 +- motorApp/MotorSrc/motorRecord.dbd | 15 +- motorApp/MotorSrc/motorUtil.cc | 4 - motorApp/MotorSrc/motorUtilAux.cc | 6 +- motorApp/MotorSrc/motor_epics_inc.h | 33 + motorApp/MotorSrc/motordevCom.cc | 32 +- motorApp/MotorSrc/motordevCom.h | 4 - motorApp/MotorSrc/motordrvCom.cc | 5 +- motorApp/MotorSrc/motordrvCom.h | 4 - motorApp/MotorSrc/motordrvComCode.h | 4 - motorApp/NewFocusSrc/874xMotorDriver.cpp | 349 + motorApp/NewFocusSrc/874xMotorDriver.h | 50 + motorApp/NewFocusSrc/Makefile | 7 +- motorApp/NewFocusSrc/devNewFocus.dbd | 3 + motorApp/NewFocusSrc/devPMNC87xx.cc | 9 +- motorApp/NewFocusSrc/drvPMNC87xx.cc | 2 + motorApp/NewportSrc/AG_CONEX.cpp | 168 +- motorApp/NewportSrc/AG_CONEX.h | 6 +- motorApp/NewportSrc/HXPDriver.cpp | 2 +- motorApp/NewportSrc/Makefile | 3 + motorApp/NewportSrc/NewportRegister.cc | 3 - motorApp/NewportSrc/NewportRegister.h | 3 - motorApp/NewportSrc/SMC100Driver.cpp | 3 + motorApp/NewportSrc/SMC100Register.cc | 3 - motorApp/NewportSrc/SMC100Register.h | 3 - motorApp/NewportSrc/XPSAxis.cpp | 251 +- motorApp/NewportSrc/XPSAxis.h | 8 +- motorApp/NewportSrc/XPSController.cpp | 115 +- motorApp/NewportSrc/XPSController.h | 51 +- motorApp/NewportSrc/XPSGathering2.c | 4 +- motorApp/NewportSrc/XPS_C8_drivers.cpp | 10 +- motorApp/NewportSrc/XPS_C8_drivers.h | 14 +- motorApp/NewportSrc/XPS_C8_errors.h | 214 +- motorApp/NewportSrc/XPS_trajectoryScan.st | 2 + motorApp/NewportSrc/devESP300.cc | 14 +- motorApp/NewportSrc/devMM3000.cc | 17 +- motorApp/NewportSrc/devMM4000.cc | 12 +- motorApp/NewportSrc/devNewport.dbd | 3 - motorApp/NewportSrc/devNewportSeq.dbd | 4 + motorApp/NewportSrc/devPM500.cc | 11 +- motorApp/NewportSrc/drvESP300.cc | 52 +- motorApp/NewportSrc/drvMM3000.cc | 22 +- motorApp/NewportSrc/drvMM4000.cc | 42 +- motorApp/NewportSrc/drvMM4000Asyn.c | 4 - motorApp/NewportSrc/drvMMCom.h | 3 - motorApp/NewportSrc/drvPM500.cc | 24 +- motorApp/NewportSrc/drvXPSAsyn.c | 13 +- motorApp/NewportSrc/drvXPSAsynAux.c | 2 +- motorApp/NewportSrc/hxp_drivers.cpp | 13803 +++++----- motorApp/NewportSrc/hxp_drivers.h | 361 +- motorApp/NewportSrc/hxp_errors.h | 196 +- motorApp/NewportSrc/tclCall.cc | 4 +- motorApp/NewportSrc/xpsSlave.st | 2 + motorApp/OmsAsynSrc/omsBaseAxis.cpp | 38 +- motorApp/OmsAsynSrc/omsBaseAxis.h | 16 +- motorApp/OmsAsynSrc/omsBaseController.cpp | 4 - motorApp/OmsAsynSrc/omsBaseController.h | 4 - motorApp/OmsAsynSrc/omsMAXnet.cpp | 8 +- motorApp/OmsAsynSrc/omsMAXnet.h | 4 - motorApp/OmsAsynSrc/omsMAXv.cpp | 9 +- motorApp/OmsAsynSrc/omsMAXv.h | 4 - motorApp/OmsAsynSrc/omsMAXvEncFunc.cpp | 4 - motorApp/OmsAsynSrc/omsMAXvEncFunc.h | 4 - motorApp/OmsSrc/README | 12 +- motorApp/OmsSrc/devMAXv.cc | 14 +- motorApp/OmsSrc/devOms.cc | 12 +- motorApp/OmsSrc/devOms.dbd | 1 + motorApp/OmsSrc/devOms58.cc | 12 +- motorApp/OmsSrc/devOmsCom.cc | 13 +- motorApp/OmsSrc/devOmsCom.h | 4 - motorApp/OmsSrc/devOmsPC68.cc | 12 +- motorApp/OmsSrc/drvMAXv.cc | 71 +- motorApp/OmsSrc/drvMAXv.h | 4 - motorApp/OmsSrc/drvOms.cc | 20 +- motorApp/OmsSrc/drvOms.h | 3 - motorApp/OmsSrc/drvOms58.cc | 68 +- motorApp/OmsSrc/drvOms58.h | 4 - motorApp/OmsSrc/drvOmsCom.h | 3 - motorApp/OmsSrc/drvOmsPC68.cc | 17 +- motorApp/OmsSrc/drvOmsPC68Com.h | 3 - motorApp/OrielSrc/OrielRegister.cc | 3 - motorApp/OrielSrc/devEMC18011.cc | 11 +- motorApp/OrielSrc/drvEMC18011.cc | 8 +- motorApp/OrielSrc/drvEMC18011.h | 3 - motorApp/PC6KSrc/ParkerRegister.cc | 3 - motorApp/PC6KSrc/devPC6K.cc | 11 +- motorApp/PC6KSrc/drvPC6K.cc | 18 +- motorApp/PC6KSrc/drvPC6K.h | 3 - motorApp/PIGCS2Src/PIC702Controller.cpp | 4 - motorApp/PIGCS2Src/PIC702Controller.h | 4 - motorApp/PIGCS2Src/PIE517Controller.cpp | 4 - motorApp/PIGCS2Src/PIE517Controller.h | 4 - motorApp/PIGCS2Src/PIE755Controller.cpp | 4 - motorApp/PIGCS2Src/PIE755Controller.h | 4 - .../PIGCS2Src/PIGCS2_HexapodController.cpp | 4 - motorApp/PIGCS2Src/PIGCS2_HexapodController.h | 4 - motorApp/PIGCS2Src/PIGCSController.cpp | 60 +- motorApp/PIGCS2Src/PIGCSController.h | 6 +- motorApp/PIGCS2Src/PIGCSMotorController.cpp | 216 +- motorApp/PIGCS2Src/PIGCSMotorController.h | 4 - motorApp/PIGCS2Src/PIGCSPiezoController.cpp | 4 - motorApp/PIGCS2Src/PIGCSPiezoController.h | 4 - motorApp/PIGCS2Src/PIHexapodController.cpp | 4 - motorApp/PIGCS2Src/PIHexapodController.h | 4 - motorApp/PIGCS2Src/PIInterface.cpp | 4 - motorApp/PIGCS2Src/PIInterface.h | 4 - motorApp/PIGCS2Src/PI_GCS2Support.dbd | 2 - motorApp/PIGCS2Src/PIasynAxis.cpp | 6 +- motorApp/PIGCS2Src/PIasynAxis.h | 4 - motorApp/PIGCS2Src/PIasynController.cpp | 6 +- motorApp/PIGCS2Src/PIasynController.h | 4 - motorApp/PIGCS2Src/picontrollererrors.h | 4 - motorApp/PIGCS2Src/translateerror.c | 4 - motorApp/PhytronSrc/phytronAxisMotor.cpp | 6 +- motorApp/PhytronSrc/phytronAxisMotor.h | 4 - motorApp/PiJenaSrc/PIJEDS_Register.cc | 3 - motorApp/PiJenaSrc/devPIJEDS.cc | 11 +- motorApp/PiJenaSrc/drvPIJEDS.cc | 10 +- motorApp/PiSrc/Makefile | 1 + motorApp/PiSrc/PIC662Register.cc | 3 - motorApp/PiSrc/PIC848Register.cc | 3 - motorApp/PiSrc/PIE516Register.cc | 3 - motorApp/PiSrc/PIE517Register.cc | 68 + motorApp/PiSrc/PIE710Register.cc | 3 - motorApp/PiSrc/PiRegister.cc | 3 - motorApp/PiSrc/devPIC630.cc | 7 +- motorApp/PiSrc/devPIC662.cc | 11 +- motorApp/PiSrc/devPIC663.cc | 9 +- motorApp/PiSrc/devPIC844.cc | 11 +- motorApp/PiSrc/devPIC848.cc | 11 +- motorApp/PiSrc/devPIC862.cc | 9 +- motorApp/PiSrc/devPIE516.cc | 11 +- motorApp/PiSrc/devPIE517.cc | 317 + motorApp/PiSrc/devPIE710.cc | 11 +- motorApp/PiSrc/devPIE816.cc | 8 +- motorApp/PiSrc/devPIMotor.dbd | 6 + motorApp/PiSrc/drvPI.h | 3 - motorApp/PiSrc/drvPIC630.cc | 2 + motorApp/PiSrc/drvPIC662.cc | 15 +- motorApp/PiSrc/drvPIC662.h | 3 - motorApp/PiSrc/drvPIC663.cc | 10 +- motorApp/PiSrc/drvPIC844.cc | 15 +- motorApp/PiSrc/drvPIC848.cc | 10 +- motorApp/PiSrc/drvPIC862.cc | 10 +- motorApp/PiSrc/drvPIE516.cc | 21 +- motorApp/PiSrc/drvPIE517.cc | 682 + motorApp/PiSrc/drvPIE517.h | 75 + motorApp/PiSrc/drvPIE710.cc | 9 +- motorApp/PiSrc/drvPIE816.cc | 18 +- motorApp/ScriptMotorSrc/Makefile | 30 + motorApp/ScriptMotorSrc/ScriptMotorDriver.cpp | 859 + motorApp/ScriptMotorSrc/ScriptMotorDriver.dbd | 1 + motorApp/ScriptMotorSrc/ScriptMotorDriver.h | 76 + .../SmarActMCSSrc/smarActMCSMotorDriver.cpp | 5 +- motorApp/SmartMotorSrc/devSmartMotor.cc | 11 +- motorApp/SmartMotorSrc/drvSmartMotor.cc | 5 +- motorApp/SoftMotorSrc/devSoft.cc | 277 +- motorApp/SoftMotorSrc/devSoft.h | 6 +- motorApp/SoftMotorSrc/devSoftAux.cc | 189 +- motorApp/ThorLabsSrc/ThorLabsRegister.cc | 3 - motorApp/ThorLabsSrc/devMDT695.cc | 11 +- motorApp/ThorLabsSrc/drvMDT695.cc | 7 +- motorApp/ThorLabsSrc/drvMDT695.h | 3 - motorApp/op/adl/4motor_form.adl | 52 - motorApp/op/adl/ScriptMotorReload.adl | 140 + motorApp/op/adl/XPSPositionCompare.adl | 522 + motorApp/op/adl/XPSPositionCompare8.adl | 2191 ++ motorApp/op/adl/XPSTest.adl | 170 - motorApp/op/adl/XPSTop.adl | 20 +- motorApp/op/adl/motorStatus120.adl | 20891 ++++++++++++++++ motorApp/op/adl/motorStatus96.adl | 17148 +++++++++++++ motorApp/op/adl/motorx_msta_detail.adl | 395 +- motorApp/op/opi/4motor_form.opi | 226 +- .../op/ui/{ => autoconvert}/16motor_form.ui | 0 .../op/ui/{ => autoconvert}/4motor_form.ui | 146 +- .../op/ui/{ => autoconvert}/8motor_form.ui | 0 motorApp/op/ui/{ => autoconvert}/ACRAux.ui | 0 motorApp/op/ui/{ => autoconvert}/ACRTop.ui | 0 .../op/ui/{ => autoconvert}/EnsemblePSOFly.ui | 0 .../EnsemblePSOFly_graphic.ui | 0 .../{ => autoconvert}/EnsemblePSOFly_more.ui | 0 .../op/ui/{ => autoconvert}/EnsemblePVErr.ui | 0 motorApp/op/ui/{ => autoconvert}/HXP.ui | 0 .../op/ui/{ => autoconvert}/HXP_coordSys.ui | 0 motorApp/op/ui/{ => autoconvert}/HXP_extra.ui | 0 .../op/ui/{ => autoconvert}/HXP_motors.ui | 0 .../op/ui/{ => autoconvert}/HXP_moveAll.ui | 0 .../{ => autoconvert}/MAX_trajectoryPlot.ui | 0 .../{ => autoconvert}/MAX_trajectoryPlot2.ui | 0 .../{ => autoconvert}/MAX_trajectoryScan.ui | 0 .../{ => autoconvert}/MAX_trajectoryScan1.ui | 0 .../{ => autoconvert}/MAX_trajectoryScan2.ui | 0 .../MAX_trajectoryScanDebug.ui | 0 .../MAX_trajectoryScanSpeed.ui | 0 .../op/ui/{ => autoconvert}/PSOarrayPlot.ui | 0 motorApp/op/ui/{ => autoconvert}/XPSAux.ui | 0 .../op/ui/{ => autoconvert}/XPSAuxBi_more.ui | 0 .../op/ui/{ => autoconvert}/XPSAuxTest.ui | 0 motorApp/op/ui/{ => autoconvert}/XPSExtra.ui | 0 motorApp/op/ui/{ => autoconvert}/XPSTest.ui | 0 motorApp/op/ui/{ => autoconvert}/XPSTop.ui | 0 motorApp/op/ui/{ => autoconvert}/motor2x.ui | 0 motorApp/op/ui/{ => autoconvert}/motor3x.ui | 0 motorApp/op/ui/{ => autoconvert}/motor4x.ui | 0 motorApp/op/ui/{ => autoconvert}/motor5x.ui | 0 motorApp/op/ui/{ => autoconvert}/motor6x.ui | 0 motorApp/op/ui/{ => autoconvert}/motor8x.ui | 0 .../op/ui/{ => autoconvert}/motorStatus104.ui | 0 .../op/ui/{ => autoconvert}/motorStatus16.ui | 0 .../op/ui/{ => autoconvert}/motorStatus24.ui | 0 .../op/ui/{ => autoconvert}/motorStatus32.ui | 0 .../op/ui/{ => autoconvert}/motorStatus40.ui | 0 .../op/ui/{ => autoconvert}/motorStatus48.ui | 0 .../op/ui/{ => autoconvert}/motorStatus56.ui | 0 .../op/ui/{ => autoconvert}/motorStatus64.ui | 0 .../op/ui/{ => autoconvert}/motorStatus72.ui | 0 .../op/ui/{ => autoconvert}/motorStatus8.ui | 0 .../op/ui/{ => autoconvert}/motorStatus80.ui | 0 .../op/ui/{ => autoconvert}/motorStatus88.ui | 0 motorApp/op/ui/{ => autoconvert}/motors.ui | 0 motorApp/op/ui/{ => autoconvert}/motors_s.ui | 0 motorApp/op/ui/{ => autoconvert}/motorx.ui | 0 motorApp/op/ui/{ => autoconvert}/motorxU.ui | 0 .../op/ui/{ => autoconvert}/motorx_all.ui | 0 .../op/ui/{ => autoconvert}/motorx_bare.ui | 0 .../op/ui/{ => autoconvert}/motorx_help.ui | 0 .../op/ui/{ => autoconvert}/motorx_more.ui | 0 .../op/ui/autoconvert/motorx_msta_detail.ui | 968 + .../op/ui/{ => autoconvert}/motorx_setup.ui | 0 .../op/ui/{ => autoconvert}/motorx_tiny.ui | 0 .../op/ui/{ => autoconvert}/profileMove.ui | 0 .../op/ui/{ => autoconvert}/profileMoveXPS.ui | 0 .../op/ui/{ => autoconvert}/topMotors4.ui | 0 .../op/ui/{ => autoconvert}/topMotors8.ui | 0 .../ui/{ => autoconvert}/topMotors8_more.ui | 0 .../op/ui/{ => autoconvert}/trajectoryPlot.ui | 0 .../op/ui/{ => autoconvert}/trajectoryScan.ui | 0 .../{ => autoconvert}/trajectoryScanDebug.ui | 0 .../trajectoryScan_Ensemble.ui | 0 .../{ => autoconvert}/trajectoryScan_MAXv.ui | 0 motorApp/op/ui/motor2xU.ui | 60 + motorApp/op/ui/motor3xU.ui | 76 + motorApp/op/ui/motor4xU.ui | 92 + motorApp/op/ui/motor5xU.ui | 108 + motorApp/op/ui/motor6xU.ui | 124 + motorApp/op/ui/motor7xU.ui | 140 + motorApp/op/ui/motor8xU.ui | 156 + motorApp/op/ui/motorx_msta_detail.ui | 956 - motorExApp/NoAsyn/Makefile | 4 - motorExApp/WithAsyn/Makefile | 39 +- 408 files changed, 64601 insertions(+), 13173 deletions(-) create mode 100755 .ci/travis-prepare.sh create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 README.md rename {documentation => docs}/Doxyfile (99%) rename {documentation => docs}/EnsemblePSOFly.txt (100%) rename {documentation => docs}/Makefile (100%) create mode 100644 docs/Problems.html create mode 100644 docs/README.md create mode 100644 docs/epics_logo.gif create mode 100644 docs/index.html rename {documentation => docs}/motorDeviceDriver.html (64%) rename {documentation => docs}/motorRecord.html (98%) rename {documentation => docs}/motor_files.html (100%) rename {documentation => docs}/motor_notes.txt (99%) rename {documentation => docs}/motor_release.html (92%) create mode 100755 docs/presentations/MotorRec2015.pptx rename {documentation => docs}/trajectoryScan.html (99%) rename {documentation => docs/trajectoryScan_files}/IDL_trajectory_actual.png (100%) rename {documentation => docs/trajectoryScan_files}/IDL_trajectory_errors.png (100%) rename {documentation => docs/trajectoryScan_files}/trajectoryPlot1.png (100%) rename {documentation => docs/trajectoryScan_files}/trajectoryPlot2.png (100%) rename {documentation => docs/trajectoryScan_files}/trajectoryScan.png (100%) rename {documentation => docs/trajectoryScan_files}/trajectoryScanDebug.png (100%) delete mode 100644 documentation/MotorRec.ppt create mode 100644 iocBoot/iocNewFocus874x/Makefile create mode 100644 iocBoot/iocNewFocus874x/newfocus8742.asyn.motor.substitutions create mode 100644 iocBoot/iocNewFocus874x/newfocus8742.asyn.st.cmd.linux-x86 create mode 100644 iocBoot/iocWithAsyn/motor.cmd.ANF2 create mode 100644 iocBoot/iocWithAsyn/motor.substitutions.ANF2 create mode 100644 iocBoot/iocWithAsyn/motor.substitutions.ANG1 create mode 100644 iocBoot/iocWithAsyn/motor.substitutions.CONEX-PP create mode 100644 iocBoot/iocWithAsyn/motor.substitutions.script create mode 100644 iocBoot/iocWithAsyn/scripts/softMotor.lua create mode 100644 iocBoot/iocWithAsyn/scripts/vmc.lua create mode 100644 iocBoot/iocWithAsyn/st.cmd.ANG1 create mode 100644 iocBoot/iocWithAsyn/st.cmd.CONEX-PP create mode 100644 iocBoot/iocWithAsyn/st.cmd.script create mode 100755 iocBoot/iocWithAsyn/st.cmd.xps6 create mode 100644 iocsh/ACS_MCB4B.iocsh create mode 100644 iocsh/EXAMPLE_motorSim.substitutions create mode 100644 iocsh/McClennan_PM304.iocsh create mode 100644 iocsh/Newfocus_PMNC87xx.iocsh create mode 100644 iocsh/Newport_ESP300.iocsh create mode 100644 iocsh/Newport_MM4000.iocsh create mode 100644 iocsh/Newport_PM500.iocsh create mode 100644 iocsh/PI_C630.iocsh create mode 100644 iocsh/PI_C867.iocsh create mode 100644 iocsh/PI_E710.iocsh create mode 100644 iocsh/PI_E816.iocsh create mode 100644 iocsh/allstop.iocsh create mode 100644 iocsh/motorSim.iocsh create mode 100644 motorApp/AMCISrc/AMCISupport.dbd create mode 100644 motorApp/AMCISrc/ANF2Driver.cpp create mode 100644 motorApp/AMCISrc/ANF2Driver.h create mode 100644 motorApp/AMCISrc/ANF2Support.dbd create mode 100644 motorApp/AMCISrc/ANG1Driver.cpp create mode 100644 motorApp/AMCISrc/ANG1Driver.h create mode 100644 motorApp/AMCISrc/ANG1Support.dbd create mode 100644 motorApp/AMCISrc/Makefile create mode 100644 motorApp/AMCISrc/README create mode 100644 motorApp/AMCISrc/README_ANF2.md create mode 100755 motorApp/AerotechSrc/EnsembleCommonStructures.h create mode 100755 motorApp/AerotechSrc/EnsembleParameterId.h create mode 100644 motorApp/AerotechSrc/devAerotechSeq.dbd create mode 100644 motorApp/Db/ANF2Aux.template create mode 100644 motorApp/Db/ScriptMotorReload.db create mode 100644 motorApp/Db/XPSPositionCompare.db create mode 100644 motorApp/Db/XPSPositionCompare_settings.req create mode 100644 motorApp/Db/asyn_auto_power.db create mode 100644 motorApp/MotorSrc/motor_epics_inc.h create mode 100644 motorApp/NewFocusSrc/874xMotorDriver.cpp create mode 100644 motorApp/NewFocusSrc/874xMotorDriver.h create mode 100644 motorApp/NewportSrc/devNewportSeq.dbd create mode 100755 motorApp/PiSrc/PIE517Register.cc create mode 100755 motorApp/PiSrc/devPIE517.cc create mode 100755 motorApp/PiSrc/drvPIE517.cc create mode 100755 motorApp/PiSrc/drvPIE517.h create mode 100644 motorApp/ScriptMotorSrc/Makefile create mode 100644 motorApp/ScriptMotorSrc/ScriptMotorDriver.cpp create mode 100644 motorApp/ScriptMotorSrc/ScriptMotorDriver.dbd create mode 100644 motorApp/ScriptMotorSrc/ScriptMotorDriver.h create mode 100644 motorApp/op/adl/ScriptMotorReload.adl create mode 100644 motorApp/op/adl/XPSPositionCompare.adl create mode 100644 motorApp/op/adl/XPSPositionCompare8.adl delete mode 100644 motorApp/op/adl/XPSTest.adl create mode 100644 motorApp/op/adl/motorStatus120.adl create mode 100644 motorApp/op/adl/motorStatus96.adl rename motorApp/op/ui/{ => autoconvert}/16motor_form.ui (100%) rename motorApp/op/ui/{ => autoconvert}/4motor_form.ui (96%) rename motorApp/op/ui/{ => autoconvert}/8motor_form.ui (100%) rename motorApp/op/ui/{ => autoconvert}/ACRAux.ui (100%) rename motorApp/op/ui/{ => autoconvert}/ACRTop.ui (100%) rename motorApp/op/ui/{ => autoconvert}/EnsemblePSOFly.ui (100%) rename motorApp/op/ui/{ => autoconvert}/EnsemblePSOFly_graphic.ui (100%) rename motorApp/op/ui/{ => autoconvert}/EnsemblePSOFly_more.ui (100%) rename motorApp/op/ui/{ => autoconvert}/EnsemblePVErr.ui (100%) rename motorApp/op/ui/{ => autoconvert}/HXP.ui (100%) rename motorApp/op/ui/{ => autoconvert}/HXP_coordSys.ui (100%) rename motorApp/op/ui/{ => autoconvert}/HXP_extra.ui (100%) rename motorApp/op/ui/{ => autoconvert}/HXP_motors.ui (100%) rename motorApp/op/ui/{ => autoconvert}/HXP_moveAll.ui (100%) rename motorApp/op/ui/{ => autoconvert}/MAX_trajectoryPlot.ui (100%) rename motorApp/op/ui/{ => autoconvert}/MAX_trajectoryPlot2.ui (100%) rename motorApp/op/ui/{ => autoconvert}/MAX_trajectoryScan.ui (100%) rename motorApp/op/ui/{ => autoconvert}/MAX_trajectoryScan1.ui (100%) rename motorApp/op/ui/{ => autoconvert}/MAX_trajectoryScan2.ui (100%) rename motorApp/op/ui/{ => autoconvert}/MAX_trajectoryScanDebug.ui (100%) rename motorApp/op/ui/{ => autoconvert}/MAX_trajectoryScanSpeed.ui (100%) rename motorApp/op/ui/{ => autoconvert}/PSOarrayPlot.ui (100%) rename motorApp/op/ui/{ => autoconvert}/XPSAux.ui (100%) rename motorApp/op/ui/{ => autoconvert}/XPSAuxBi_more.ui (100%) rename motorApp/op/ui/{ => autoconvert}/XPSAuxTest.ui (100%) rename motorApp/op/ui/{ => autoconvert}/XPSExtra.ui (100%) rename motorApp/op/ui/{ => autoconvert}/XPSTest.ui (100%) rename motorApp/op/ui/{ => autoconvert}/XPSTop.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motor2x.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motor3x.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motor4x.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motor5x.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motor6x.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motor8x.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorStatus104.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorStatus16.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorStatus24.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorStatus32.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorStatus40.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorStatus48.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorStatus56.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorStatus64.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorStatus72.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorStatus8.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorStatus80.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorStatus88.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motors.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motors_s.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorx.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorxU.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorx_all.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorx_bare.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorx_help.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorx_more.ui (100%) create mode 100644 motorApp/op/ui/autoconvert/motorx_msta_detail.ui rename motorApp/op/ui/{ => autoconvert}/motorx_setup.ui (100%) rename motorApp/op/ui/{ => autoconvert}/motorx_tiny.ui (100%) rename motorApp/op/ui/{ => autoconvert}/profileMove.ui (100%) rename motorApp/op/ui/{ => autoconvert}/profileMoveXPS.ui (100%) rename motorApp/op/ui/{ => autoconvert}/topMotors4.ui (100%) rename motorApp/op/ui/{ => autoconvert}/topMotors8.ui (100%) rename motorApp/op/ui/{ => autoconvert}/topMotors8_more.ui (100%) rename motorApp/op/ui/{ => autoconvert}/trajectoryPlot.ui (100%) rename motorApp/op/ui/{ => autoconvert}/trajectoryScan.ui (100%) rename motorApp/op/ui/{ => autoconvert}/trajectoryScanDebug.ui (100%) rename motorApp/op/ui/{ => autoconvert}/trajectoryScan_Ensemble.ui (100%) rename motorApp/op/ui/{ => autoconvert}/trajectoryScan_MAXv.ui (100%) create mode 100644 motorApp/op/ui/motor2xU.ui create mode 100644 motorApp/op/ui/motor3xU.ui create mode 100644 motorApp/op/ui/motor4xU.ui create mode 100644 motorApp/op/ui/motor5xU.ui create mode 100644 motorApp/op/ui/motor6xU.ui create mode 100644 motorApp/op/ui/motor7xU.ui create mode 100644 motorApp/op/ui/motor8xU.ui delete mode 100644 motorApp/op/ui/motorx_msta_detail.ui diff --git a/.ci/travis-prepare.sh b/.ci/travis-prepare.sh new file mode 100755 index 0000000..7beb7b4 --- /dev/null +++ b/.ci/travis-prepare.sh @@ -0,0 +1,164 @@ +#!/bin/sh +set -e -x + +SUPPORT=$HOME/.cache/support + +install -d $SUPPORT + +# Conditionally build IPAC +if [ -n "$IPAC" ]; then + IPAC_PATH=$SUPPORT/ipac +else + IPAC_PATH= +fi + +RELEASE_PATH=$TRAVIS_BUILD_DIR/configure/RELEASE +EPICS_BASE=$SUPPORT/epics-base + +cat << EOF > $RELEASE_PATH +IPAC=$IPAC_PATH +SNCSEQ=$SUPPORT/seq +ASYN=$SUPPORT/asyn +EPICS_BASE=$SUPPORT/epics-base +EOF + +# use default selection for MSI +sed -i -e '/MSI/d' configure/CONFIG_SITE + +if [ ! -e "$EPICS_BASE/built" ] +then + + git clone --depth 10 --branch $BASE https://github.com/epics-base/epics-base.git $EPICS_BASE + + EPICS_HOST_ARCH=`sh $EPICS_BASE/startup/EpicsHostArch` + + case "$STATIC" in + static) + cat << EOF >> "$EPICS_BASE/configure/CONFIG_SITE" +SHARED_LIBRARIES=NO +STATIC_BUILD=YES +EOF + ;; + *) ;; + esac + + case "$CMPLR" in + clang) + echo "Host compiler is clang" + cat << EOF >> $EPICS_BASE/configure/os/CONFIG_SITE.Common.$EPICS_HOST_ARCH +GNU = NO +CMPLR_CLASS = clang +CC = clang +CCC = clang++ +EOF + ;; + *) echo "Host compiler is default";; + esac + + # requires wine and g++-mingw-w64-i686 + if [ "$WINE" = "32" ] + then + echo "Cross mingw32" + sed -i -e '/CMPLR_PREFIX/d' $EPICS_BASE/configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw + cat << EOF >> $EPICS_BASE/configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw +CMPLR_PREFIX=i686-w64-mingw32- +EOF + cat << EOF >> $EPICS_BASE/configure/CONFIG_SITE +CROSS_COMPILER_TARGET_ARCHS+=win32-x86-mingw +EOF + fi + + # set RTEMS to eg. "4.9" or "4.10" + if [ -n "$RTEMS" ] + then + echo "Cross RTEMS${RTEMS} for pc386" + install -d /home/travis/.cache + curl -L "https://github.com/mdavidsaver/rsb/releases/download/travis-20160306-2/rtems${RTEMS}-i386-trusty-20190306-2.tar.gz" \ + | tar -C /home/travis/.cache -xj + + sed -i -e '/^RTEMS_VERSION/d' -e '/^RTEMS_BASE/d' $EPICS_BASE/configure/os/CONFIG_SITE.Common.RTEMS + cat << EOF >> $EPICS_BASE/configure/os/CONFIG_SITE.Common.RTEMS +RTEMS_VERSION=$RTEMS +RTEMS_BASE=/home/travis/.cache/rtems${RTEMS}-i386 +EOF + cat << EOF >> $EPICS_BASE/configure/CONFIG_SITE +CROSS_COMPILER_TARGET_ARCHS+=RTEMS-pc386 +EOF + + fi + + make -C "$EPICS_BASE" -j2 + # get MSI for 3.14 + case "$BASE" in + 3.14*) + echo "Build MSI" + install -d "$HOME/msi/extensions/src" + curl https://epics.anl.gov/download/extensions/extensionsTop_20120904.tar.gz | tar -C "$HOME/msi" -xvz + curl https://epics.anl.gov/download/extensions/msi1-7.tar.gz | tar -C "$HOME/msi/extensions/src" -xvz + mv "$HOME/msi/extensions/src/msi1-7" "$HOME/msi/extensions/src/msi" + + cat << EOF > "$HOME/msi/extensions/configure/RELEASE" +EPICS_BASE=$EPICS_BASE +EPICS_EXTENSIONS=\$(TOP) +EOF + make -C "$HOME/msi/extensions" + cp "$HOME/msi/extensions/bin/$EPICS_HOST_ARCH/msi" "$EPICS_BASE/bin/$EPICS_HOST_ARCH/" + echo 'MSI:=$(EPICS_BASE)/bin/$(EPICS_HOST_ARCH)/msi' >> "$EPICS_BASE/configure/CONFIG_SITE" + + cat <> configure/CONFIG_SITE +MSI = \$(EPICS_BASE)/bin/\$(EPICS_HOST_ARCH)/msi +EOF + + ;; + *) echo "Use MSI from Base" + ;; + esac + + touch $EPICS_BASE/built +else + echo "Using cached epics-base!" +fi + +# IPAC +if [ -n "$IPAC" ]; then + if [ ! -e "$SUPPORT/ipac/built" ]; then + echo "Build ipac" + install -d $SUPPORT/ipac + git clone --depth 10 --branch $IPAC https://github.com/epics-modules/ipac.git $SUPPORT/ipac + cat << EOF > $SUPPORT/ipac/configure/RELEASE +EPICS_BASE=$SUPPORT/epics-base +EOF + make -C $SUPPORT/ipac + touch $SUPPORT/ipac/built + else + echo "Using cached ipac" + fi +else + echo "Skipping ipac" +fi + + +# sequencer +if [ ! -e "$SUPPORT/seq/built" ]; then + echo "Build sequencer" + install -d $SUPPORT/seq + curl -L "http://www-csr.bessy.de/control/SoftDist/sequencer/releases/seq-${SEQ}.tar.gz" | tar -C $SUPPORT/seq -xvz --strip-components=1 + cp $RELEASE_PATH $SUPPORT/seq/configure/RELEASE + make -C $SUPPORT/seq + touch $SUPPORT/seq/built +else + echo "Using cached seq" +fi + + +# asyn +if [ ! -e "$SUPPORT/asyn/built" ]; then + echo "Build asyn" + install -d $SUPPORT/asyn + curl -L "https://epics.anl.gov/download/modules/asyn${ASYN}.tar.gz" | tar -C $SUPPORT/asyn -xvz --strip-components=1 + cp $RELEASE_PATH $SUPPORT/asyn/configure/RELEASE + make -C "$SUPPORT/asyn" -j2 + touch $SUPPORT/asyn/built +else + echo "Using cached asyn" +fi diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9712a09 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +#Which files need CRLF handling +* text=auto +*.sh eol=lf +*.bat eol=crlf +*.cmd -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fae3cab --- /dev/null +++ b/.gitignore @@ -0,0 +1,17 @@ +*~ +O.* +*.swp +*BAK.adl +bin/ +db/ +dbd/ +html/ +include/ +lib/ +templates/ +cdCommands +envPaths +dllPath.bat +auto_settings.sav* +auto_positions.sav* +.ccfxprepdir/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..0f4036e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,27 @@ +sudo: false +dist: trusty +language: c +compiler: + - gcc +cache: + directories: + - $HOME/.cache +addons: + apt: + packages: + - libreadline6-dev + - libncurses5-dev + - perl + - clang + - g++-mingw-w64-i686 + - re2c +env: + - BASE=3.14 STATIC=shared SEQ=2.2.4 ASYN=4-31 IPAC=2.14 + - BASE=3.14 STATIC=static SEQ=2.2.4 ASYN=4-31 IPAC=2.14 + - BASE=R3.15.5 STATIC=shared SEQ=2.2.4 ASYN=4-31 IPAC=2.14 + - BASE=R3.15.5 STATIC=static SEQ=2.2.4 ASYN=4-31 IPAC=2.14 + - BASE=3.16 STATIC=shared RTEMS=4.10 SEQ=2.2.4 ASYN=4-31 IPAC=2.14 + - BASE=3.16 STATIC=shared CMPLR=clang WINE=32 SEQ=2.2.4 ASYN=4-31 IPAC= + - BASE=3.16 STATIC=static WINE=32 SEQ=2.2.4 ASYN=4-31 IPAC= +install: ./.ci/travis-prepare.sh +script: make diff --git a/README b/README index 10defa7..10ca6a5 100644 --- a/README +++ b/README @@ -1,4 +1,13 @@ -Motor Module R6-9 Release Notes +Notice +====== + +This file was historically used to document changes to the motor module that +were relevant to developers. It is largely obsolete now that the motor module +has moved github. It will not be updated in the future and is likely to move +to the documentation directory. + + +Motor Module R6-10 Release Notes =============================================================================== The motor module software in this release is compatible with EPICS base @@ -144,6 +153,74 @@ Known Problems - Tapping the Jog button can cause the motor to move past the soft-travel limit when backlash is nonzero. +Modification Log for R6-10 +========================== + +2) Fix for OMS controllers that do not have the correct deceleration rate at + the end of a JOG. Bug introduced with item #9 under R6-6. + + File modified: OmsSrc/devOmsCom.cc + +3) - If the user request UEIP be set true and the MSTA's EA_PRESENT indicator + is off, then special() denies the request and sets UEIP false. In other + words, UEIP can only be set true if the device/driver has set the + "Encoder is Present" MSTA indicator true. Replaced six occurrences of + logic that tested both UEIP and EA_PRESENT with just UEIP. + + - UEIP and URIP are mutually exclusive. For example, if the user request + UEIP be set true when URIP is also true, then the special() function + will set URIP off and vice versa. Added the special attribute to URIP. + + - If URIP is true and the RDBL link points to a valid DBR_DOUBLE, then the + value pointed to by RDBL will be multiplied by RRES, divided by MRES + and stored in RRBV. This fixes a problem with all previous releases + where RRBV was inconsistent with DRBV when URIP was true. + + Files modified: motorApp/MotorSrc/motorRecord.cc + motorApp/MotorSrc/motorRecord.dbd + +4) Fix for build errors when SNCSEQ isn't defined in the RELEASE file. + + Files added: motorApp/AerotechSrc/devAerotechSeq.dbd + motorApp/NewportSrc/devNewportSeq.dbd + Files modified: motorApp/AerotechSrc/Makefile + motorApp/AerotechSrc/devAerotech.dbd + motorApp/NewportSrc/Makefile + motorApp/NewportSrc/devNewport.dbd + +5) Márcio Paduan Donadio (LNLS) fixed a bug with SYNC field processing. SYNC + was being ignored when URIP == True. + + Files modified: syncTargetPosition() in motorRecord.cc + +6) Kevin Peterson discovered an initialization bug when the motor record is + configured to do retries. When configured to do retries, the motor + record issues incremental rather than absolute moves. If the motor + behaves badly (e.g., a piezo stiction motor) the controller's absolute + step count can be far from its' absolute readback position. The motor + record initialization logic that determines how the target positions + are initialized at boot-up was not taking into consideration whether + or not the motor record is configured to do retries, and therefore, + whether or not absolute or incremental moves were issued by the motor + record. With this release, if the motor record is configured to do + retries, then the controller's absolute position is ignored (because + the controller's absolute position was "corrupted" by retries) and the + autosave/restore position is used to set the controllers position. + + Switching between retries on and off (relative vs. absolute moves) + between reboots will cause unpredictable results and is not covered + by this bug fix. + + Files modified: motor_init_record_com() in MotorSrc/motordevCom.cc + init_controller() in MotorSrc/devMotorAsyn.c + +7) The MAXv User's Manual specifies that "The IRQ interrupt level range is + 0x010-0x111 (IRQ2-7)...". The appropriate error check has been added to + the MAXvSetup() call. + + File modified: OmsSrc/drvMAXv.cc + + Modification Log for R6-9 ========================= diff --git a/README.md b/README.md new file mode 100644 index 0000000..793e787 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# motor +APS BCDA synApps module: motor + +[![Build Status](https://travis-ci.org/epics-modules/motor.png)](https://travis-ci.org/epics-modules/motor) + +**Note**: Current discussion on future of the *motor* module repository: https://github.com/epics-modules/motor/issues/55 + +For more information, see: +* [main page](https://epics-modules.github.io/motor) +* [motor wiki](https://github.com/epics-modules/motor/wiki) +* http://www.aps.anl.gov/bcda/synApps +* [HTML documentation](https://github.com/epics-modules/motor/blob/master/docs/README.md) + +[Report an issue with Motor](https://github.com/epics-modules/motor/issues/new?title=%20ISSUE%20NAME%20HERE&body=**Describe%20the%20issue**%0A%0A**Steps%20to%20reproduce**%0A1.%20Step%20one%0A2.%20Step%20two%0A3.%20Step%20three%0A%0A**Expected%20behaivour**%0A%0A**Actual%20behaviour**%0A%0A**Build%20Environment**%0AArchitecture:%0AEpics%20Base%20Version:%0ADependent%20Module%20Versions:&labels=bug) +[Request a feature](https://github.com/epics-modules/motor/issues/new?title=%20FEATURE%20SHORT%20DESCRIPTION&body=**Feature%20Long%20Description**%0A%0A**Why%20should%20this%20be%20added?**%0A&labels=enhancement) + +converted from APS SVN repository: Fri Oct 16 12:31:41 CDT 2015 diff --git a/configure/RELEASE b/configure/RELEASE index 6c1a60a..56f99a3 100644 --- a/configure/RELEASE +++ b/configure/RELEASE @@ -17,7 +17,7 @@ SUPPORT= # Recommended ASYN release: R4-23 ASYN=$(SUPPORT)/asyn/R4-23 -# Need the sequencer and the bust record for the MM4005 and XPS trajectory scanning +# Need the sequencer and the busy record for the MM4005 and XPS trajectory scanning # Recommended SNCSEQ release: R2.1.16 SNCSEQ=$(SUPPORT)/seq/seq-2-1-16 # Recommended BUSY release: R1-6 @@ -37,6 +37,9 @@ EPICS_BASE= # Recommended IPAC release: R2-12 IPAC=$(SUPPORT)/ipac/R2-12 +# Script module needed to build ScriptMotorController +#!LUA=$(SUPPORT)/lua + # The following is only needed for the motor examples in iocBoot. #!MOTOR=$(TOP) diff --git a/documentation/Doxyfile b/docs/Doxyfile similarity index 99% rename from documentation/Doxyfile rename to docs/Doxyfile index e3f527a..e0f8a64 100755 --- a/documentation/Doxyfile +++ b/docs/Doxyfile @@ -586,6 +586,10 @@ INPUT = ../../asyn/asyn/miscellaneous/asynPortDriver.cpp \ ../motorApp/NewportSrc/XPSController.h \ ../motorApp/NewportSrc/XPSController.cpp \ ../motorApp/NewportSrc/XPSAxis.h \ + ../motorApp/NewportSrc/AG_CONEX.cpp \ + ../motorApp/NewportSrc/AG_CONEX.h \ + ../motorApp/NewportSrc/AG_UC.cpp \ + ../motorApp/NewportSrc/AG_UC.h \ ../motorApp/NewportSrc/XPSAxis.cpp \ ../motorApp/MotorSimSrc/motorSimDriver.h \ ../motorApp/MotorSimSrc/motorSimDriver.cpp diff --git a/documentation/EnsemblePSOFly.txt b/docs/EnsemblePSOFly.txt similarity index 100% rename from documentation/EnsemblePSOFly.txt rename to docs/EnsemblePSOFly.txt diff --git a/documentation/Makefile b/docs/Makefile similarity index 100% rename from documentation/Makefile rename to docs/Makefile diff --git a/docs/Problems.html b/docs/Problems.html new file mode 100644 index 0000000..f4393c0 --- /dev/null +++ b/docs/Problems.html @@ -0,0 +1,1060 @@ + + + + + + Motor Module Known Problems + + + +

Motor Module: Known problems

+ +

Known problems with Release 6-10 and later

+ +See issues on github: https://github.com/epics-modules/motor/issues + +

Known problems with Release 6-9

+ + +

Known problems with Release 6-8

+ +
    +
  1. +

    + Soft-travel Limits +

    +

    +

      +
    • + Although there are a number of improvements with R6-8's support of soft-travel + limits (LVIO), there are also two problems that will remain "Known Problems". + These limitation are as follows: +
    • +
        +
      • + Tweaking (TWF/TWR) very small increments with UEIP = Yes while in the invalid + range of the soft-travel limits may put the motor record in a state where the + user cannot tweak in either direction. The solution is to either jog the motor + towards the valid range or increase the tweak increment value (TWV field). +
      • +
      • + Tapping the Jog button can cause the motor to move past the soft-travel limit + when backlash is nonzero. +
      • +
      +
    +

    +
  2. +
  3. +

    + Newport ESP100/300/301 +

    +

    + The R6.8 ESP support changes made to "Use MRES rather than controller resolution + to do EGUtoRAWbacktoEGU conversion." do not work. (Model 1 drivers do not always + have access to motor record data.) The most obvious problem with R6.8 ESP + support is the inability to "set" the controller's position. +

    +

    + This + patch file rolls back the R6.8 ESP changes and adds one bug fix to + the EPS100/300/301 driver; when a controller error occurs, the driver prints the + error code to the console and sets the RA_PROBLEM bit of the MSTA field. The + motor record patch unconditionally sends a "stop motor" command whenever a + driver sets the RA_PROBLEM bit. Finally, the patch file updates ESP info in the + README file. +

    +

    + R6-8-1 includes both the MRES related rollback and the STOP on RA_PROBLEM bug fix. +

    +
  4. +
+ +

Known problems with Release 6-7

+ +
    +
  1. +

    + Aerotech Ensemble +

    +

    +

      +
    • + Due to network broadcasting upgrades to Aerotech Ensemble Motion Composer, + starting with motor module R6-7-1, the EPICS Ensemble driver only supports + 4.01.002 Ensemble version firmware 4.01.002 and above. +
    • +
    • + The home search from EPICS command was been restored with R6-7-1. In order for + an EPICS home search command to work, the Aerotech Ensemble example program, HomeAsync.abx, + must be compiled and stored in the Ensemble. In addition, the Parameters>System>TaskExecutionSetup + parameter must be set to enable Auxiliary Task execution. +
    • +
    +

    +
  2. + +

    +

  3. +

    + Schneider Electric (formally IMS) MDrive +

    +

    + Joe Sullivan fixed several bugs in the Schneider Electric MDrive driver + associated with input buffer overflows that arose with newer MDrive firmware (e.g., + 3.003). These bug fixes were 1st released with motor module R6-7-1. +

    +
  4. +

    + +
+ +

Known problems with Release 6-5

+ +
    +
  1. +

    + Aerotech Ensemble +

    +

    +

      +
    • + With previous releases the Aerotech Ensemble asyn motor driver would crash the + IOC at boot-up if the Ensemble was not powered up and able to communicate. Fixed + with R6-5-1. +
    • +
    • + The EOT limit switch status was not available except via an Ensemble fault + condition. With release R6-5-1 the status of the EOT limit switches are always + available. +
    • +
    +

    +
  2. + +

    +

  3. +

    + OMS MAXv WatchDog Timeout Counter +

    +

    + Beginning with R6-5-1 and OMS MAXv firmware ver:1.33, the EPICS MAXv driver reads + the MAXv's Watchdog Timeout Counter at bootup, and with every motor status + update. If the Counter is nonzero, an error message is sent to both the errlog + task and the console. Since a watchdog timer trip indicates that the MAXv has + rebooted and no longer has valid motor positions, the driver disables the + controller. That specific controller is no longer available to EPICS until after + the VME crate has been power cycled. Other MAXv boards in the system are + unaffected by this scenario. +

    +

    + To better communicate this problem to the user, several medm displays have been + changed. Small displays (motorx_tiny.adl, motorx.adl) will show a yellow border + around their position readback values. Larger displays (motorx_more.adl, + motorx_all.adl) will display the message "Controller Error" in yellow. The + following error message at the console and/or in the errlog is definitive; +

    +

    +

    + ***MAXv card #(card#) Disabled*** Watchdog Timeout CTR =(count) +
    +

    +
  4. +

    + +
  5. +

    + spec upgrade required +

    +

    + The RES field was removed from the motor record with R6-5. Since earlier + versions of Certified Scientific Software's spec used the RES field, an upgrade + to spec version 5.8.06-6 or above is required for spec to work with motor record + R6-5 and above. The problem of using earlier versions of spec with motor record + R6-5 exhibits itself by spec setting the "responsive" parameter to zero and not + allowing any motor motion. +

    +
  6. + +
  7. +

    + VxWorks 6.x compiler error +

    +

    + The GNU preprocessor assertions in motor.h are deprecated with the VxWorks 6.x + compiler. Test for CPU macros that are compatible with VxWorks 6.x have been + added. This change prevents an "Error: unknown bit order!" compiler error with + VxWorks 6.x. This problem is fixed with R6-5-2 and above. Alternatively, you can + replace <motor>/motorApp/MotorSrc/motor.h with the following copy: motor.h +

    +
  8. + +
  9. +

    + Aerotech Ensemble Home Search +

    +

    + The EPICS Ensemble driver uses Aerotech's ASCII communication protocol. That + protocol blocks all communication on the ASCII comm. port during a home search. + Consequently, once a home search is started from EPICS, it is unable to stop it. + As a result, beginning with R6-5-2, the home search command has been commented + out of the EPICS driver until an Ensemble firmware update resolves this problem. +

    +
  10. + +
+ +

Known problems with Release 6-4

+ +
    +
  1. + R6-4 had 64-bit compile problems with the PI E816 and Aerotech Ensemble device + drivers. Fixed with R6-4-1 and above. +
  2. +

    +

  3. + Dirk Zimoch (PSI) discovered and fixed a bug in the orginial OMS MAXv driver (R5-4) + that caused the home switch status in the response string to be overwritten. + Fixed with R6-4-2 and above. +

    +

  4. +

    +

  5. + A problem was introduced in R6-4 of the old motor record device drive + architecture. If during the move of one or more motors the motor task did not + issue an OS delay during status updates, it could potentially not respond to any + further motor commands. Fixed with R6-4-2 and above. +
  6. +

    +

  7. + There is a bug in these motor record versions (R6-4, R6-4-1, R6-4-2) + that affects motors that have encoders and are configured to do closed-loop + control via retries (i.e. UEIP=Yes and RTRY != 0). Retries are not done + correctly and occasionally motors exceed their maximum retries and are left at + their backlash position; i.e., command position - backlash distance. See the + Release Notice for further error conditions. Fixed with R6-4-3 and above. +
  8. +

    +

  9. + The asynMotor device support in general, and the simulated motor, in particular, + had save/restore related problems. Fixed with R6-4-4 and above. +
  10. +

    +

  11. + Previous releases of the Aerotech Ensemble device driver had incorrect Jog + speeds, lacked support for a negative PosScaleFactor parameter and did not + detect maximum travel limit switch faults correctly. Fixed with R6-4-4 and above. +
  12. +

    +

+ +

Known problems with Release 6-3

+ +
    +
  1. + The OMS VME58 "stale data" problem is caused by the driver communicating via the + ASCII commands while the DPRAM was updating. The OMS VME58 driver was modified + with R6-3 to eliminate this contention and the "stale data delay" was set to + zero. Since then a problem with OMS VME58 2.24-8S version firmware and all 2.35 + firmware versions has arisen. When the user sets the motor record's position, + the previous target and readback positions are read from the controller on the + next update. +

    + With releases after R6-3 (e.g., R6-3-1 and R6-4) the driver searches all VME58 + board ID's for either 2.24-8S or any 2.35 version. If any board is found, the "stale + data delay" is set to a non-zero value. +

  2. +

    +

  3. + A problem was reported by Emma Shepherd (Diamond) with R6-3 if the "Use RDBL + Link" field (URIP) was set to "Yes". The NTM logic was sending stop commands + and issuing the "tdir=.." message to the console if the RDBL link was used. This + error was the result of changing the NTM logic as described in item #11 under R6-3 + modifications. +

    + With releases after R6-3 (e.g., R6-3-1 and R6-4), the NTM logic is restored to + using feedback rather than reference positions. In addition, with release R6-4 + and after, an "NTM deadband factor" field (NTMF) is added to allow the user to + set the NTM deadband; NTM deadband = NTMF * (|BDST| + RDBD) NTMF must be >= 2. + If properly configured, the NTM deadband prevents NTM logic from issuing a STOP + command at the end of a DC motor move that overshoots its' target position. +

  4. +

    +

  5. + The asyn motor device driver architecture does not support the motor record + GET_INFO command. Hence, operations that require a status update (i.e., setting + the position) were not working. This is fixed in R6-4. +
  6. +

    +

  7. + In the process of fixing the OMS VME58 "stale data" problem described above, + needless delays were added to the code that updated the VME58's DPRAM. These + needless delays can be calculated as follows; +

    + delay = (n-1) * (1/sysClkRate) +

    + where, n = # of VME58 boards in the IOC.
    + sysClkRate = 60 Hz, unless changed by a sysClkRateSet() from st.cmd. +

    + These delays are eliminated with R6-4-2 and above. +

  8. +

    +

+ +

Known problems with Release 6-2

+ + +
    +
  1. + Link errors occurred when building "XPSGatheringMain" for the solaris-sparc-gnu + target. Newport users should upgrade to R6-2-1. +
  2. +

    +

  3. + Errors occurred in various motorApp's when building for the solaris-sparc (SUNWspro) + target. SUNWspro users should upgrade to R6-2-1. +
  4. +

    +

  5. + Mark River's found and fixed a bug in the motor record. RDBD was being used in + motor record initialization before the RDBD validation check. This resulted in + motor positions not being initialized from save/restore at boot-up if RDBD was + not included in a save/restore save set. This is fixed in R6-2-2. +
  6. +

    +

  7. + A bug was introduced into the shell command motorUtilInit affecting these + versions of the motor distribution; R6-2, R6-2-1 and R6-2-2. This bug resulted + in the erroneous error message; "motorUtilInit: Prefix %c: has more than 53 + characters. Exiting". Replace <motor>/motorApp/MotorSrc/motorUtil.cc with + the following copy:  motorUtil.cc +
  8. +

    +

  9. + The "alldone" PV in motorUtil.db defaulted to the "moving" state between "iocInit + " and "motorUtilInit", giving the false indication that motors were moving + during boot-up. The "alldone" PV now defaults to the "done" state. Replace <motor>/motorApp/Db/motorUtil.db + with the following copy:  motorUtil.db +
  10. +

    +

+ +

Known problems with Release 6-1

+ +
    +
  1. + The Newport PM500 driver was not issuing the correct command when it queried for + the number of axes at boot up. This resulted in a "PM500 system error" message + on the 1st axis; fixed in R6-2. +
  2. +
  3. + A bug was introduced with R6-0; the OMS device support was overwriting PID + parameter fields during its' normalization calculation; fixed in R6-2. +
  4. +
  5. + There was a bug in the logic that determines the precedence between using the + controller's or save/restore's motor position at boot-up. Negative controller + positions were not handled correctly; fixed in R6-2 +
  6. +
  7. + The home request (HOMF/HOMR) were not cleared when a soft-limit violation + occurred; fixed in R6-2. +
  8. +
  9. + Due to releasing R6-1 during Newport development, R6-1 can result in linker + errors on the symbol "xpsgathering". Newport users should upgrade to R6-2. +
  10. +
+ +

Known problems with Release 6-0

+ +
    +
  1. + The R6-0-bugfix CVS repository branch has become corrupted. Hence, no further + changes will be made (i.e., bug fixes) to the R6-0 branch. +
  2. +
  3. + A bug was introduced with this release. The OMS device support overwrites PID + parameter fields during its' normalization calculation. This is fixed in R6-2. +
  4. +
+ +

Known problems with Release 5-9

+ +
    +
  1. + An undocumented change was made in R5-4 to two OMS setup functions. Namely, the + unused 2nd argument ("axes per card") was eliminated from omsSetup() and + oms58Setup(). +
  2. + +
  3. + Since R4-5 the motor record has required that RDBD be >= MRES. The test for + this condition was done using floating point values. This caused an occasional + error that resulted in the record not always issuing a motor move command when + RDBD = MRES and the user issued an incremental move request equal to MRES. This + is fixed with R5-9-1 and R6-0. +
  4. + +
  5. + A warning message was added with R5-6 when a user attempted to move an OMS motor + with an invalid velocity (slew <= base). Applications that manipulate the + velocity values are unaware of this restriction and create a torrent of + these messages. With release R5-9-1 and R6-0 the OMS device driver will + only output this warning message once. +
  6. + +
  7. + Added a work around for OMS PC68/78 firmware error. PC68/78 controllers make an + erroneous response after they are queried with the "?KP" command at boot-up. + This resulted in 1st axis having same position (RP command) as last the axis. + This is fixed with R5-9-1 and R6-0. +
  8. + +
  9. + GPIB under ASYN allows only one input EOS character; no output EOS is allowed. + Adjustments were made to the Newport ESP300 driver to accomodate this + restriction with R5-9-1 and R6-0. +
  10. + +
  11. + The CVS repository has become out of synch with the R5-9-1 tar file (motorR5-9-1.tar.gz). + Hence, no further changes will be made (i.e., bug fixes) to the R5-9 branch. +
  12. +
+ +

Known problems with Release 5-8

+ +

Known problems with Release 5-7

+ +

Known problems with Release 5-6

+ +

Known problems with Release 5-5

+ +

Known problems with Release 5-4

+ +
    +
  1. + An undocumented change was made to two OMS setup functions. Namely, the unused + 2nd argument ("axes per card") was eliminated from omsSetup() and oms58Setup() + in R5-4. +
  2. +
+ +

Known problems with Release 5-3

+ +
    +
  1. + "sorry, not implemented: `tree_list' not supported by dump_type" error when + compiling drvOms.cc and drvOms58.cc under Tornado 2.2. The Tornado 2.2 compiler + (i.e., 2.96) creates errors in devLib.h. The root cause of this "bug" is a + problem with the gcc-2.96 compiler bundled with Tornado 2.2. Unfortunately, to + date, Wind River is only helping with workarounds; not fixing the compiler. Hence, + the following patches are required. +
  2. +
      +
    • + For R3.14.4-5, replace <base>src/libCom/osi/devLib.h with the following + copy: devLib.h +
    • +
    • + Edit <motor>/motorApp/OmsSrc/drvOms.cc by uncommenting the lines with the Tornado + 2.2 comment and commenting out the line with the Tornado 2.0.2 + comment. +
    • +
    • + Edit <motor>/motorApp/OmsSrc/drvOms58.cc by uncommenting the lines with + the Tornado 2.2 comment and commenting out the line with the Tornado + 2.0.2 comment. +
    • +
    +
+ +

Known problems with Release 5-2

+ +
    +
  1. + "sorry, not implemented: `tree_list' not supported by dump_type" error when + compiling drvOms.cc and drvOms58.cc under Tornado 2.2. The Tornado 2.2 compiler + (i.e., 2.96) creates errors in devLib.h. The root cause of this "bug" is a + problem with the gcc-2.96 compiler bundled with Tornado 2.2. Unfortunately, to + date, Wind River is only helping with workarounds; not fixing the compiler. Hence, + the following patches are required. +
  2. +
      +
    • + For R3.14.4-5, replace <base>src/libCom/osi/devLib.h with the following + copy: devLib.h +
    • +
    • + Replace <motor>/motorApp/OmsSrc/drvOms.cc with the following + updated copy: drvOms.cc +
    • +
    • + Replace <motor>/motorApp/OmsSrc/drvOms58.cc with the following + updated copy: drvOms58.cc +
    • +
    +
+ +

Known problems with Release 4-9

+ +
    +
  1. + PID parameters (i.e., PCOF, ICOF and DCOF fields) were not initialized at boot-up. + With R4.9.1, if the GAIN_SUPPORT bit in the MSTA is true, each nonzero, + PID parameter will be initialized. For backwards compatibility, zero valued PID + parameters will not be initialized. +
  2. + +
  3. + Previous releases of the IMS MDrive device driver did not work. Thanks to Kevin + M. Peterson (UNI-CAT) for identifying and fixing the errors in previous releases. +
  4. +
      +
    • + Fixed with R4-9-2. +
    • +
    + +
  5. + Two bugs were found and fixed with the Newport MM3000 device support. First, + the enable/disable torque control field (CNEN) was not working. Second, an + error was introduced into the Newport MM3000 device driver with R4-8; the driver + was confusing valid responses with the "system error" response from the + controller +
  6. +
      +
    • + Fixed with R4-9-3. +
    • +
    + +
  7. + A retry on initial communication with the Physik Instrumente (PI) C-844 motor + controller was added. The controller was intermittently not responding after an + IOC power-cycle. +
  8. +
      +
    • + Fixed with R4-9-4. +
    • +
    + +
  9. + Modifications were made to the motor record in order to allow a user to + configure it for periodic status updates using the SCAN field. +
  10. +
      +
    • + Available with R4-9-4. +
    • +
    + +
  11. + The motor record would get into an invalid state when it attempted to perform a + backlash correction move in the direction of an activated limit switch. +
  12. +
      +
    • + Fixed with R4-9-5. +
    • +
    + +
  13. + Bug fix for home request re-activating after a limit switch error is cleared. + This release clears the homing and jog request after a LS or travel limit error. + Updated the motorx_all.adl MEDM screen (V2.5) to show the state of the jog + request. +
  14. +
      +
    • + Fixed with R4-9-5. +
    • +
    + +
  15. + A bug was reported by David Maden (PSI) that occurred when a motor was jogged + into a limit switch with the DIR field set to "Neg". Under these conditions, the + motor record was not processing the limit error condition correctly. This + resulted in the motor record not setting either of the limit error indicator + fields (HLS/LLS) and becoming stuck in the "Moving" state. +
  16. +
      +
    • + Fixed with R4-9-6. +
    • +
    + +
  17. + Kevin Peterson (UNI-CAT) and I diagnosed a bug that is in all R3.13 versions of + the motor record distribution. The bug is in the interface between motor record + GPIB capable drivers (i.e., Newport MM4000/5/6, MM3000, PM500, ESP300/100) and + the EPICS base GPIB driver; drvGpib.
    + Dynamic memory is allocated and shared with drvGpib by the motor task. The + problem arises here, at the end of ibLinkTask in drvGpib.c;
    + + plink->deviceStatus[pnode->device] = (*(pnode->workStart))(pnode);
    + + pnode->workStart is a pointer to gpibIOCallback() in gpibIO.c. When + gpibIOCallback() is done processing it "gives" a semaphore that is "taken" by + either gpibIOSend() and gpibIORecv(). Both gpibIOSend() and gpibIORecv() + immediately free the shared memory.
    + + This works almost all the time; but occasionally the memory is taken by some + other task and trashed before the line above is executed resulting in a bus + error on "pnode->device".
    + + As a quick fix, the task priorities of the all GPIB capable controllers has been + lowered below ibLinkTasks priority. This allows ibLinkTask to finish processing + and be waiting for the next GPIB request before the shared memory is de-allocated. +
    + + All users of the R3.13.x version of the motor record distribution that use GPIB + to communicate to Newport controllers (i.e., Newport MM4000/5/6, MM3000, PM500, + ESP300/100), should upgrade to the R4-9-6 release. +
  18. +
      +
    • + Fixed with R4-9-6. +
    • +
    +
+ +

Known problems with Release 4-8

+ +
    +
  1. + Previous releases of the IMS MDrive device driver did not work. Thanks to Kevin + M. Peterson (UNI-CAT) for identifying and fixing the errors in previous releases. +
  2. +
      +
    • + Fixed with R4-9-1. +
    • +
    +
  3. + Users of the status update field (STUP) should use a later release. +
  4. +
      +
    • + Fixed with R4-9 and above. +
    • +
    +
  5. + Two bugs were found and fixed with the Newport MM3000 device support. First, + the enable/disable torque control field (CNEN) was not working. Second, an + error was introduced into the Newport MM3000 device driver with R4-8; the driver + was confusing valid responses with the "system error" response from the + controller +
  6. +
      +
    • + Fixed with R4-8-1 and above. +
    • +
    +
+ +

Known problems with Release 4-7

+ +
    +
  1. + With release R4-5, DBE_LOG was omitted from the event select mask of all + db_post_events() calls.  This prevented archival clients from being + notified of process variable changes. +
  2. +
      +
    • + Fixed with R4-7-1. +
    • +
    +
  3. + Communication with the Newport MM3000 motor controller was getting out of + synchronization whenever the MM3000 responded with an error message. This + problem was resolved by having recv_mess() in drvMM3000.c detect an error + message response, print the error message and then, recursively, call itself. + This restored communication transmit/receive synchronization. +
  4. +
      +
    • + Fixed with R4-7-2. +
    • +
    +
  5. + With release R4-7, there was a slight (undocumented) modification made to the + way that backlash correction functioned. If a move is in the preferred direction + and the backlash speed and acceleration are the same as the slew speed and + acceleration, then the backlash move is skipped and the motor moves directly to + the target position. Unfortunately, there was a bug in the logic that appeared + only when MRES< 0. When MRES < 0, and the backlash speed and acceleration were + the same as the slew speed and acceleration, the motor record did the opposite + of the requirements; i.e., it did backlash correction when the move was in the + preferred direction and did not do backlash correction when the move was not in + the preferred direction. +
  6. +
      +
    • + Fixed with R4-7-2. +
    • +
    +
  7. + The Newport ESP300 would randomly crash at boot-up because an internal parameter + ("drive_resolution") was not always, under all configurations, initialized. With + this release, the "drive_resolution" is set based on the response to the ESP300 + "SU?" command. In addition, the user is required to set MRES to the resolution + of the controller as explained in the new document /motorApp/NewportSrc/README. +
  8. +
      +
    • + Fixed with R4-7-2. +
    • +
    +
  9. + A bug was introduced in R4-6 while fixing another bug; see item#2 under + Modification Log from R4-5 to R4-6 in the distribution README file. This error + exhibited itself only under the following conditions; BDST != 0, DLY != 0 and a + new target position is issued before the backlash correction move. Under these + conditions the motor record became unresponsive; i.e., it locked up. +
  10. +
      +
    • + Fixed with R4-7-3. +
    • +
    +
  11. + Although there is no explicit statement in the motor record documentation, most + user's would expect the "Readback settle time" field (DLY) to update the + readback after the delay timeout. It did not do this. With this release, the + readback is updated one time after the timeout. +
  12. +
      +
    • + Fixed with R4-7-3. +
    • +
    +
  13. + There were problems with the tweak function (TWF/TWR) when the TWV was set to + less than MRES. Under this condition, the following scenario would result. First, + tweak forward (TWF). Since DIFF < MRES, the motor is not moved. Next, tweak + reverse (TWR). Next TWF again. The motor record does not respond; i.e., DVAL + and RVAL are not updated; VAL is not posted. A single tweak, back and forth, + confirms that the motor record is not responding. +
  14. +
      +
    • + Fixed with R4-7-4. +
    • +
    +
  15. + The motor record would lock-up when a user tried to move off an activated limit + switch with the OMS VME58 servo motor controller board (i.e., model -8S). See "Known + Problems" item #4 in the motor record's distribution README file. +
  16. +
      +
    • + Fixed with R4-7-4. +
    • +
    +
+ +

Known problems with Release 4-6

+ +
    +
  1. + An uninitialized pointer error check was omitted from ESP300_init_record() in + the devESP300.c file.  This resulted in a bus error at boot-up if there was + a failure to connect to the controller.  Choose one of the following + methods to applying the bug fix: +
  2. +
      +
    • + Replace <motor>/motorApp/NewportSrc/devESP300.c with the following + updated copy: devESP300.c +
    • +
    • + Install motor record version R4-6-1 or above, which includes this bug fix. +
    • + +
    +
  3. + With release 4-5, DBE_LOG was omitted from the event select mask of all + db_post_events() calls.  This prevented archival clients from being + notified of process variable changes. +
  4. +
      +
    • + Fixed with R4-6-2. +
    • +
    +
  5. + Communication with the Newport MM3000 motor controller was getting out of + synchronization whenever the MM3000 responded with an error message. This + problem was resolved by having recv_mess() in drvMM3000.c detect an error + message response, print the error message and then, recursively, call itself. + This restored communication transmit/receive synchronization. +
  6. +
      +
    • + Fixed with R4-6-3. +
    • +
    +
  7. + The Newport ESP300 would randomly crash at boot-up because an internal parameter + ("drive_resolution") was not always, under all configurations, initialized. With + this release, the "drive_resolution" is set based on the response to the ESP300 + "SU?" command. In addition, the user is required to set MRES to the resolution + of the controller as explained in the new document /motorApp/NewportSrc/README. +
  8. +
      +
    • + Fixed with R4-6-3. +
    • +
    +
  9. + A bug was introduced in R4-5-1 while fixing another bug; see item#2 under + Modification Log from R4-5 to R4-5-1 in the distribution README file. This error + exhibited itself only under the following conditions; BDST != 0, DLY != 0 and a + new target position is issued before the backlash correction move. Under these + conditions the motor record became unresponsive; i.e., it locked up. +
  10. +
      +
    • + Fixed with R4-6-4. +
    • +
    +
  11. + Although there is no explicit statement in the motor record documentation, most + user's would expect the "Readback settle time" field (DLY) to update the + readback after the delay timeout. It did not do this. With this release, the + readback is updated one time after the timeout. +
  12. +
      +
    • + Fixed with R4-6-4. +
    • +
    +
+ +

Known problems with Release 4-5

+ +
    +
  1. + Soft Channel Device Support - see Release + Notice. +
  2. +
      +
    • + Fixed with R4-5-1.
      +
    • +
    +
  3. + Backlash Correction Bug Fixes - see Release + Notice. +
  4. +
      +
    • + Fixed with R4-5-1
      +
    • +
    +
  5. + With release 4-5, DBE_LOG was omitted from the event select mask of all + db_post_events() calls.  This prevented archival clients from being + notified of process variable changes. +
  6. +
      +
    • + Fixed with R4-5-2
      +
    • +
    + +
  7. + Communication with the Newport MM3000 motor controller was getting out of + synchronization whenever the MM3000 responded with an error message. This + problem was resolved by having recv_mess() in drvMM3000.c detect an error + message response, print the error message and then, recursively, call itself. + This restored communication transmit/receive synchronization. +
  8. +
      +
    • + Fixed with R4-5-3. +
    • +
    +
  9. + The Newport ESP300 would randomly crash at boot-up because an internal parameter + ("drive_resolution") was not always, under all configurations, initialized. With + this release, the "drive_resolution" is set based on the response to the ESP300 + "SU?" command. In addition, the user is required to set MRES to the resolution + of the controller as explained in the new document /motorApp/NewportSrc/README. +
  10. +
      +
    • + Fixed with R4-5-3. +
    • +
    +
  11. + A bug was introduced in R4-5-1 while fixing another bug; see item#2 under + Modification Log from R4-5 to R4-5-1 in the distribution README file. This error + exhibited itself only under the following conditions; BDST != 0, DLY != 0 and a + new target position is issued before the backlash correction move. Under these + conditions the motor record became unresponsive; i.e., it locked up. +
  12. +
      +
    • + Fixed with R4-5-3. +
    • +
    +
  13. + Although there is no explicit statement in the motor record documentation, most + user's would expect the "Readback settle time" field (DLY) to update the + readback after the delay timeout. It did not do this. With this release, the + readback is updated one time after the timeout. +
  14. +
      +
    • + Fixed with R4-5-3. +
    • +
    + +
  15. + An error occurred when the SET/USE field was in the SET mode and the FOFF field + was in the FROZEN mode. Under these conditions, if the user entered a new RVAL, + the record ignored every other new RVAL; with every other new DVAL that the user + entered, RVAL was not updated. VAL always worked. +
  16. +
      +
    • + Fixed with R4-5-4. +
    • +
    • + Replace <motor>/motorApp/MotorSrc/motorRecord.c with the following updated + copy: motorRecord.c +
    • +
    +
+ +

Known problems with Release 4-4

+ +
    +
  1. The "Driver Power Monitoring" feature (available only for OMS VME58 + controllers)  was erroneously and randomly being enabled.  Choose + one of the following methods to applying the bug fix:
  2. + +
      +
    • Make the following modification to <motor>/motorApp/MotorSrc/motordevCom.c:
    • + +
        + 202a203
        + >     ptrans->dpm = OFF; + +
      +
    • Replace <motor>/motorApp/MotorSrc/motordevCom.c with the +following updated copy:  + motordevCom.c
    • +
    • Install motor record version R4-4-1 or above, which includes this +bug fix.
    • + +
    +
  3.  Code around "safeDoubleToFloat conversion bug" in EPICS R3.13.5.  + A bug was introduced into R3.13.5 with the "dbConvert and dbFastLinkConv" + fix (see EPICS base Release Notes for R3.13.5) that resulted in the inability + to set PV fields defined as DBF_FLOAT's to zero.  One of the scenarios + where this has caused a problem is when a user tries to disable software + travel limits by setting DHLM = DLLM = 0.  Choose the following methods + to applying the bug fix:
  4. + +
      +
    • Replace <motor>/motorApp/MotorSrc/motordevCom.c with the following + updated copy:  + motorRecord.c
    • + +
    +
  5. The makeConfigAppInclude.pl perl script distibuted with R4-4 and + R4-4-1 does not support spaces between the macro and the "=" sign in the + config/RELEASE file.
  6. + + +
  7. The following scenario would put the motor record into an invalid state. + A new target position (i.e., VAL/DVAL/RVAL) is written to the motor +record under the following conditions,
    +
      +
    • motion is in progress (i.e., DMOV is false).
    • +
    +
      +
    • the new target position is different from the actual position by +less than the retry deadband (|DIFF| < RDBD).
    • +
    +
      +
    • backlash correction is enabled (i.e., BDST is non-zero) and the +new move is NOT in the "preferred direction" (preferred direction is the +direction in which the motor moves during the backlash-takeout part of a +motor move).
    • +
    +Install motor record version 4-4-2 or above to fix this problem.
    +
  8. +
+ +

Known problems with Release 4-3

+ +
    +
  1. +The "Driver Power Monitoring" feature (available only for OMS VME58 controllers)  +was erroneously and randomly being enabled.  Choose one of the following +methods to applying the bug fix:
  2. + +
      +
    • +Make the following modification to <motor>/motorApp/MotorSrc/motordevCom.c:
    • + +
        202a203 +
        >     ptrans->dpm = OFF;
      + +
    • +Replace <motor>/motorApp/MotorSrc/motordevCom.c with the following updated +copy:  motordevCom.c
    • + +
    • +Install motor record version R4-3-1, which includes this bug fix.
    • +
    + +
  3. +Under certain conditions target positions entered through RVAL were ignored.  +If the difference between the current and the next target position (i.e., +RDIF, DIFF) was less than the retry deadband (RDBD), and the next target +position was in the "preferred direction", then the new RVAL was ignored.  +Motor record version R4-3-2 includes the fix for this bug.
  4. + +
+ +

Known problems with Release 3-5

+ +
    +
  1. Under certain conditions target positions entered through RVAL were +ignored.  If the difference between the current and the next target +position (i.e., RDIF, DIFF) was less than the retry deadband (RDBD), and +the next target position was in the "preferred direction", then the new RVAL +was ignored.
  2. +
+ + +
+ + + diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..12d11f9 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,8 @@ +# HTML documentation + +* [index.html](https://epics-modules.github.io/motor) (formerly motor.html) +* [motorDeviceDriver.html](https://epics-modules.github.io/motor/motorDeviceDriver.html) +* [motorRecord.html](https://epics-modules.github.io/motor/motorRecord.html) +* [motor_files.html](https://epics-modules.github.io/motor/motor_files.html) +* [motor_release.html](https://epics-modules.github.io/motor/motor_release.html) +* [trajectoryScan.html](https://epics-modules.github.io/motor/trajectoryScan.html) diff --git a/docs/epics_logo.gif b/docs/epics_logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..26ed21adbee482421c2cbda8136c5985bc0069cd GIT binary patch literal 1820 zcmXAodr;O@8pj_KSwPrDHZF20dAPk5Ef5s(Cs5FmsRA_+l4flx-MBoqk;!WrR`a3lhVU_?kFkSHLE5haO2 zqJd~ev?Ll0cLW(hNf2!|fl-hYkP@JTQ6ecpN`X>FsiYJs2g(`cl5(U1s9;n`Dv&Cm zicux0LaKpkMzy3Gjfp8TijpGQMhC`0azIXi6UK?;1UUsx8K;s{oJ-D;3*drr zA-O=VfGft8@k-U`R= z(laJMIBQjJThqV3X`mCFy<*gDQqhsj;8DJK1Obm*-D!Y&~F_xx~AyaiHCO`i`4lTF%_Nnq?9`E39XSJF@0n>iW$R ze(##=%k806YyW2&Udm5+m{i;nGWl%N3yv(u>b3Ryt+I&kE0P23M=N?$E59$F zZf+d&6CX2?5lYMZ*fk9=0UF5O(e?^e3K z$3O{*TJ+cAkf3L(ul}unLS*soDIbiL?dmHWH7$w=xA!}kA5rVMyYuw&R}Z`0@G2qJ zE{79KgF2Qcr~NSX#6OF#XE(VN2#Jky;b z-}Sd|Pu_o}r6%}Ht>xgXvmHCYzo~jn=K6PfqJ!Sw+?zfUTzzv{Gq?14kNns?X<_$Z z<@xS;HA$jttm8w!b@AK9OHS#%<(KDl-;3Plv}|?RmU$7+Tm-v}+Q|5}I=0f!?}%y1 zwd4Z#OU_lpRXZoekiN(ObL?QG&&06WhME4fe4gvXo}~750SijVg0C{mzFzFo+g~2Z z?gw1i{Ahgeva6{puhfMf&ku23Z0FmNFyD7a?(DQ}MICNuF0Wc0-d+BBXPLdD+HF1S z3~XJ(3iqo4lY+fE!)j+=`ykJ6e8Kx0=ly3_df!@8V$&CopKQ$6ZUGPHUMMn$jt`W? zzp?v5^Y1=sAGtlXXY`bO)cQm1gKs^oZy!%sYu!@&b?vE>y#Bp4BRfy@)!jeR(f8d* zW7fiFEjhyzx6OKTWBZdpxa}5ysBKf|=n99#35lNP zO5>-3{mO*v{?j77mV4Ue#bkFKo0ikLKiGM0Om11`G`m)JAIF@qSA2gd`orS4q8eTe cO9<*J`mN + + + + + + + EPICS: Motor Record + + +EPICS +

EPICS: Motor Record and Device/Driver support.

+ +
+
Module Owners: Kevin Peterson
+
+ +

+
+This is the home page for both the motor record and various motor controllers +supported by motor record device/drivers. +

+

+GitHub repository: https://github.com/epics-modules/motor +

+

+Please email any comments to Kevin Peterson who +is responsible for coordinating development and releases. Bug reports can be created on +github. +

+ +

Where to Find it

You can download the software using +the links in the table below:
+  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Module VersionEPICS Release - RangeFilenameDocumentationRelease NoticeKnown ProblemsRelease Date
LatestR3.15.5-3.14.12.5master.zipmotorRecord.htmlmotor_release.htmlProblemsn/a
R6-11R3.15.5-3.14.12.5motorR6-11.tar.gzmotorRecord.htmlmotor_release.htmlProblems12/12/2018
R6-10R3.15.5-3.14.12.5motorR6-10-1.tar.gzmotorRecord.htmlmotor_release.htmlProblems11/30/2017
R6-9R3.15.1-3.14.12.3motorR6-9.tar.gzmotorRecord.htmlmotor_release.htmlProblems01/07/2015
R6-8R3.14.12.3motorR6-8-1.tar.gzmotorRecord.htmlmotor_release.htmlProblems06/16/2014
R6-7R3.14.12.2motorR6-7-1.tar.gzmotorRecord.htmlmotor_release.htmlProblems03/06/2012
R6-5R3.14.10-11motorR6-5-2.tar.gzmotorRecord.htmlmotor_release.htmlProblems10/14/2010
R6-4R3.14.8.2-10motorR6-4-4.tar.gzmotorRecord.htmlmotor_release.htmlProblems06/22/2009
R6-3R3.14.8.2-10motorR6-3-1.tar.gzmotorRecord.htmlmotor_release.htmlProblems12/10/2008
R6-2R3.14.8.2-9motorR6-2-2.tar.gzmotorRecord.htmlmotor_release.htmlProblems04/04/2007
R6-1R3.14.8.2motorR6-1.tar.gzmotorRecord.htmlmotor_release.htmlProblems12/18/2006
R6-0R3.14.8.2motorR6-0.tar.gzmotorRecord.htmlmotor_release.htmlProblems09/22/2006
R5-9R3.14.8.2motorR5-9-1.tar.gzmotorRecord.htmlmotor_release.htmlProblems08/21/2006
R5-8R3.14.7-8.2motorR5-8.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R5-7R3.14.7motorR5-7.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R5-6R3.14.7motorR5-6.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R5-5R3.14.6 - 7motorR5-5.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R5-4R3.14.6motorR5-4.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R5-3R3.14.5motorR5-3.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R5-2R3.14.4motor5-2.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R4-9R3.13.5 - 10motorR4-9-6.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R4-8R3.13.5 - 9motorR4-8-1.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R4-7R3.13.2 - 9motor4-7-4.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R4-6R3.13.2 - 9motor4-6-4.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R4-5R3.13.2 - 9motorR4-5-4.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R4-4R3.13.4 - 5motor4-4-2.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R4-3R3.13.4 - 5motor4-3-2.tar.gzmotorRecord.htmlmotor_release.htmlProblems
R4-1R3.13.2motor4-1.tar.gzmotorRecord.htmlmotor_release.html
R3-5R3.13.1.1 - 2motor_V3.5.tar.gzmotorRecord.htmlmotor_V3.5.htmlProblems
+ +

Required Modules

  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Motor Version Required modulesRelease needed
R6-10ASYN  
+ IPAC  (for serial + or GPIB communication only)
R4-25
+ R2-13
R6-9ASYN  
+ IPAC  (for serial + or GPIB communication only)
R4-25
+ R2-13
R6-8ASYN  
+ IPAC  (for serial + or GPIB communication only)
R4-21
+ R2-12
R6-7ASYN  
+ IPAC  (for serial + or GPIB communication only)
R4-18
+ R2-11
R6-5ASYN  
+ IPAC  (for serial + or GPIB communication only)
R4-13-1
+ R2-10
R6-4ASYN  
+ IPAC  (for serial + or GPIB communication only)
R4-10
+ R2-9
R6-3ASYN  
+ IPAC  (for serial + or GPIB communication only)
R4-9
+ R2-9
R6-2ASYN  
+ IPAC  (for serial + or GPIB communication only)
R4-7
+ R2-8
R6-1ASYN  
+ IPAC  (for serial + or GPIB communication only)
R4-6
+ R2-8
R6-0ASYN  
+ IPAC  (for serial + or GPIB communication only)
R4-6
+ R2-8
R5-9-1ASYN  
+ IPAC  (for serial + or GPIB communication only)
R4-6
+ R2-8
R5-8ASYN   (for + serial or GPIB communication only)
+ IPAC  (for serial + communication only)
R4-4
+ R2-8
R5-7ASYN   (for + serial or GPIB communication only)
+ IPAC  (for serial + communication only)
R4-3
+ R2-8
R5-6ASYN   (for + serial or GPIB communication only)
+ IPAC  (for serial + communication only)
R4-2
+ R2-8
R5-5ASYN   (for + serial or GPIB communication only)
+ IPAC  (for serial + communication only)
R4-1
+ R2-8
R5-4ASYN   (for + serial or GPIB communication only)
+ IPAC  (for serial + communication only)
R3-3
+ R2-7a
R5-3MPF   (for + serial communication only; no GPIB support)
+ IPAC  (for serial + communication only)
R2-4-2
+ R2-7a
R5-2MPF   (for + serial communication only; no GPIB support)
+
R2-4
+
R4-9MPF  + (for serial or GPIB communication only)
+ mpfGpib + (for GPIB communication only; runtime requirement only)
+ mpfSerial + (for serial communication only)
R1-10
+ R1-5
+ R1-5
R4-8MPF  + (for serial or GPIB communication only)
+ mpfGpib + (for GPIB communication only; runtime requirement only)
+ mpfSerial + (for serial communication only)
R1-10
+ R1-4
+ R1-4
R4-7MPF +   (for serial or GPIB communication only)
+ + mpfGpib + (for GPIB communication only; runtime requirement only)
+ + mpfSerial + (for serial communication only)
R1-10
+ + R1-4
+ + R1-4
R4-6Same as R4-5
R4-5
+
MPF +   (for serial or GPIB communication only)
+ mpfGpib + (for GPIB communication only; runtime requirement only)
+ mpfSerial + (for serial communication only)
+
R1-8
+ R1-4
+ R1-3
+
R4-4MPF +   (for serial or GPIB communication only)
+ mpfGpib + (for GPIB communication only; runtime requirement only)
+ mpfSerial + (for serial communication only)
R1-6
+ R1-3
+ R1-2
R4-3MPF +   (for serial or GPIB communication only)
+ mpfGpib + (for GPIB communication only; runtime requirement only)
+ mpfSerial + (for serial communication only)
R1-6
+ R1-3
+ R1-2
R4-1MPF +   (for serial or GPIB communication only)
+ mpfGpib + (for GPIB communication only; runtime requirement only)
+ mpfSerial + (for serial communication only) + +
+ OR +
+ HIDEOS (for + serial or GPIB communication only)
R1-5
+ R1-3
+ R1-1 +

+ Latest? +

+
+ +

Installation and Building

After obtaining a copy of the distribution, +it must be installed and built for use at your site. These steps only need to +be performed once per site (unless versions of the module running under +different releases of EPICS and/or the other required modules are needed). +
    +
  1. + Create an installation directory for the module, usually this will end with +
  2. + +
    .../support/motor/
    +
  3. + Place the distribution file in this directory. Then issue the commands (Unix + style) +
  4. + +
    gunzip motor<rel>.tar.gz
    tar xvf motor<rel>.tar
    + where <rel> is the release. For example. + +
    motor4-1.tar.gz
    +
  5. + This creates a <top> application. +
  6. + +
    .../support/motor/motor<rel>
    +
  7. + Edit the config/RELEASE file and set the paths to your installation of + EPICS base (i.e., define SUPPORT and EPICS_BASE). +
  8. +
  9. + Edit  .../support/motor/motor<rel>/motorApp/Makefile.  Define + which device/driver modules to build. +
  10. +
  11. + Run gnumake in the top level directory and check for any compilation + errors. +
  12. + +
+ +

Documentation

The following documentation is available: +
    +
  • +  Consult the README file in the motor distribution for configuration + details. +
  • + +
+ +
+
+Page Last Modified: 05/01/2018
+Kevin Peterson
+
+
+
+ + diff --git a/documentation/motorDeviceDriver.html b/docs/motorDeviceDriver.html similarity index 64% rename from documentation/motorDeviceDriver.html rename to docs/motorDeviceDriver.html index 0205b9a..2a4ada6 100644 --- a/documentation/motorDeviceDriver.html +++ b/docs/motorDeviceDriver.html @@ -206,176 +206,6 @@

The asynMotorAxis base class defines the following methods:

-

- This driver inherits from ADDriver. - It implements many of the parameters in - asynNDArrayDriver.h and in - ADArrayDriver.h. It also implements a number of parameters that are specific - to the mar345 detector. The mar345 - class documentation describes this class in detail.

-

- Implementation of standard driver parameters

-

- The following table describes how the mar345 driver implements some of the standard - driver parameters. -

- - - - - - - - - - - - - - - - -
- Implementation of Parameters in asynNDArrayDriver.h and ADDriver.h, and EPICS Record - Definitions in ADBase.template and NDFile.template
- Parameter index variable - EPICS record name - Description
- ADAcquire - $(P)$(R)Acquire - Setting this to 1 starts an acquisition sequence. If ADNumImages is greater than - 1 then it acquires multiple frames. For each frame it does the following: -
    -
  1. Erases the detector if mar345EraseMode is "Before expose".
  2. -
  3. Opens the shutter if either the mar345 shutter or EPICS shutter controls are enabled.
  4. -
  5. Waits for the desired exposure time.
  6. -
  7. Closes the shutter if either the mar345 shutter or EPICS shutter controls are - enabled.
  8. -
  9. Scans the detector and saves the file.
  10. -
  11. Erases the detector if mar345EraseMode is "After scan".
  12. -
- If ADAcquire is set to 0 during exposure (step 3 above) then it proceeds immediately - to step 4, finishes collecting the current frame and stops the acquisition sequence - if ADNumImages is greater than 1. If mar345Abort is set to 0 then the acquisition - is terminated as soon as possible without saving the data. Note however that commands - to the mar345 server to erase, change mode, or scan cannot be aborted, so the driver - must wait for these commands to complete.
-

- It is useful to use NDPluginROI to define an ROI containing the entire mar345 detector. - The MaxValue_RBV PV in this ROI can be monitored to make sure that the 16-bit limit - of 65,535 is not being approached in any pixel. -

-

- mar345 specific parameters

-

- The mar345 driver implements the following parameters in addition to those in asynNDArrayDriver.h - and ADDriver.h. Note that to reduce the width of this table the parameter index - variable names have been split into 2 lines, but these are just a single name, for - example mar345ScanSize. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Parameter Definitions in mar345.cpp and EPICS Record Definitions in mar345.template -
- Parameter index variable - asyn interface - Access - Description - drvInfo string - EPICS record name - EPICS record type
- Readout parameters
- mar345
- ScanSize
- asynInt32 - r/w - The detector diameter to read out. Choices are 180mm, 240mm, 300mm, and 345mm. - - MAR_SIZE - $(P)$(R)ScanSize
- $(P)$(R)ScanSize_RBV
- mbbo -
- mbbi
- mar345
- ScanResolution
- asynInt32 - r/w - The pixel size to use when reading the detector out. Choices are 0.10 and 0.15mm. - - MAR_RESOLUTION - $(P)$(R)ScanResolution
- $(P)$(R)ScanResolution_RBV
- mbbo -
- mbbi
-

- Configuration

-

- The mar345 driver is created with the mar345Config command, either from C/C++ or - from the EPICS IOC shell.

-
int mar345Config(const char *portName, const char *serverPort,
-                 int maxBuffers, size_t maxMemory,
-                 int priority, int stackSize)
-  
-

- For details on the meaning of the parameters to this function refer to the detailed - documentation on the mar345Config function in the - mar345.cpp documentation and in the documentation for the constructor for - the mar345 class. -

-

- There an example IOC boot directory and startup script (iocBoot/iocMAR345/st.cmd) - provided with areaDetector. -

-

- MEDM screens

-

- The following show the MEDM screens that are used to control the mar345 detector. - Note that the general purpose screen ADBase.adl can be used, but it exposes many - controls that are not applicable to the mar345, and lacks some fields that are important - for the mar345.

-

- mar345.adl is the main screen used to control the mar345 driver. -

-
-

- mar345.adl

- mar345.png
+

NOTE: This documentation file is incomplete. It needs to be completed.

diff --git a/documentation/motorRecord.html b/docs/motorRecord.html similarity index 98% rename from documentation/motorRecord.html rename to docs/motorRecord.html index 3cbb568..6b2a716 100644 --- a/documentation/motorRecord.html +++ b/docs/motorRecord.html @@ -35,11 +35,11 @@

Contents

-

Overview

This documentation describes version R6-9 of the EPICS motor +

Overview

This documentation describes version R6-11 of the EPICS motor record, and related EPICS software required to build and use it.  Version -R6-9 of the motor record is compatible with EPICS base R3.14.12.2 and above. +R6-11 of the motor record is compatible with EPICS base R3.14.12.2 and above.

-The motor record is intended to support motors of all kinds, but currently +The motor record is intended to support positioning motors of all kinds, but currently supports only the following variety of motor controllers (in addition to Soft Channel support):

@@ -61,7 +61,7 @@

Overview

This documentation describes version R6-9 of the EPICS motor Mclennan models PM304 and PM600.
  • - Physik Instrumente (PI) GmbH & Co. models; C-630/844/848/862/863, E-662/710/816, micos SMC hydra and all GCS2 (General Command Set) compatible controllers. + Physik Instrumente (PI) GmbH & Co. models; C-630/662/663/844/848/862/863, E-516/517/710/816, micos SMC hydra and all GCS2 (General Command Set) compatible controllers.
  • MicroMo model MVP 2001 B02. @@ -76,7 +76,7 @@

    Overview

    This documentation describes version R6-9 of the EPICS motor Parker Hannifin, Compumotor Division, 6K Series controllers.
  • - New Focus, models; 8750 and 8752. + New Focus, models; 8750, 8752, & 874x.
  • ACS Motion Control, SPiiPlus model. @@ -117,6 +117,9 @@

    Overview

    This documentation describes version R6-9 of the EPICS motor
  • Phytron I1AM01 Stepper Motor Controller.
  • +
  • + AMCI ANG1 Stepper Motor Controller/Driver, ANF1E/ANF1/ANF2E/ANF2 Stepper Motor Controllers. +
  • The record maintains two coordinate systems for motor position ("user" and "dial " coordinates); displays drive and readback values; enforces limits to motor @@ -301,8 +304,7 @@

    Field Descriptions

    In addition to fields common to all record types (se R Raw commanded direction SHORT -
    - + (1:"Pos", 0:"Neg")
    CNEN @@ -531,6 +533,14 @@

    Field Descriptions

    In addition to fields common to all record types (se
    + + IGSET + R/W + Ignore SET Field + SHORT + (0:Normal operation, 1: SET is ignored)
    + + INIT R/W @@ -857,6 +867,14 @@

    Field Descriptions

    In addition to fields common to all record types (se
    + + SPDB + R/W + Set Point Deadband (EGU) + DOUBLE +
    + + RDBL R @@ -1334,6 +1352,14 @@

    Field Descriptions

    In addition to fields common to all record types (se SHORT Set Set/Use switch to "Use". + + IGSET + R/W + Ignore SET Field + SHORT + (0:Normal operation, 1: SET is ignored)
    + + SET is a toggle switch used in calibrating the motor's user and dial positions:  @@ -1354,6 +1380,16 @@

    Field Descriptions

    In addition to fields common to all record types (se LLM). When the offset is frozen (FOFF=1), writes to any drive field affect both user and dial values, and also load the hardware position register.

    + +

    + When IGSET = 0, the motor record will obey the SET field and behave as described above. +

    + +

    + When IGSET = 1, the motor record will behave as though SET = 0. Ignoring the SET + field can useful for applications with soft motors (motors with soft-channel device + support). +

    @@ -1802,6 +1838,16 @@

    Field Descriptions

    In addition to fields common to all record types (se performed (see RTRY).  + SPDB + R/W + Set Point Deadband (EGU) + DOUBLE + Before the motor is commanded a move, a check is done if the move is to small. + It is to small when the distance is less the the step size defined in MRES. + When a bigger deadband is wanted than MRES, set the value into SPDB. + + + RTRY R/W Max retry count @@ -3124,8 +3170,8 @@

    Alarm fields

    R Raw commanded direction
    - SHORT
    - + SHORT
    + (1:"Pos", 0:"Neg")
    PP @@ -3889,8 +3935,7 @@

    Design Decisions

    This section of the document is an attempt to record
    Suggestions and comments to:

    -Ron Sluiter : (sluiter@aps.anl.gov)
    Kevin Peterson : (kmpeters@anl.gov)
    -Last modified: January 7, 2015 +Last modified: May 1, 2018 diff --git a/documentation/motor_files.html b/docs/motor_files.html similarity index 100% rename from documentation/motor_files.html rename to docs/motor_files.html diff --git a/documentation/motor_notes.txt b/docs/motor_notes.txt similarity index 99% rename from documentation/motor_notes.txt rename to docs/motor_notes.txt index b7fe93a..7b4f692 100644 --- a/documentation/motor_notes.txt +++ b/docs/motor_notes.txt @@ -83,7 +83,7 @@ OFF User Offset (EGU). User and dial coordinates can differ by a sign the FOFF field is "Variable". OFF = VAL - (DVAL * DIR) ENDIF - special(): IF new DIR + special(): IF new DIR, AND, FOFF is "Variable" OFF = VAL - (DVAL * DIR) ENDIF load_pos(): IF FOFF field is "Variable". diff --git a/documentation/motor_release.html b/docs/motor_release.html similarity index 92% rename from documentation/motor_release.html rename to docs/motor_release.html index d23bcf1..bf856b3 100644 --- a/documentation/motor_release.html +++ b/docs/motor_release.html @@ -2,15 +2,195 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - + - EPICS Motor Record Release R6-8 Notice - + EPICS Motor Record Release R6-10 Notice +
    +

    + Motor Record Version 6-11 Release Notice

    +
    + +
    +

    + See release notes on github: https://github.com/epics-modules/motor/releases/tag/R6-11 +

    +
    + +
    +

    + Motor Record Version 6-10-1 Release Notice

    +
    + + + +
    +

    + Motor Record Version 6-10 Release Notice

    +
    + +
    +

    + Modifications to Existing Features

    +
    + +
    +

    + OMS support +

    +

    + Ron Sluiter added a check for an invalid MAXv interrupt level (IRQ=1) + (1196bbe4df5968ae4ac05c142a9f4be93827d06e) +

    +

    + Ron Sluiter added a check for a new MAXv failure mode where the board reboots after the 1st command with response + (e604c9588a087228dc6c0333818e00113df841ea) +

    +

    + Ron Sluiter added an optional test for VME58 failure mode where the board reboots after the 1st motion related command + (4f54eb502bb1e4157db9a0587cfdbabd66de0c95) +

    +
    + +
    +

    + Aerotech A3200 support +

    +

    + Ron Sluiter Removed the "Task number" argument from A3200AsynConfig and switched to using Task #2 for the ASCII Interface + (a52ec2f62ff34b30597bccc7de9d70b4d2ed7f86) +

    +
    + +
    +

    + Newport support +

    +

    + Mark Rivers modified the ESP300 driver so that it correctly determines the resolution when open-loop steppers are used + (5245991323fb8c73cd6383e064da7b02c2629fea) +

    +

    + Mark Rivers changed the XPS PositionCompare API + (44351c99d92837cbb283b21877a87ecc821875e0) and made numerous improvements to the PositionCompare functionality. +

    +
    + +
    +

    + Motor Record improvments +

    +

    + jmdewart & Ken Lauer changed the acceleration calculation so that VBAS is ignored when VELO==VBAS + (4b89359e1cc1b411f974c0733bdf0b70df303aa8) +

    +

    + Ron Sluiter changed the motor record logic so that the motor is stopped if URIP=Yes and RDBL read returns an error + (220d18fcff89507a236152bd17aa48e5f13ca471) +

    +

    + Tim Mooney added a field, IGSET, to allow the SET field to be ignored. + More info on why this was desirable can be found in pull request #53. + (5cad105357739d603218502eb38be20ee736b4ee) +

    +

    + Tim Mooney modified the motor record's SYNC functionality so that it works when URIP=True + (ac900b90615ef650f13a9f21a5f1c145c0402408) +

    +
    + +
    +

    + New Features

    +
    + +
    +

    + AMCI ANG1 support +

    +

    + Kurt Goetze added support for the AMCI ANG1 controller/driver + (8966aeabf292874de8c78754e95e14cde1f1c776) and made numerous improvements to the PositionCompare functionality. +

    +
    + +
    +

    + Newport CONEX-PP support +

    +

    + Mark Rivers added support for the CONEX-PP series to the AG_CONEX driver + (2b853366f48230356c869a46691acbd8c7391810) and made numerous improvements to the PositionCompare functionality. +

    +
    + +
    +

    + iocsh scripts +

    +

    + Keenan Lang add iocsh setup scripts for many motor controllers + (17d10a8158ba5ca23bfc97133901d8d6e859f1ac + & + a87835c14a20a8e11745e16591d031fb674f0e14) +

    +
    + +
    +

    + PI E-517 support +

    +

    + Bruno Luvizotto added files for supporting PIE517 piezo controller + (f31ed90b255a554a1930ac721d595ade0c8095a2) +

    +
    + +
    +

    + New Focus 874x support +

    +

    + Wayne Lewis added support for the NewFocus 874x series of controllers + (634e49d5076d87fefbd875cd0700e7feb6d062e3) +

    +
    + +
    +

    + asynMotor support +

    +

    + Matthew Pearson added parameters to asynMotorController to deal with automatic amplifier control via setClosedLoop. + (36dfab4a78725866fab5bd212c4c128a86e9f044) +

    +
    + + + + + + + + + + + + + + + + + +

    Motor Record Version 6-9 Release Notice

    diff --git a/docs/presentations/MotorRec2015.pptx b/docs/presentations/MotorRec2015.pptx new file mode 100755 index 0000000000000000000000000000000000000000..1d113f0c00ac7782001bd301059c2b67e6580855 GIT binary patch literal 389029 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

    JWn;T)a_(Zj)zNg@ZMO%N+ z-gDGYShW+J3wI*8V80vmXab_ifcu)84Wo_gjX5U713k<0xu(H5$|fs8mM~KzEhON= zY*_#ci*dJ~zup^zl_Ni)7=a80mPD50EOg9 zQrV1eBzKB^Mh}`p#FL|IAPri`u_~bto4h(c<7fB~S3?w)2HI%`%bVrQ@0_tUWCz}Q zPbV4E+>HUp^I}X2oxtY+f*vVIn7lHBbgT;`9tt6Yl#y7@2xBW)jaCR)ftBU^e0JXj z+ibB4*wJF9*87oKzEJmMsh;tI@FTczjERdB8iUc829nOUJl(xB{oT2+<%kHfK<7L` zrrEpHO4<2V^4C6ksY*m<;&T*VeVa`uUEbXB;kRjhk11b14X)9e#lKwQQe-KA^Zxv_ zTfKmL|CplR#$k2n2YeZ?{-gM{RjYUNI!7cia-8nh(R1>pd!Y1DDfi}Z&7sh4QxH*X zU|zQZoAoJIxBL(!NV|F=*1RRSS_`{gLvZ@S)$zIfh3;&<3$EQj!dA7d+DgjcaS%#W z)_@`v{bWXSe_vUo7YZT*nFh+6A1=QcSAo z%NUd-qb@7-`j@%YP}tQ?r!#l&RPB{B=IZ1zFxskuJ(EMG-wn}>DMKBDv3duV{ybz2 z52wbrfmYnB6FR%9y#ww$JJrF_V%Wt(75l`oo}o@qj=>NMA4n_#DAQAsG3 zg4T>S_|Vv!og1i15m zq)v-A<--L7vwc0r^JF`9wi?>Xgn`HAV@!BtF0D7$4v%*`J*&5mG6$da`>W}@O7qC~ znX;GJ8u1R3|76JvyBq<9tezDZ=uD2_6jRV8;~A;>>{Pi&V&x#noig}PqdI8~6Gdg> zH$Mu>oHT6Yv@^J<0+{Hn@%QpJ6KrFmOdWTiOaMn;oZ+}ONFUQ10o76oqTTFh@RHog zZxv^&F3~YU8D534M3ssCH(if({B`kaAds4a5{dRi`XWe)jb|wMy$Ce?C=hF-ud9MI zI;NsTlj5{AU@&-Tx3B*scIb2Uoh<(hl^*>lNBrkd>AyPQhw4A-5#ku#b&Kv8SFQ${ zz1b)@m^MVx5kW9#pY`1J$}`i|=4On=k&9(#)Q{b9^W8F15~83t;EK&?1pUSd3f-sR_+>>>j@Ver7V&M1s^`nYJigb%n9Gun?-m|D8wIIzDy-%)q^jHS%9 zsE$dnHMs~c$6Ih012vh!irX+ziLmyC5wGsQUq=^rZTc zvSc{s-H~>N{Cz{yhWbQ<2n!$r@Sr1@257;~?Z{;^{S`r{yRRagqdjX{##`Wkg=te! z^Be3GmZl|2$B;({RvA8AcFaN)aM^&8;Gd#JkE3YrUAb1zc}m@OGRAnrK8Q%Gr{&?k zd6$$Pc9!rG1r(rS47v0CFEXH;W>xLBU{WXGy5oZUZZtz4KU$LWD*+8>B>v;S?w}4E!B2R8r zhMH)s+RaJpyn1d}S8iQ%Zaz_1Q)bjwo8~#lpNC}+p_7pbyX)@^BaE+%n&!-XK*`Fu zWyINvW-36+2Po2_F8t-(8)l#Yq*qS-uNU(6vFIPL;f%5o=E3R2ut_f~;Z%bbVyu$! zXcCGa^&X;2)E?}55h3yMMvRv|LT&lOjCORJd>zO!GAwL@Z;WNRueIoyZ?NjC++dae?uUNNsLqUU@~Ft5Uerp z(a|R{p%p8a%F7lgl`5e!>jzg+N35u3S5X~Tw1RWoW55y^DT1 zS_H#|40qGpMAHz0rDxtkSK4y6ifE-Le6Us@XP0(94Ug{V5mme>W~^?eZkDT3w1g8s zNs;T|trR&Kh_bVu#f7Cm&kKrK`UMHz0k3o;_zPFPPQGaUdF!N9m-FjB>&5p_@~Z68 zjbNxpc|A^nkn)ui!$tea&|CpiWJzdN)*+`N` zn|`7e5e?tP3Nxle;fIgjFzPdbe!L$mk%dzrA7#}ouWd968Y71drSvl(mtbm3-LtGU zfU)yuNTz$_Ev#gSsu6d4mhLD%m$$7&8~_H=GGZN|QF-*l$54C|IKg=2fs!7(r}$U4 z5GN1ZQT!(`2y74-(KE1IYG{lOiOD%v_N5lYmDWV^Zxbyk)kCyIvN&i;!hYQvaQA7W zd?-Tp>riz~{(PsZegIa&R&bZiMjWd5Y^L4?k%QXc)kFH-IMjkih1)@C0BGc7f$y&E zg=>dR{6nIU3SJI}>* z*zH??y#T)fYI@?OTbQ=Gr4gaYJ&1o&NFBkRchdM-1ye>-dvWA6MUj^+oh_R?IkvJi zLX$)6xITk(fqjY17je3;aa7;*=7wO?Bgdo4Yx@e*L$19C>}F=!C^ zeV=j*A-~Nn4~-W#mXEX?2AIFSRC4n}2!-NHa{af|SI^tyDBGpf@6K-+6UbgjzR((j z53-Nlpz@Gsxj&-B$adU0A4;;ut|DWoHlNa@-b%EQt@3?_3+mGvmI%?q-ZJYEshWWE z?}FF*)tx3FZ)!{Bq1!M2EhE(WJ<~S)g8+20{I`tIzsk~=S{rr;97w+U2Hyd*0|sao z+NnP7^79hef5-*Mkq6KEuDj=cD1HT^Y?7RJFkq+fYrbpp7xZiUqTNH1-0A~@Cw++$ z4Yg&FB}RU44$P$%LcubcEhnHykzo>OKLkH9@9mQby^15k3I{afai-rVvJsDbm*1cE zJ-4yNjDbrTm%F_5ijnR<`eKln#+qi?CJgK*M$xD|kqP+FKCmhyi}2Jbq5Q*^$8AqW zNl!K$GQ>`Ug+4M&rV$WA4M1b2iB6gd2U!XSff5A9YV;9J@R_2%SQk}?X+P+5nk*mG z_Q^@VOrGpCsFZPiS{M@#SffXGmP1{}h>elm-;|@GeKdEwP^0R)eC+nMhu&A^&x;F2 zr=ox0=QoSwzb(f<@Uz}Si$23Gdb(9jwS)Dd<#M1@!8~Y0?+vk(0>?say!O33O?x7R zaef*r@CDf|8z(}bF8ROM^OZStjpSnrxr8jIgJMPDV3#@h)RfM0b0}25TGtX2S~+{r zd*qPTl$ZjvkadJw<65A)`lR96eQZ0Y$(;&4UhmQ$X!mjzU)GXA9)|~DuznX1L?lYX z49o_QXyt0*5R;M_UwA#GJhZ$66^a8ml95Vj$Z0b^_2^Oq4g9ZBNwn2iq*GyB-aC*w$;j zhKRV!S*hOr)*1!58R#u$)T#s%N^Mxuxw&!~P0ut7$uQiDgO%EnHSg zFPuU}#EQjoM8HZlQKe?AyJJ4Tzqd!X(HumlirehN7h-%kW#T%}`2yR17b;q9Y(N_q zI28`NjB)Jl(D01_>GP=im?!Agy9DGYi)fm(6u`YlRK5%=@y9HB_Xs3rbnXO7OYs92 z+Md6mM!jM|2fnj`yUrR!$~mS6-Ko%pd;CTR7yFg-a-^%Myun}vAy14;=O_oMgHEG! z4Ec>n4VPjr)2Gz_N3(qku>>hqigaGERw8;HrXo0hVc{h_S^UWTl(_WFIBDAK*js8b zLpN=X<+>y}6Pyvtr9uE1=BqrNf5c(0S=3?ypYCcNX&;f4 z0;HkmQ(Vp#Ilf)+lV)ML0ow!;GyaDqT2dCe3__gSqt36^>sisdC))BoVr1Ws_dH@D zRIxM;@w7G!1{XiCS=hOovXN6}RiNK<6pB0DU+%!SVcJcq@0Xqiz7Q;Um_UZ4vOZ;y1i_deYnWx|OhI?Eb=~*)R=)QyP5u zd_C^6_)a7-<3H?I0UzA(J2&`}SiqK1zvwy9A|Ym6@w*rN7$(_ozE7b6PWoFO&4h)q zuwB1l{^5Vrut=x;!~byg7XNw1HEK}ttpm4%`mGDRFn>?xias*T(XM6v*1wMI-pxC? z-d5!usqSSd83X2T`z_*AB^F+Z*iVvF?qN=VYj-mP18&5ZEpXCdf;H-uxXoE5L3%}c z=Sx-1S}*mkvo(0%C0XTyHOP=g-MaFTe2g&L=Tor@5)5OZl{gIz*7xt(y2yQ+R_~pH zL#$D()aG0rf^ zCUuWlPFDBdnW(Y49pSjEYP&)$Q>pd|1&e`puRJj`EFMj1$kJNcIJ*sG)>54k=U;#4 zQ;ng2q9Pv&^@4X_H3a+xM-&K(r|#%)fLW=}Zk$a$OQN^-sFu)snniFUspl8jAqtVO z9|FJ-7OJG1FcJqO`4@Mmb8HRO_Iu!)ZtmdFFQa;+(3rk4w*~w_h;@a}`0D23WNK-K z*NrS$oXZzsT$}-CBcPsOiUr}1m^zKji47B8<;Uub$@Baf!p!~EfZa0G$eh*06ZluTzI zNm4BcN-480MVTcqV^bD8E+|M;KHAJ(nhu9=(QTm2^sr?g`kSC=mQ~Q z_0YqFFS`LEatNSkpKSn&c#8uT%$&4DgwGQ8XG2~y5#_S^b}(o>k62&Vy%#^Eu&?H~ zS8>}YY}ox((fzv$+}xV17=&KYu18#A*LGgXDY3dx$POBzOWP4hyQ1p~9w8Bpz@C?F+;`E>VY7iU?+l^GTQKO+`T$Yl^8F0;FB>525&b%Sqw) z8DxTxnD?4LmtG#zs!)j^g%aC~`&oi0#v1^~T>GfHuxs9P=cq(kVGg|T!(HGq6F_Hd zE33FgE2biz@+!4doR2DZYEPgVa6CLEc9H5m1hwbboYRc1nEDi7K6KII*r-+4QCx(x z8o+N`pV{k8U5pVdp~j3UDYtVhq$4MgYl5~w`p}cKYOwa?$`@`*?&M0erFySlvI{-x zw&d(|b*1kGi3tVkz=9^BEM&>0#=-*kbvE|JK72>OB4n$8GHgK`G0Zq@H&|2X9w;s( z6%=_c;lpADm`+22z6gKs5yT`?*eQ@$x}-kGda?kk6E|jz`&e_+6S_Y46W31l+i<#~ zr+hjJQS=Tr=whh6-k{_4Z|eAa<}jP$_!LVgIYtg`3my9?s;8)g9-o3md4)t&pjLBJ zr#SxB+}d*KE7FjgKZ#kEH=6y9n9CmiPMD*if+uTDeKp*83RT2l+r}1^oH>S%NqY=y zur-KTfiGf^&GCF$c9yMcwj}$?BuprukhyO->3m6+Eg+_9X!k>jh`=%GUwzmBV%OqL z>gO2hGt2*rOHBw?2nAiS#}vIs59@8nFSE-Zssq$K8E+ISJzSHyTT$FArQG-uX3AR; z79>p)`u~R2|LhD;!)pX!A zXetOLs40iqeu!XBZP{9{7k1ZX_~>z2@jSF6y>-oIVb-(%CCr$;A|Aa;)L|3;P|L21L7o z4hMfPKwOX|srXuL5iwn|MSy+Yk8_Rp+$9(el9uWtI@;G=m^=pp~^$7-35P_p64x0$hQC@$PU}F>YEBfN%;+G74^*Fr9siKuM4j zgyjr+g^@+hYRV}ayl&Byf$zuQGr>@78+TmLzVrpNSXQD zIIv%nG}m9uKlKt#7WPOkbp2XRI0{WfP+Y}%YTd+D^KZxQ;^#v>Xw{EN6HL9QNy-m_ zRa3fv!5lF{t~^s%kLynhIdF?DQCL6bzxt%g9XRK#^!A49ZU(O>CH1Nr%+vlxLYkF_p)7&n*k3}nw``M}$lYWSlm_)D(Z|HF6guns)ca(%cb$hq`iIUAo{~aa&6+k)E(6;+Qbw255c@f^-P2LE( zhdBhR2ZsPWG2FmDODV^Rgc4{ZIiFF0QMN?Y=fCMnuusvvBqiO<5@nb~!5}j66ZQ}8 zbDiNy^}4yYQE+N1*kmFd5pbJ;ML-iMk*geU_q^7zz(zG_lqO5^4-BMb9ef@S;BOX3 zZ&CVe48=Tf4wowxF|ZOBfU1$uS+P5We+ zM$alsjt4?%W6mWTL+55?Q!Z#I&oq>>uo?`{d`*@R3y7idxRxlcWGbm6U*t7um1jI} zrCnr*(SUXXkvIT0ff#Nn!avj*T~Y6$FR06+#<6A4=|HZ|n&AMvX}`eeVsB}PREqt! zCw*H2HkR~z?mey7Bw6Iq(h5Tk%`A_u!!M&1>kmS?X?^Hoh@a^y9tB*t8*1idJMQYo%9U_ zJ(~M_FH6*^8n*eMw`yeyM6TH$5B&S@m$_}5+a9QkvyfeI=Mjsp;)^d6I6TDZclgH% z&PI>_#{dCY{1hcuR+l_ldAypHM=7ZV-WT4f8~Y^DD;$0gq8nO?l9G1jax{X2iu81a z7`jICZY?eAUteBv0rVq#F%I-x1lfp1%5e%ekxtCp2oy~1l=VD*gsoj6$9Js0@2C6K zvgA@}8M|$WP0r@bE;&=j6G3h^O`w$Xv3C z^}94Br@v`Z9k|jR3CPoULfZK!{dvtjxHx~=;K~4l;*a#vlZG-!*g1ueCx+Nd_F8=_ zWlmLXy00YPEe?FLM(+EuTf%Ey8E)D>C7xMYb7075&sjRTVaUUkjcJ}J*FRu!Anv{d z1$3iNkEFGV=lB*grET+fqq=#mRebu1_|9#@3B!^?n=+fnwe08lgm6Selr@htr&I#4C(x zSEiVJ36WT>v{LzfxE}b?l{Yuz z1DVtVarwwDj-uAO_|j%(B{T)Y(;_3lkfoOZUQ!whdK?JMHY?}-dboCVg;kg=X=={f zPBiXhy0Ut5igj^#)&EaIvE=fxiS$ow`u(G%`(Fys{|ZAas&6>`Pzii*WWE6h%oj*p z)5x5L3#;Xjx#u*-!379Nj9`Fh0L~NT%>EKyS^F2I-wgQdzwi{pqCp-j%@(v4t$X`Ef4bM*2OL8N zE(pQj&PvCOfeYqKN-gUDyLp(X?@{XwiRLx{#nS&Z~+?~jV5nddec#~@;3Sm8aIDaX*+Vi zs1Tw7?B*eH0BiCPY*w&!7H)9M+3mYi-5LtIQZj7;wXxuS{Pj2I6U;5v4wmSMgmW_S z@iU=|q>JM>cR4D^OR|n(W*GqN2%BHUE&n7>a9dj^zg#*~EO9Y2vUB86u7tCjoL%syLuR#2x}|iXql(r> zcIK{uoI>LpN!is%HruzT9IY_k={8=Af5191;i_F&m)ydT+TwZe)vX}QbH5++Wy=JG zwMdN`yOYNCh!*Ahnp_o(CJHiT^g#U}h{L4YnvfIx(PX?!AoFmIq62;c3bickDZQ;W zia@f{g78h;4z)8?!?%D$ry=G$4P3V_mFoE0WB6mMQ_x$?<|+1bS~3n|gbxX-He ze~4rWmtY7(^v>3o8%h4RxE}|Q8Qi75qy!%~h$Tc<0?HKB^cq$adi1$f8Kr(M!4yaV z#rcc3;5X=ir}TtwL7Ip8puS@PBOH+_oLkADYEM^=@ zyQ|VIQm~n0LWo{K%|#Nwe)Z&#W4k71JEkf;){dg76i|ZyD6t@)c9=Z7O#k(A3NAzy zNh|lKst^2C<9wu^c+|Q`nBohmtCvQ)>t_Wi+8FZTjN-aJ#c}!0w)0-&!Sw9Cbv+n2 zd?(t&d@jEqHB4@A&+0(bdtHR*d)P`}#cnK@93{mz1sX@d^X&EiP-@ zbQM*;y>qCOo0V7s1u#OyjtZPyYE=>37643|AkY)lH&Ddn{@63t=hxfb<`#^Rv9{~mb3y}JN{_<<11u>L#x z{BJb_&53_1qb>APegv)NUXFWVKcnn`tHB_kv1r4e4JK1-X$es(2q{N$`v8C+k=xJR zUFLlGP5ttFW~HTC4i;sz-I>bK(S}aiPVn@U4lmdr(i1QxP$9S7q`XDL0A559?kqPr zdC$$t>kc{4!n>8BMqH zNl|8xf5h>Q$I+ERU|^|E$wzjn~-0R zz2OBs&!=@9r(uvw#hCy=He_yZ$|MCgkJgg~OA-NeI6;^_ED?2Z4C=}HF>cPbr)R~d zOJ-@!m(bu@Xlt_V7XLTo&0Q96lJ%}p#y{sG?51_`X<&f1dFu$^Iz%u=74r}6G0KFV zr{z3?&*MijVBh8XcrU3-3J&DA3?kiZQ#9lpbOWGEG0F+ytU$(P^e@$cXw(N8p+a;> zxMJcdg1R)+^+7BhTQVVDZltZiAgA$FNWM$?+@Ngcm4hi5Cd)PB*~ItHGI z(uQOcA@T)vUtvBzqnZAp%cgPSB*lQ!$Hd51bxSzC#v}Bw0J829Y0-F^Ez|zQ?#1VU z@%>Akf4p%)$ly1DC@pBhJQG$KS)lDHD(+AaV2aBt3t9&{AWhi}`^^cgJM0)~T&D+U z?NQjA%&38Mu#Xs>-rP%YG;TL0`{nVe2Me0vo8}B*o;J;CZ#e|ZxtPPqN_LOx`3JF^uWwzpX zXRN@~IIntQ9Zo2Ld7mJ7Cge$R269-tiWv(D{w*(^X}@sWu=m~f(%;SD|15Rp)eHzj zmBSlIdQjqZMJQEd2a-i7%%#eAdYdMoK#*4SOOWjeLt*F!svj@HlTT0!jf~Ue*9$p; zhk1dGulD~znuX_gkM;ABh|-sV_!D5@gE)fGKtN9V58pYqxF(dkJeqMUhCYMDja{-M@ZtzJ?UyySYE0+ zMfzKvHFP$+5(VSj|Dx-yf+AbGpiyLScX!u82ZzDk-QC?C1{!xA90nQO-5nZtcXxN^ za?bb1m56g+s#oRS58b;WcCT8sGSi#0;foE+fpSQUhO$f-r^MVPUbA|qRCAJyH*VFC z#)DeJkb_wfFXq><&FU$W_{d5}h7WH#Ri_EVc-<1Qpc)rNJqVVu)3OgUj_%W&;!YwM zf%3fIGh!2n)-(Z8k#zgS)U0LKe3wM^|60gK%*J9Wy_e+ydRY$m0n2)Knbs= zAB5SS;s_HB`Z{^b#e;prDHa>Mm;RfMXE>5|=36uJdTsC%d?p;gMyjJp8pu@s(}^oD ze5{0`OhNiv{LjJm4&oUU3(Px>;wqLF|jy;*wi`nb6pKRZ}xx#j#$99@E z#eaez`f0**o5P5tI5ttWUX)g6_)S*{e6jTL*)!VvlJ7rmLg}A@dU{^4Bv1 zcz`O_roq~IF^7v*EmBx2%z^DCW-VhZ&&W_IsMpvoGnCb|a^e~t_v|<%?2^BdW(sN@ z8)w(XzG+z@Oxmm9A>^C=)nlA5i*&P`v(_89t>{cnch{iXR9QilOFwzxM5KDz=hul= zc1V<*S4I;X6VCI;A^ElxXc+C+3zy@C*em0k>W^5WFxV?0Ryq!Spv+O6-xXW^^0JQ< zPAzUFG6mEa026ggWw}usEsP3U0ShVNL7NzQCHPEwlj3@m=Q)5yj+($m9HKTOK^gK- zZL%mH?`+Jc-Pgj1sv_7|eQPx*U_LCVRj*7rT~KbYf)T?OB-$#KK_2v$G?<5<01F;W zwOmWu(jPS7&dYJ@F@TH%XVMrwmd*1U!%s3Gl=fg$-G-uv|2+MRt0Smz^p_Uf)lnpE z0dWdD>gxoq0Y5*ma5V&TcFpPIvFdYWAr5}R_DbH=7rHenf;rzXg~g1pzk1WGm$rO9 zix=EJ$y`|~6-AL4AH-2I3ES|0f zJWRqbIi3`wK}@KjLw@TtK5_ZA?&0xeu$r1|+$a(2aa`i_^+5Sh-X@%b?Fkz2ngGob z43>|fMn4YXX4Gy%MSA)`6jgGC5@IL5gV?Bz9l}KIhDY(#Gwd5R;kAR5uoRjibxT4- zDC%S;m`&{;q(NMP-h08qa!+W?Sh)RO9T9muWdL@n=;*B>@$U{v?SlJMfTCawKT*7Q zu3V88QsIDQemV`ZoLiz*ie@gOB>hGl1jcxa6JgzJ{xNysqK%o&?`qn`>d4;t2|sin zYxdT%Jxy08`8_eJAhOXNNh4G1c9;m;kZa>aq%-8&qzc|<5b9#(C@&lN2v~PrWcbzb zOTzd_=+0u{e;AK$LL(UpPE4k-6AhIZ3x@M*G!D;cE3^UpS9nHl6Wz07sh|}Y)wzfk z$Bm660zXjy@^mfRUaY9PU$Q<_>jQuD@lrC{;PB z64z)ssTvVX+B)uLO9B^9mJqG0LH6D-!T!Qheg zFl>1KRK3c7?eAWw1d!z%>UgU^Fjj zlLQNEMMy-n@aDGL>~N;q8Z32Kt>>{=p$fNd)uLoc#IeyZO4W5rDql4N|BV@E=e0cs z1GlS$Alic12nR`pIV`^%dR}&CQiPnD-L+VchR%%L@n}&xblxi8O=ENou6AFYtO8O- zO&^!(8ilGWCc5Mo&aZsibkvbhoJKR@Zfv$dL}wuDIGT;4Z_jPu98<8vEZ5F2r_wNh z%L!t)HCJX7`wQop>~|YoGZ#YO$nW+TYPj!CrKnDC#0P@3cSZEthp;zYa3HurIx8G3 zzdulavtq8W@HsUE0TG5rV>VQOfx6y}D?{HIB7zLY#g!7=GUbDyhE!jgdDM2V1NV3Iey5@A7P;s4X>9o7%XmU1TQNu5|up?7;C>ynQ2H7AV}@WcGTO0*Va?-Dv)0a z&wBOAQ2{_<%EgIDzs?<_fn;#)I#*f;*7ky#t}T`t`VQc`x!i`DfA1AY(#A@4&dzfq zpAiwhE5uD55>BF`Mz0IyB?#u->f`FAzTx10Gb>+bB^3tZpi z*zWBAbH(&Jk*N55m+Ds9)%{v|)$h%QoNQU@?TnM6#Qa+M(-}C)us%gM^i+s9gbj~% z`=wB7#;?i7ABS5i1G8Fe*}MAtkW|&z#}6)1`KXmD5u$W3LcMIs@a6u`q*K7wg$<~r z^Y)B$ML@+`7H{$ z;C|Y)w$xsCLPht_9qivTe#)##B0<6|lM-(A4hg}x8tNbU~B5G;EB`Ix@) zyljzAP@mM-F@a|YpHaEeL%tLRCFMn-*{{>Pa^o$p2QNT4pfL+f)T<`t_Ne*XMVd5K zuS4&#t88n=8jFr!XPO(%G|{+(k>nhc4gRV{Ri+1*^dA0XH#TICNH+|jLArTAp?n>1 zkwSB#P7oDqz7|0@Tmo_8D^kLm+mkJp6lIHZY?F?A5Ue%nS9+ayDu=FN==3SslgOs! z@U7)l4J-Up1>%?)pcTlJGnCT8sNX8)Vfk8av2!t?V)_7An;WSIGNQk{ITaHR2S61_ zwGm5v&LFT(e4dV(H|!x^Gx{=0+j0w2u5il}Dqv=h`s2Z%8K60;PU=~Nf<>ID8i3{4 z(K~9}D*wSbUmGzWEvEHm&k69C5&~SpJ=ufpCla?u34;XogIV+f{(kkBE#H!s**oy|$Lp?hK+Gom zl!+h-ULstkq!=5m=ZY-ziGIatrTxtl5F)k(M|Xl#-qs zRPU^E`PFg}c`FvzkFm(8_qbnD4}VFI;S4)d<`RFwBpJX@NHItXZA-x{u6B@1>q^bQ z(FC(N$coCZZzToFY&CM+?dafb&(@*|cuXK_qjPu`4cV{RZetdxmH0paS}#5oe_&InREE~au?ztfn~ zXGqtHSmB!5p8cEY9(R;Ox`@^Qa)Q}G7}ZXv#oqS!FBS_(w8{bJVTuPoz5`KEM%|xd z%7}x1GI3G6TgnkQ^}cVJSa!rlCPn!Y(DDFQ)4pGiZwqlS7F*pA_RKSBQbR!1Rh@!< z0KVw};@thjCu&;(`ys*eV`1%^J-etkS_a=!{`|!AT}4L~OLX62iV6Aw-ZPsCMqICs z5TZ_Tq35`tyy#e|Kd{WttWR4Lw^+vr@9P|cAhF%JVHJavW#?<&UA^!FH;OhyEHWHv zs5r{8aL@5X?ECSt1vf=_(~<5Km^H^zjyI6*7l*Spkb<*m-)!A$EDLXP3}uvVloeb) zPF8i&TtI+s((H=X@kZ!oY3lBlpK6SEn_bix$V#2gSUL5Dq(Cn~2P{ z{Lc|RXoo$@Iy{7dR87*$g!(LAXIN0)hq@$x| z#L^0xTSZJ5Ha1FX{Bh}NI?w_Zmc4e9bu#lCLRAJ%V9Ghe1tRm7*YC1-)ty1|8lccx zMHKQYuvqG>=MXGS8a2bHBbWET+1uei{t>|bI-ymN2LFZ*0txc9c?KZ?c{~hf=Y$6V z;W7E||DFF)?sUiPRwYn7zgJ&QO<7`Li@kkbN1+|LBXKTUbydr{>=lIdt zf50fcOM>-xcZcYRu~xTw=NVL{UT?AE+@k9I1&~d~Yyb8w^>B88^lq8+evw%kmJ8Y( zh2htY4~Cg1yO!IS1&%ovJXy9~Vp7%2Cu*qzbHkB8E(7gKqCfA;0sHhtMCdzlCw$(@I4W9)Rzn!A{1V))T8l#YYSJf6u3 zrB7kG1oWo_rhf4xFLGy&cZ&G?vwTDCwQDbTAa8pNi z8Gv=BH)75XDPQ=Fk(!RUjL+~@%AXi;9u(0Mv+x_g1u{0;iS$iC92OXP0&sxZh^-`^ zUhktdZy?A2jfZL=BA&xC-U+p+2iE~4*DLrBCYTnv>e$Mr(qh$A2Z8Y^<=`N=QB)Xc zSyw>ql*KeSOJySxA&76R%Sz>bsnQwSdYz1`xPtEd4~DZ}V8taNhAV+(h1esxv3e5; zanD}ql)+nOg1%c8ZUmFF#p1QqSL({Rp(t`N52N~u*>yYhR3?}?--eo-eO6vK{iU5o z3}ewS`(@FhHfettf4S0%_L3VI1cFtUN4-4*yMDSU1R8v7B{(%BISp7Qm|sC?N)2;E zCB7NO>ew<9PgC|{cr$8@{cMKNpJJFK^~yq9Qj?j+W=gS)fuf!}$D}uBscGDhGjdX{}xQlARUHpPt(t^WTHt@QU~l zLu6z`ILtj2!PMM(MkTos@+GW1XIiJKDys*;AmioXr2c45*B@+KUb@TQQ(pA5V<jwkPnOTvBulC>HBjhXL)tezrV3DcEpT$ zf(i&K|IHy*qm1qa2}RR?a^jERTvmu1ICkM|I77`AYx2v0cf|8pHk6!|buIQDnR6o; z$V~se!&O>VoX&A)Gk-UBT|YjfnOgnbJX|La#a-pj-OhO8R)uMgBQ2lG5!wzde997R zUeFTtG^CeX63i0X0(;mE9In7$025I1m%DJAHpUny!cs=X^hi#8#GqigkrgK!BhL~bqlLq+(YXP7qe_RVkbm9 zFM_QacjQ@VY1_}(A-vCR15$>RcfV_@%H|#>D-}Jb#ylR{DL%! zgt4V1_x%~@zc>GjVQME|F-6QyPkZrqYLj|VbHamb5!N8Sr11kNlI7fz7M<8$!A!bs zd~jjR0cYVGd{iln9@-RuQ3!03_E(T`a_!BQwL{qYAS&CG%7gK9F*T_RMZ_Scs4Oc& zO}RFSsuRpGp|YBC3%!Tur4GVu+$V){Zg! zSw2|!QS#3f1Y(A9ku^IINo+ppkT<~9F&6Q6@EY?;%L%V`Pqd3t6cU>GvZ4rJCP!KORZ9^%T zlgzO#aK#pk!if>R0`YRCwS3TCZwI0$POWecxB$x&_HpgrR}3=*7VM;n1#DP`)%bFu zyOWPKd$|NMu^xEw0DlZ@|&=~{>yanOsoUZF`32`ZuMH|KE|E?e9Ms2w+LfG zdh>DC5X{qAj7oOCXw=25TD3F`%jAXy`SE24Uy8Cjq$c`XXX?J89!TTKi1qK8}(N=R?8wfGE@ihK zdOn=Krpb|X|aKH}}oxQKO;6uJ%X>C()xELntXrsEH z|FuF?fLm&Psd{#aRSfR<*A&;gV&oBS?n41NQ_ZzX^3^Y(mEG&LJ?>l%!kiR&Q@@#g z=~t7)Aqtu0U^8!80zIb)_5kfzne(JydqeAmGhiaC7-hY%>9m=552<&+^C*Xvu&^hK z?##~c3E{mPI;*cVkVir(3>WRoKr|;&j9iW*hr9V)lbOd1E=s$ab5h^gQAz*z0ZHWz zNB@4gL>*>qbJXMTrZ1Wg3^SYvSrFx7G_G3UJ%A)gia6nBZ4rF*&JzcvV|Gjg<3B=kR`MA37F-eh3w-V@*j_Q9iq^7t4%r~Cz>19v!MFr59Z2&wTsU5>$0ztj zW>1D|#jH7P(X2exkdwY#^HVbSVt97v(p2L~MM&jUrNZBa>G`=l*f?nL^Q>X!J;gAf zUbxzViwj1$4Pvi zB)qMwUr?Y=fI)WgtNf`?5U?-trbxx~Z~M?c4S#|`X4qT1!RWLd+OlSZnu+1vvC1zl zpDU}kdcQ@f#fBx8MlKo$RJ^f7SY+q_Fjx`OORqRo;+rPmjf#;O_F+zD%5CP&=OhW&N%kuI23m5ln8oajFi-j_o<=pF10@$-&b~p(n5b@SUPZuIXNB0kKTxs zO%1(ef{nEHDehc;Q<~IqR4qtw`arre3mS<~JjpM)=AVf+*m6b)qlK*YP_8_h=;hXL zt(MO2KDF4`vfw$R$*&JF-ue7L*hzAj|G)i6*X5 zFw?CPBRnRUK^j+bA{P%Y)jUl+gDPzRVDcPCX_3W=Q?AorUk?84TtRU|Ci?#Hy3WFG z=kaA%?zU35smTX0S0tobzPG$Q-JdJq%P;MtN1Wx|E$Z;ryZ7_|eC&Ex%T%$n>7Lef zMa_P|bk)tgdsVI98m;z9!QusM9(cCETR&;(J?^r!2iGyqb{cE?`QuP($`gI@r=NWI zKuyATMI23jt)OLgA{B^OtG^O;CG@we5Je_z@=kL!->+?cnej^q7DH9?rQo2`0;r2Xc;32H0N#!1IPt(V$9r!A;Ncx zn8xAZ(w(?RCIT!;M(|33Igg)IXBp)6gu-Q=tiSn_(rd8TjzBo zM#?+hD?fZr6h~L;k&CBmO9ifcEW^GPBX}lY!Px)#>MS(Fs^JY_XoRYBg_CChoyd?JMp^#^QV{WPAud5nJ4=-{X5bNPCV25qit39@8_u* zRPSZ?b1)0)wEbD}PH8u&6V8#XkC>cKX1mFichcyqi!GOJhI}HKShDRfkLib>zNFnA z>VdpK?*g0OZ>tR29DB>Ryy+7?QMCth~sDS2w7qRk_^r zsU$}OCJwjuX`QRqbvdL7#ZcD1$Oj*iggmKUYCm6@W% zz582Q-Rhanhm#RcPu)yrzSKO0v8e9XnPM;Zb#eH6ihAj__Dq2ak)R%nY}3Ch9})(2 z=j&eh_gQ=sS1Rnqh4~jtZi~M}5Zii6+kgg)`!8RrWwB)#&^2ff;)wSvS*yC0YIT>V zvs`+3;8kj~yk*fZom;m|V7cEDDcF4O?UAFT$O8R~IzB&M1+1*c4zd17-4m3`E-WWQ zD+(O<MzD*PsCxzJ8iql&`pJI4$rIwLBLyfWL)RzhYssKfIXK|bmA49<=%1mAOl&!b~Ak=*MOHtAd zcxdn)+!MSDHdoXl>^D6d?1XyS(f9llq%y{Wg;FSjc}?Qg&El8a;(w;I4JV9jWDgr4 ziuZtjfx4KJq!;hYkm46X6)dGPm!d>c$E;#NMfQ^(glNuo2`vAgjr}Y;zOl|G$>|}B zE}se3%I5$U)O#eS)DW=Q+p#xpw2uCl@>g96t5H0@JIYgb^zu!8nTdgA6?1tQg`o|- z+0jITF5ol5`W8nI$}>Vki8MtQ3E>(6et7xfTZrbEJIW?;r=Snu3Gy0Y2d|$a%pUpw z0ZL=O;PKTSjvPdQ{Sstnys};lz#c#JTVuN4t`~aiz4l#*V%1-c-{08;y#RNR#|Sfc z1soFgaT~-P{{pXS|4jaz{4=(jc{ww`xk3BvY9VySPbMzcn)wacn{?gZ=-ui1<7{Hz zveA4@*K4y6T?cmGq#qXZPHtw0fCnn9x}gs{Za-8=O!kpe1t+|J8}vkUBOAvg?X8W(9GzNT@lj;38WFb`@0A40hHqg1C?XjCH%@2=4LuK$c1u-!OFlZapr?c*@M zvER=;hhTiyaX15HMLy-g@DHBtX5+O56uOf(p?~daR65XRc7)bFBG2JlKj^*QaAI&1 z>Z=^2359y(=0w38-4Hs9aQM@?JO%7^u((tc8(?!YxfmRA8XYb9;AM`-G!Z7BugbL% zs&2imPQo8K1l;;LE

    !BI0dVqx`=IlDPpxGW;Jx^Iw-kqc?`Cr_XLq1sBk;SZ#UE z7UQuvZ;V)inA>u@K}|0vj95CMv`fUe_=RDk(6QsknQ5*Lq+v3F>J8qVO{fYh3I?lg zx`9;`KVhRtAZVDB3<|m>0^-5QAjJN;{~thw;A`CC__*qB>JcO)B+jU!aENIrc-ol% z<%=5jQD?**vw!-rnST7Ox8ZJ#f4);3KZ+B3dA!Df$x>h8kHgijb)*0mVxiz`jFwPp z-K`xOB*(THj$=WO1b{h@7(om-iVfS6X~y6mAb$Q|pp@(jetWUJS{w!f#$YJV+qTiW zNPxQ>K`rCnTYoAh;x>u91pNSSkk1G=czYZ}_Wv)SH0BE)$2;V}g4*FYUu~YZ=>%@> z-|0w$Dvu^pBu`q-uK)c-05rNOBmqHmrD24KQvPSroKN&#alaNVra7XSZqYUFXt7~$ z-IdOzIlCQ7z?DxPp5UJa<5fPg5RWq30$+P-*V4P5;grvvZW@}!o)OSO+Y#2}#pdfb zubCoL{>z-H)sXwq04qI(jk{eFhBdx@lA864?0aWLfzty)yvv75hD&}hhrF@on!vCJ z(;cLX!OASn5;Fz=(zS=t3t5V1f6kM!(C0}*3#2T|(BsB~VMDn%4N_er$0@Ps z9kGy^UxU;>&~&&(p@^9;ZRUd;pJfwgI+v?{c#hl{^QXx*pYuseP*jKulM_|1J{;3Y z@!r(RWL<2H+rm!Cgw|eDJN*rL8P7*)8wb6?*rP5Nc^dXy=U0=&musroneMVSedge<+rS#=25OF^KTSX$0k1MMDt0>=W^xx?*^Z(eS zy6aB)Uuw~trM^%R-Ya4H+qjQO(Xx{=e|bve%pPz7_{!jc7)z2~R;3S`57Q5l4@XdV zKsoODtO*nEWH@Bvf-mhmz};{Fkzad-l(Dpi_MD4R9!H}ka{9cdU=`Itm3nxvZ2q}Y zdXcH@aDO{l#q;iJ*XMbt+1l?GQ1@B4Ot~@FMfTn4;_-z7sZ|bFVQL-i`En^9PLsv_ z%)cB{R;n@htB7K%S_;bRli5!G9aOiG0W5*w9~h3DGV*)v*w5^&>T zZAhYD&vpE@{v5hZL*7zRR%X=)?!+v`bmGz0c>sEwqSY6eK6(%sK1$SxHAd|OGR?-*-N(2R=75X zjFf#toxk7E-ANNuRw;?XJ~{>A2jzUiFZi>=HFgXzbK6DZ8pDD9x4s_b)tJmQj8``s zPq*gk!gwsL+zx2I)jn#m>zp^cy=V>wP?A}v4fKvj(#s*^Qc`1A?W$G|OVL|(1#oq+5#qN9p+Yn^+N+$q z1=d{}Kz6b-I60whfdc#VmFD8{Rhh)y{Eg?r>L9ZKm{}reATvpFPGgyh7_%5Rd(JsN&N@VwbOj&t9jh_g5N{L)%2;!_qc9 zYWsc2Xk#6cxRgFf4c$9HpUrS#*?=t3FqyxE=(Zhz7uGxK>Sw$M;f}u;i;pd^2LT`6 zEO6C~-yGC)azP~8)TvX15D%V6=J0zl2Fz@+x!-W}5`^;a$}Y-!RNJa%)@C@6<&30I zDZRq_hr^s1>~u2v$gC;D_L{Bx@_MpJQWM3>fZGo;I@Q)8ZWeX`xkA4tkF83sNEL68i`%ICZy__~8+mrx7VJZxQ}l8TBj@YA@>8|oY!>p3E^Ea3_TB&cHXTx@^q zxh{kge5+vYjr@yVrky=-h5Qfte=WVHL0qE%iSokHFLnP|dhPd+i(a{|K|Y%8P@(KO zhZK=Mfq1DmS=~82TdMB?qSkvt(@_VAB&g!?;;Lo1q~(k6PbqRJ+|2uo5ou77yi#S| z0x{lLDlN#l(a3vO^$UrfYci>%&TyF(zTCZ4!1#E}USUQukYR}zPj90iO9yO|LTM| zB?AMu3;y$GkpgAUP}FIb8YcPgCxMF^n^VIY2tdjJiXUY`+hs;xtW1P-Yci?`}S^vRKymh0w z{Zpb0Zh5VhE=Y3dHBzv46GOZ99>IZ%U3=o4fWG`3vd{p42ZS65SLG?>JHB=zFr9Zn zWO6hSxM58aE9~8L7S!KmOW+9Xq{`k-=UG^*k)!$d;~<9Jy}ZSEoWS}*gO%rBNKDrm zn9lQY(XyK}u}MX?#Eay9*46oG{;Nk3n-+5!0qks}C{PHiEt3wFz7`xRCpVBSvRu<- zoYY?!lglIed%xowvSYev7qa;55O{LrFd}HHc&Nw9dH~L>oTbw?!USx#W%vNZtYL zeYe3F{dRlaJ*27LPx8)G>;^)D7l~qaWsHoHQtsdR{F`4d7<#>xE1p*0x?(2L+CGdy z_{52&A~e#*^SZ;Y$I?l@*R*@0Yt52hRrI^_eb3&uJY(dnnIX2%WG3YoyK??i3_d6+ zmr~wDUYHAhqVCSNMnhc!z!?NdkVzvg$&L%1EOleO?mZr~_Y) z58FsN?5M44OYzf=qHS^OWlGuTs>BcM)tw_##byUhaSv4`#Si#w$8t75-t7hE`zYlR znpw}z6BQPA{?3eF}O|Kd1wf4Y)jqide=6_2n&E;D< zwW{iZT5wV{nOSUa z8Duy#4`}>tPw2#Gz9(~BYIKx;Pvd<5I7qTu?mVVOH zy4|Llgh35`u-i{oSDB{TVnr^JVN~pZ2oY!1?MSA4sE!P7wPy@Bl(QPl8`A&}4L$cr z-jBVv&sNwl&XK>OZo(Ud|2maaT4P@2^g&h$W8|J23DR7!(dl;v=jJIa_=(;CGL#dl zPdS1#e;|4D*Q`NL3UEfWe~$jLT>v|OkM zKOeisC$21QUV4@x2eFA;yhkWa8bUjZ%!v_|q*cyQ(-tZSq7P5|lo(oA+6=aasJmJG zVdaR$zez|;D&U@9Sq?>SA-@z=lxmaDuko)eN9)o&>0&8S2+DJ)$yYrn2H*=6yf6eo ziRxhVt3GWd_u%!hK%8Ekq7p~upmYMO4nR3vbRd$`avQ8(6F!=#KhK)mD#k2p9PvR) ztA(4o$Ia70yl4nL-5%Q|572&0TNa=(0yd`jRMq74%Guz1p zT;1=UchgI*nBG`)A)q3@Q&sD(RnG$G^hbU3iyr%@?ssD$wMZnGe1MiJyJR!KI)^33 zq(Ae!V*^MZ>8$LsJmuE47MC>=wm}Cc8cNkcY8DxfV<5ivT!$Kku&DJ%WQ*qCG{>Tq z5AANQe!}`WkJjlpDdIv;G^qM3%}GJ|t-Zda2Z)k)S%M<}QH$lSURjBX`xpeNm_?*< zgq56nT1x)#fXdSd<(;=k|8JTDJ3Ox}^ukBN7t~@$C4|eSmxT7vw&Y&bqd&L<*%@Id zYH<}zPY=u3M6ro&Jx`>TC0(I{0+XL|&#VrQ~=`!A0)D@Pv(qv?gtWX!FXuPe_g^0w$v~lMf_axAZDM zu9=`tC$#=2CMeLKy~p>V|JG)j_|X#8JivxYf>m~_>p`F$-#K@y1KuY?*(9> z8i6nA9~TLx?_fF}&CaoqblB#wd)44zEIklYa4{ITSpNXq*?!+pitSM@jLknX|$S9pnqG+}eZEUr$&gC)MCZPiNQxXGG^AyPO{k;D_}pFud3E6vl$$geXKrlLVW3v+o0xPXQKR?|`5CnGxo;Xyp1>0* zvk@#GYT8GL8_)vsEkS1?1+r?#R&pK%V(|b}bs0jmB`zys1)lT8t}tblq5;@S@ZA zbmmT1h2Et4EbM5GrMBiyX&WE*YAv74zvwN)t zP^OBC0Fu0~@GX@1SyeC0Gnl$2f9<{q`0;>(LBvoW!6Th43J>}Fg!$R!Nqc9cl>%$f z6|mRPg%bFso|JK_kE%bT%73Bdsg$NI*0`LN)q0~Vw+2h>LR)1eYr?gpPZvT=;-yh^ zY+tDNR>*FkuI?DCHdtlmQB*eDq^GF3>$qTF{rBnU_#9}K%$JBL7X5#xN38#c0dV?7 z2FLv9>h1(rhj=M#q~AO*QSOh?{U*U8n8{e(g;_5mEkdnCa;%L7@j|?Mc=YL;#6L`! zknp`_j5ARt%jAo{8=m6)KC!(${3t-L9C9E+OY1QSH-dqLLKqQt(|q{u!bjV{SHO0F z@#Uxo8SH*g47db6IeWjI=h)~ru3F=!@8A7*yN~$4}YzHZ& zxh+eUnw4kX*Xz{3sMD7zVk4&_&HNi=E&h+Jv_vIpdP$&GBT|D5Dul_|1wnkw&pL-O z(p#0~2J-&)>*rV&JoA(pIsLKk6nQ91qr&(_2AGqRR5zv%iIeA%{^s5~?K>Avw92>N z)~9L@1FqE%7CDSfN)(SE`^GI&eS8dTQ{jm;&avR%7z)McsMdU4akI3F^om_Xg|58E zpi3(o==Ri>)1d9qcfjtP%#Z=!)Dn$p21rRbmCTkbyEcwwjIuQY?`Xjp)2+mATB?v@|iMgDGJ%M)ec zDO*}IiEmk|#7W)%LK$n4fMp<;5@iE_6;-j6q+$iIf6EP`WQDCkn@GZ>d0#ei5C_|| z+O@BLfUENDb&s|xa^7@rs5;`=g+WUF&M`{lxDBph??xMKHXg_coqq1Mk9f8!NM)ho z#K}QBZ`J0AG#7KXu|>?=+K;O5TVtH1A3;>KVDbZ1M>|r+5n2tWY9`!(aHJS95k-!M zl~xEB0gWDGns0J2aT&%e#qDds4<7>q$X>yac{c~Q0%a6JjFtRAEbxMnGgx=W)Js#B z)0sx>A)`V#B-{|L_AN~W?bw{?@8X9)CnJwLG<%qD1DB2M8zTquqF7Z2Gn0*(AE^w3 zd>eLvnuTw39velxq@zxG$`3ck2SVkFX;W>LjR7LcN*R%4-s~Y}S zlh+7oO4X%u)naIGl$-ei_E!O%D9u{ z*Ht0reY@AyZBT<{msq<+v+MXCAW-30{2tj<2C>~}orS22u%3OG@en{nu zRp=4jtpWinS6H*u2q)_bsNTC=3|>7<9#x;|GYYT};<`ADpq^xlll_51G777s2(+HU zOCg3+7AjhTWm(=>VLTSkn7UYJYZ?QHCG4eKcvNG=ig8pX2wB74&TE}Z zcpeS?+q}PcS*FOL25bF7bs>vIHaX%yRdA&dYoyd^ zeQ8NQoMbZ)_5=_?ae~&G3Ajd2!09>YqjU%N9zY4*$*Vk}QIS(8zis{qp1MN?Vf-C5 z1KyLL2_}Ip7-8hm(68cv~eeUoO7}{AKu82HsK=KH3}&3z)2nW1N;H=H{Zlvh5-z z1Qm1`2A6qmAmHf1uxEFG4C7YdNz1YO*V--%>y%{la{$GrQBJ zxxkv^5>@gHx{AiAVjlt@u0>+tFrMYPk+ ?n`jn^hX6%lfXhArr1<34ee)4T3_bh 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 Installation

    The source files for trajectory scanning are in the synApps -motor module +motor module , in the motorApp/ tree.

    @@ -1267,7 +1267,7 @@ 

    .

    -

    +

    trajectoryPlot.adl is used to plot the requested trajectory in @@ -1276,14 +1276,14 @@

    (MnError).

    -

    +

    trajectoryScanDebug.adl is used to display detailed information, useful for debugging.

    -

    +

    MEDM displays for the MAXv and Ensemble are very similar, but also include @@ -1554,10 +1554,10 @@

    These are the resulting plots:

    -

    +

    -

    +

     

    diff --git a/documentation/IDL_trajectory_actual.png b/docs/trajectoryScan_files/IDL_trajectory_actual.png similarity index 100% rename from documentation/IDL_trajectory_actual.png rename to docs/trajectoryScan_files/IDL_trajectory_actual.png diff --git a/documentation/IDL_trajectory_errors.png b/docs/trajectoryScan_files/IDL_trajectory_errors.png similarity index 100% rename from documentation/IDL_trajectory_errors.png rename to docs/trajectoryScan_files/IDL_trajectory_errors.png diff --git a/documentation/trajectoryPlot1.png b/docs/trajectoryScan_files/trajectoryPlot1.png similarity index 100% rename from documentation/trajectoryPlot1.png rename to docs/trajectoryScan_files/trajectoryPlot1.png diff --git a/documentation/trajectoryPlot2.png b/docs/trajectoryScan_files/trajectoryPlot2.png similarity index 100% rename from documentation/trajectoryPlot2.png rename to docs/trajectoryScan_files/trajectoryPlot2.png diff --git a/documentation/trajectoryScan.png b/docs/trajectoryScan_files/trajectoryScan.png similarity index 100% rename from documentation/trajectoryScan.png rename to docs/trajectoryScan_files/trajectoryScan.png diff --git a/documentation/trajectoryScanDebug.png b/docs/trajectoryScan_files/trajectoryScanDebug.png similarity index 100% rename from documentation/trajectoryScanDebug.png rename to docs/trajectoryScan_files/trajectoryScanDebug.png diff --git a/documentation/MotorRec.ppt b/documentation/MotorRec.ppt deleted file mode 100644 index 681412cf9b6ecc3e547f912f1150bc4a3c0735af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 730624 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%0A6I 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 E9v2?PTx=`1 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�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 JDyc`<{|BmmzNG*F diff --git a/iocBoot/iocNewFocus874x/Makefile b/iocBoot/iocNewFocus874x/Makefile new file mode 100644 index 0000000..6512ead --- /dev/null +++ b/iocBoot/iocNewFocus874x/Makefile @@ -0,0 +1,6 @@ +TOP = ../.. +include $(TOP)/configure/CONFIG +ARCH = linux-x86_64 +TARGETS += envPaths +include $(TOP)/configure/RULES.ioc + diff --git a/iocBoot/iocNewFocus874x/newfocus8742.asyn.motor.substitutions b/iocBoot/iocNewFocus874x/newfocus8742.asyn.motor.substitutions new file mode 100644 index 0000000..cbc5b8a --- /dev/null +++ b/iocBoot/iocNewFocus874x/newfocus8742.asyn.motor.substitutions @@ -0,0 +1,8 @@ +file "$(MOTOR)/db/basic_asyn_motor.db" +{ +pattern +{P, N, M, DTYP, PORT, ADDR, C, S, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT} +{IOC:, 1, "X", "asynMotor", M0, 1, 0, 0, "X", counts, Pos, 100, 25, 1, 0, 0, 50, 1, 0, 0, 0, ""} +{IOC:, 2, "Y", "asynMotor", M0, 2, 0, 0, "Y", counts, Pos, 100, 25, 1, 0, 0, 50, 1, 0, 0, 0, ""} +} + diff --git a/iocBoot/iocNewFocus874x/newfocus8742.asyn.st.cmd.linux-x86 b/iocBoot/iocNewFocus874x/newfocus8742.asyn.st.cmd.linux-x86 new file mode 100644 index 0000000..5aebfe7 --- /dev/null +++ b/iocBoot/iocNewFocus874x/newfocus8742.asyn.st.cmd.linux-x86 @@ -0,0 +1,67 @@ +#!../../bin/linux-x86_64/picoctl + +## You may have to change picoctl to something else +## everywhere it appears in this file + +< envPaths + +epicsEnvSet("EPICS_CA_AUTO_ADDR_LIST", "NO") +epicsEnvSet("EPICS_CA_ADDR_LIST", "10.28.0.255") + +epicsEnvSet("Sys", "Sys") +epicsEnvSet("Port", "P0") +epicsEnvSet("ControllerPort", "M0") +epicsEnvSet("MC", "MC:10") +epicsEnvSet("CT", "CT") +epicsEnvSet("IOC_PREFIX", "$(CT){IOC:MC10}") +epicsEnvSet("MC_PREFIX", "$(CT){$(MC)}") + +cd ${TOP} + +## Register all support components +dbLoadDatabase "dbd/picoctl.dbd" +picoctl_registerRecordDeviceDriver pdbbase + +# Setup IP port for 8742 +drvAsynIPPortConfigure("$(Port)", "10.28.2.111:23") +asynOctetSetInputEos("$(Port)",0,"\r\n") +asynOctetSetOutputEos("$(Port)",0,"\r") + +#db asyn debug traces +asynSetTraceMask("$(Port)",-1,0x1) +asynSetTraceIOMask("$(Port)",-1,0x1) + + +# New Focus Picomotor Network Controller (model 87xx) configuration parameters: +# (1) IP asyn port name (string) +# (2) Controller asyn port name (string) +# (3) Number of axes +# (4) Moving poll period (ms) +# (5) Idle poll period (ms) +nf874xCreateController("$(ControllerPort)", "$(Port)", 4, 200, 1000) + +## Load record instances +dbLoadTemplate("iocBoot/iocNewFocus874x/newfocus8742.asyn.motor.substitutions") + +dbLoadRecords("${ASYN}/db/asynRecord.db", "P=$(MC_PREFIX),R=Asyn,PORT=$(Port),ADDR=,OMAX=80,IMAX=80") + +## autosave/restore machinery +save_restoreSet_Debug(0) +save_restoreSet_IncompleteSetsOk(1) +save_restoreSet_DatedBackupFiles(1) + +set_savefile_path("${TOP}/as","/save") +set_requestfile_path("${TOP}/as","/req") + +set_pass0_restoreFile("info_positions.sav") +set_pass0_restoreFile("info_settings.sav") +set_pass1_restoreFile("info_settings.sav") + +iocInit() + +## more autosave/restore machinery +cd ${TOP}/as/req +makeAutosaveFiles() +create_monitor_set("info_positions.req", 5 , "") +create_monitor_set("info_settings.req", 15 , "") + diff --git a/iocBoot/iocNoAsyn/st.cmd.Vx b/iocBoot/iocNoAsyn/st.cmd.Vx index da5a32d..ca05ba6 100644 --- a/iocBoot/iocNoAsyn/st.cmd.Vx +++ b/iocBoot/iocNoAsyn/st.cmd.Vx @@ -42,7 +42,7 @@ dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=IOC:") # (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 (1 - 6). +# (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) @@ -63,7 +63,7 @@ dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=IOC:") #!str = malloc(200); #!strcpy str, "AA; LMH,H,H,H,H,H,H,H;" -#!strcat str, "AX LH PSO; AY LH PSO; AZ LL PSO; AT LL PSO; AU LL PSO; AV LL PSO; AR LL PSO; AS LL PSO;" +#!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) diff --git a/iocBoot/iocWithAsyn/motor.cmd.ANF2 b/iocBoot/iocWithAsyn/motor.cmd.ANF2 new file mode 100644 index 0000000..f501ae2 --- /dev/null +++ b/iocBoot/iocWithAsyn/motor.cmd.ANF2 @@ -0,0 +1,107 @@ +# ANF2 motors command file example (run in iocsh) +# +### Note: Modbus support (the EPICS modbus module) is required to be included in the +### EPICS application where the ANF2 support will be loaded. This file is an +### example of how to load the ANF2 support, in an ioc that is built with the +### EPICS modbus module. + +epicsEnvSet("PORT1", "ANF2_C1") +epicsEnvSet("PORT2", "ANF2_C2") + +# drvAsynIPPortConfigure("portName", "hostInfo", priority, noAutoConnect, noProcessEos); +drvAsynIPPortConfigure("$(PORT1)_IP","192.168.0.50:502",0,0,1) +drvAsynIPPortConfigure("$(PORT2)_IP","192.168.0.51:502",0,0,1) + +# modbusInterposeConfig("portName", linkType, timeoutMsec, writeDelayMsec) +modbusInterposeConfig("$(PORT1)_IP",0,2000,0) +modbusInterposeConfig("$(PORT2)_IP",0,2000,0) + +# NOTE: modbusLength = 10 * number of axes +# drvModbusAsynConfigure("portName", "tcpPortName", slaveAddress, modbusFunction, +# modbusStartAddress, modbusLength, dataType, pollMsec, "plcType") +drvModbusAsynConfigure("$(PORT1)_In", "$(PORT1)_IP", 0, 4, 0, 120, 0, 100, "ANF2_stepper") +drvModbusAsynConfigure("$(PORT2)_In", "$(PORT2)_IP", 0, 4, 0, 60, 0, 100, "ANF2_stepper") + +# NOTE: modbusLength = 10 * number of axes +# drvModbusAsynConfigure("portName", "tcpPortName", slaveAddress, modbusFunction, +# modbusStartAddress, modbusLength, dataType, pollMsec, "plcType") +drvModbusAsynConfigure("$(PORT1)_Out", "$(PORT1)_IP", 0, 16, 1024, 120, 6, 1, "ANF2_stepper") +drvModbusAsynConfigure("$(PORT2)_Out", "$(PORT2)_IP", 0, 16, 1024, 60, 6, 1, "ANF2_stepper") + +# Asyn traces for debugging +#!asynSetTraceIOMask "$(PORT1)_In",0,4 +#!asynSetTraceMask "$(PORT1)_In",0,9 +#!asynSetTraceIOMask "$(PORT1)_Out",0,4 +#!asynSetTraceMask "$(PORT1)_Out",0,9 +#!asynSetTraceInfoMask "$(PORT1)_Out",0,15 + +# Asyn records for debugging +#!dbLoadRecords("$(ASYN)/db/asynRecord.db","P=IOC:,R=asyn:c1ip,PORT=$(PORT1)_IP,ADDR=0,OMAX=256,IMAX=256") +#!dbLoadRecords("$(ASYN)/db/asynRecord.db","P=IOC:,R=asyn:c1in,PORT=$(PORT1)_In,ADDR=0,OMAX=256,IMAX=256") +#!dbLoadRecords("$(ASYN)/db/asynRecord.db","P=IOC:,R=asyn:c1out,PORT=$(PORT1)_Out,ADDR=0,OMAX=256,IMAX=256") +#!dbLoadRecords("$(ASYN)/db/asynRecord.db","P=IOC:,R=asyn:c1,PORT=$(PORT1),ADDR=0,OMAX=256,IMAX=256") + +# Load the motor records +dbLoadTemplate("templates/motor.substitutions.ANF2") + +# AMCI ANF2 stepper controller driver support +# +# ANF2CreateController( +# portName, The name of the asyn port that will be created by this driver +# ANF2InPortName, The name of the In drvAsynIPPPort to read from the ANF2 controller +# ANF2OutPortName, The name of the Out drvAsynIPPPort to write to the ANF2 controller +# numAxes) The number of axes in the stack (max=12) +# +# ANF2CreateAxis( +# ANF2Name, The controller's asyn port +# axis, The axis to be configured (zero-based numbering) +# hexConfig, The desired hex configuration (see manual & AMCI Net Configurator for details) +# baseSpeed, The base speed (steps/second; min=1, max=1,000,000) +# homingTimeout) The homing timeout (integer number of seconds; min=0, max=300) +# +# Note: The base speed can't be changed using the VBAS field of the motor record, but the driver +# does correct the acceleration sent by the motor record to give the desired acceleration time. + +# Controller 1 (One ANF2E, Five ANF2's) +ANF2CreateController("$(PORT1)", "$(PORT1)_In", "$(PORT1)_Out", 12) +# Axes for Controller 1 +ANF2CreateAxis("$(PORT1)", 0, "0x86280000", 100, 0) +ANF2CreateAxis("$(PORT1)", 1, "0x86000000", 100, 0) +ANF2CreateAxis("$(PORT1)", 2, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT1)", 3, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT1)", 4, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT1)", 5, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT1)", 6, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT1)", 7, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT1)", 8, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT1)", 9, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT1)", 10, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT1)", 11, "0x84000000", 100, 0) + +# Controller 2 (One ANF1E, Five ANF1's) +ANF2CreateController("$(PORT2)", "$(PORT2)_In", "$(PORT2)_Out", 6) +# Axes for Controller 2 +ANF2CreateAxis("$(PORT2)", 0, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT2)", 1, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT2)", 2, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT2)", 3, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT2)", 4, "0x84000000", 100, 0) +ANF2CreateAxis("$(PORT2)", 5, "0x84000000", 100, 0) + +# NOTE: the poller needs to be started after iocInit + + + +########## +# iocInit +########## + + + +# ANF2StartPoller( +# portName, The controller's asyn port +# movingPollPeriod, The time in ms between polls when any axis is moving +# idlePollPeriod) The time in ms between polls when no axis is moving +# +ANF2StartPoller("$(PORT1)", 200, 1000) +ANF2StartPoller("$(PORT2)", 200, 1000) diff --git a/iocBoot/iocWithAsyn/motor.substitutions.ANF2 b/iocBoot/iocWithAsyn/motor.substitutions.ANF2 new file mode 100644 index 0000000..a29a9eb --- /dev/null +++ b/iocBoot/iocWithAsyn/motor.substitutions.ANF2 @@ -0,0 +1,54 @@ +file "$(MOTOR)/motorApp/Db/asyn_motor.db" +{ +pattern +{P, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT, RTRY} + +{IOC:, "m1", "asynMotor", "ANF2_C1", 0, "ANF2 C1 M1", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m2", "asynMotor", "ANF2_C1", 1, "ANF2 C1 M2", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m3", "asynMotor", "ANF2_C1", 2, "ANF2 C1 M3", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m4", "asynMotor", "ANF2_C1", 3, "ANF2 C1 M4", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m5", "asynMotor", "ANF2_C1", 4, "ANF2 C1 M5", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m6", "asynMotor", "ANF2_C1", 5, "ANF2 C1 M6", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m7", "asynMotor", "ANF2_C1", 6, "ANF2 C1 M7", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m8", "asynMotor", "ANF2_C1", 7, "ANF2 C1 M8", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m9", "asynMotor", "ANF2_C1", 8, "ANF2 C1 M9", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m10", "asynMotor", "ANF2_C1", 9, "ANF2 C1 M10", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m11", "asynMotor", "ANF2_C1", 10, "ANF2 C1 M11", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m12", "asynMotor", "ANF2_C1", 11, "ANF2 C1 M12", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} + +{IOC:, "m13", "asynMotor", "ANF2_C2", 0, "ANF2 C2 M1", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m14", "asynMotor", "ANF2_C2", 1, "ANF2 C2 M2", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m15", "asynMotor", "ANF2_C2", 2, "ANF2 C2 M3", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m16", "asynMotor", "ANF2_C2", 3, "ANF2 C2 M4", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m17", "asynMotor", "ANF2_C2", 4, "ANF2 C2 M5", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, "m18", "asynMotor", "ANF2_C2", 5, "ANF2 C2 M6", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} + +} + +file "$(MOTOR)/motorApp/Db/ANF2Aux.template" +{ +pattern +{P, R, PORT, ADDR} + +{IOC:, m1:, "ANF2_C1", 0} +{IOC:, m2:, "ANF2_C1", 1} +{IOC:, m3:, "ANF2_C1", 2} +{IOC:, m4:, "ANF2_C1", 3} +{IOC:, m5:, "ANF2_C1", 4} +{IOC:, m6:, "ANF2_C1", 5} +{IOC:, m7:, "ANF2_C1", 6} +{IOC:, m8:, "ANF2_C1", 7} +{IOC:, m9:, "ANF2_C1", 8} +{IOC:, m10:, "ANF2_C1", 9} +{IOC:, m11:, "ANF2_C1", 10} +{IOC:, m12:, "ANF2_C1", 11} + +{IOC:, m13:, "ANF2_C2", 0} +{IOC:, m14:, "ANF2_C2", 1} +{IOC:, m15:, "ANF2_C2", 2} +{IOC:, m16:, "ANF2_C2", 3} +{IOC:, m17:, "ANF2_C2", 4} +{IOC:, m18:, "ANF2_C2", 5} + +} + diff --git a/iocBoot/iocWithAsyn/motor.substitutions.ANG1 b/iocBoot/iocWithAsyn/motor.substitutions.ANG1 new file mode 100644 index 0000000..069accf --- /dev/null +++ b/iocBoot/iocWithAsyn/motor.substitutions.ANG1 @@ -0,0 +1,17 @@ +file "$(MOTOR)/motorApp/Db/basic_asyn_motor.db" +{ +pattern +{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT, RTRY} + +{IOC:, 1, "m$(N)", "asynMotor", "ANG1_1_1", 0, "AMCI ANG1 1", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +{IOC:, 2, "m$(N)", "asynMotor", "ANG1_1_2", 0, "AMCI ANG1 2", steps, Pos, 100, 0, .2, 0, 50, .2, 1, 5, 1e9, -1e9, ""} +} + +file "$(MOTOR)/motorApp/Db/ANG1Aux.template" +{ +pattern +{P, R, PORT, ADDR} +{IOC:, m1:, ANG1_1_1, 0} +{IOC:, m2:, ANG1_1_2, 0} +} + diff --git a/iocBoot/iocWithAsyn/motor.substitutions.CONEX-PP b/iocBoot/iocWithAsyn/motor.substitutions.CONEX-PP new file mode 100644 index 0000000..78df4c2 --- /dev/null +++ b/iocBoot/iocWithAsyn/motor.substitutions.CONEX-PP @@ -0,0 +1,9 @@ +file "$(TOP)/db/basic_asyn_motor.db" +{ +pattern +{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT} +# Newport NSA12 stage, 6.35 microns/full step, 128 micro-steps/s +{IOC:, 1, "m$(N)", "asynMotor", CONEX1, 0, "X", mm, Pos, 1., 0.1, .25, 0, 1, .2, 4.9609375e-5, 4, 28, -1, ""} +{IOC:, 2, "m$(N)", "asynMotor", CONEX2, 0, "Y", mm, Pos, 1., 0.1, .25, 0, 1, .2, 4.9609375e-5, 4, 28, -1, ""} +{IOC:, 3, "m$(N)", "asynMotor", CONEX3, 0, "Z", mm, Pos, 1., 0.1, .25, 0, 1, .2, 4.9609375e-5, 4, 28, -1, ""} +} diff --git a/iocBoot/iocWithAsyn/motor.substitutions.script b/iocBoot/iocWithAsyn/motor.substitutions.script new file mode 100644 index 0000000..c2f63ea --- /dev/null +++ b/iocBoot/iocWithAsyn/motor.substitutions.script @@ -0,0 +1,15 @@ +file "$(TOP)/db/asyn_motor.db" +{ + pattern + {P, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VMAX, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT} + {IOC:, m1, "asynMotor", VMC_MOTOR, 0, "VMCMotor", mm, Pos, 15., 3., .05, .5, 0, 1.0, 2, .025, 5, 0, 0, ""} + {IOC:, m2, "asynMotor", SOFT_MOTOR, 0, "SoftMotor", mm, Pos, 15., 3., .05, .5, 0, 1.0, 2, .025, 5, 0, 0, ""} +} + +file "$(TOP)/db/ScriptMotorReload.db" +{ + pattern + {P, PORT} + {IOC:, SOFT_MOTOR} + {IOC:, VMC_MOTOR} +} diff --git a/iocBoot/iocWithAsyn/scripts/softMotor.lua b/iocBoot/iocWithAsyn/scripts/softMotor.lua new file mode 100644 index 0000000..0f6e8fd --- /dev/null +++ b/iocBoot/iocWithAsyn/scripts/softMotor.lua @@ -0,0 +1,67 @@ +IdlePollPeriod = 1.00 +MovingPollPeriod = 0.25 + +lastPos = 0 +targetPos = 0 + +function move(position, relative, minVel, maxVel, accel) + local MRES = asyn.getDoubleParam( DRIVER, AXIS, "MOTOR_REC_RESOLUTION") + + if (relative) then + local prev = asyn.getDoubleParam( DRIVER, AXIS, "MOTOR_POSITION") + targetPos = prev + (position * MRES) + else + targetPos = (position * MRES) + end + + epics.put(DRIVE_PV, targetPos) + + if (position > 0) then + asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_DIRECTION", 1) + else + asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_DIRECTION", 0) + end + + asyn.callParamCallbacks(DRIVER, AXIS) +end + + +function poll() + local MRES = asyn.getDoubleParam( DRIVER, AXIS, "MOTOR_REC_RESOLUTION") + + if (MRES == 0.0) then + return true + end + + local curr = epics.get(READBACK_PV) + + asyn.setDoubleParam( DRIVER, AXIS, "MOTOR_POSITION", curr / MRES) + + local done = 0 + local moving = 1 + + if (curr == targetPos) then + done = 1 + moving = 0 + elseif (math.abs(curr - targetPos) <= MRES and lastPos == curr) then + done = 1 + moving = 0 + end + + lastPos = curr + + asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_DONE", done) + asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_MOVING", moving) + + asyn.callParamCallbacks(DRIVER, AXIS) + + return (done ~= 1) +end + + +function stop(acceleration) + local curr = asyn.getDoubleParam( DRIVER, AXIS, "MOTOR_POSITION") + + epics.put(DRIVE_PV, curr) + targetPos = curr +end diff --git a/iocBoot/iocWithAsyn/scripts/vmc.lua b/iocBoot/iocWithAsyn/scripts/vmc.lua new file mode 100644 index 0000000..46ff05f --- /dev/null +++ b/iocBoot/iocWithAsyn/scripts/vmc.lua @@ -0,0 +1,66 @@ +IdlePollPeriod = 1.0 +MovingPollPeriod = 0.25 +ForcedFastPolls = 2 + +InTerminator = "\r\n" +OutTerminator = "\r\n" + +function sendAccelAndVelocity(minVel, maxVel, accel) + asyn.writeread( string.format( "%d BAS %f", AXIS + 1, minVel) , PORT); + asyn.writeread( string.format( "%d VEL %f", AXIS + 1, maxVel) , PORT); + asyn.writeread( string.format( "%d ACC %f", AXIS + 1, accel ) , PORT); +end + + +function move(position, relative, minVel, maxVel, accel) + sendAccelAndVelocity( minVel, maxVel, accel) + + if (relative) then + asyn.writeread( string.format( "%d MR %d", AXIS + 1, math.floor(position) ) , PORT) + else + asyn.writeread( string.format( "%d MV %d", AXIS + 1, math.floor(position) ) , PORT) + end +end + + +function moveVelocity(minVel, maxVel, accel) + sendAccelAndVelocity( minVel, maxVel, accel) + + asyn.writeread( string.format( "%d JOG %f", AXIS + 1, maxVel) , PORT); +end + + +function poll() + asyn.write( string.format( "%d POS?", AXIS + 1) , PORT) + + asyn.setDoubleParam( DRIVER, AXIS, "MOTOR_POSITION", tonumber( asyn.read(PORT) ) ) + + asyn.write( string.format( "%d ST?", AXIS + 1) , PORT) + + local status = tonumber( asyn.read(PORT) ) + + local direction = (status & 1) + local done = (status & 2) >> 1 + local limit_high = (status & 8) >> 3 + local limit_low = (status & 16) >> 4 + + asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_DIRECTION", direction) + asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_DONE", done) + asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_MOVING", done ~ 1) + asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_HIGH_LIMIT", limit_high) + asyn.setIntegerParam( DRIVER, AXIS, "MOTOR_STATUS_LOW_LIMIT", limit_low) + + asyn.callParamCallbacks(DRIVER, AXIS) + + return (done ~= 1) +end + + +function stop(acceleration) + asyn.writeread( string.format( "%d AB", AXIS + 1) , PORT); +end + + +function setPosition(position) + asyn.writeread( string.format( "%d POS %d", AXIS + 1, math.floor(position) ) , PORT); +end diff --git a/iocBoot/iocWithAsyn/st.cmd.ANG1 b/iocBoot/iocWithAsyn/st.cmd.ANG1 new file mode 100644 index 0000000..8e9a5dc --- /dev/null +++ b/iocBoot/iocWithAsyn/st.cmd.ANG1 @@ -0,0 +1,74 @@ +# ANG1 motors Command file Example +# +### Note: Modbus support (the EPICS modbus module) is required to be included in the +### EPICS application where the ANG1 support will be loaded. This file is an +### example of how to load the ANG1 support, in an ioc that is built with the +### EPICS modbus module. + + +# Use the following commands for TCP/IP +#drvAsynIPPortConfigure(const char *portName, +# const char *hostInfo, +# unsigned int priority, +# int noAutoConnect, +# int noProcessEos); +# One per controller. One controller can support up to six drivers. +drvAsynIPPortConfigure("ang1_1","164.54.53.107:502",0,0,1) +#drvAsynIPPortConfigure("ang1_2","164.54.53.23:502",0,0,1) +#drvAsynIPPortConfigure("ang1_3","164.54.xxx.xxx:502",0,0,1) + +#modbusInterposeConfig(const char *portName, +# modbusLinkType linkType, +# int timeoutMsec, +# int writeDelayMsec) +# One per controller. One controller can support up to six drivers. +modbusInterposeConfig("ang1_1",0,2000,0) +#modbusInterposeConfig("ang1_2",0,2000,0) + +# Word access at Modbus address 0 +# Access 1 words as inputs. +# Function code=3 +# default data type unsigned integer. +# drvModbusAsynConfigure("portName", "tcpPortName", slaveAddress, modbusFunction, modbusStartAddress, modbusLength, dataType, pollMsec, "plcType") +# One per axis. Note: "ANG1" is the AMCI model. "ANG1_1" is the controller. "ANG1_1_1" is the axis. +drvModbusAsynConfigure("ANG1_1_1_In_Word", "ang1_1", 0, 4, 0, 10, 0, 100, "ANG1_stepper") +drvModbusAsynConfigure("ANG1_1_2_In_Word", "ang1_1", 0, 4, 10, 10, 0, 100, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_3_In_Word", "ang1_1", 0, 3, 20, 10, 0, 100, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_4_In_Word", "ang1_1", 0, 3, 30, 10, 0, 100, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_5_In_Word", "ang1_1", 0, 3, 40, 10, 0, 100, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_6_In_Word", "ang1_1", 0, 3, 50, 10, 0, 100, "ANG1_stepper") + +# Access 1 words as outputs. +# Either function code=6 (single register) or 16 (multiple registers) can be used, but 16 +# is better because it is "atomic" when writing values longer than 16-bits. +# Default data type unsigned integer. +# drvModbusAsynConfigure("portName", "tcpPortName", slaveAddress, modbusFunction, modbusStartAddress, modbusLength, dataType, pollMsec, "plcType") +# Not sure why the outputs can't be configured for Modbus data type 4? +drvModbusAsynConfigure("ANG1_1_1_Out_Word", "ang1_1", 0, 6, 1024, 10, 0, 1, "ANG1_stepper") +drvModbusAsynConfigure("ANG1_1_2_Out_Word", "ang1_1", 0, 6, 1034, 10, 0, 1, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_3_Out_Word", "ang1_1", 0, 6, 1044, 10, 0, 1, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_4_Out_Word", "ang1_1", 0, 6, 1054, 10, 0, 1, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_5_Out_Word", "ang1_1", 0, 6, 1064, 10, 0, 1, "ANG1_stepper") +#drvModbusAsynConfigure("ANG1_1_6_Out_Word", "ang1_1", 0, 6, 1074, 10, 0, 1, "ANG1_stepper") + +# Second ANG1 controller... +#drvModbusAsynConfigure("ANG1_2_1_Out_Word_0", "ang1_2", 0, 6, 1024, 1, 0, 1, "ANG1_stepper") + +dbLoadTemplate("ANG1_motors.substitutions") + +# AMCI ANG1 stepper controller/driver support +# portName The name of the asyn port that will be created for this driver +# ANG1InPortName The name of the In drvAsynIPPPort that was created previously to connect to the ANG1 controller +# ANG1OutPortName The name of the Out drvAsynIPPPort that was created previously to connect to the ANG1 controller +# numAxes The number of axes that this controller supports +# movingPollPeriod The time in ms between polls when any axis is moving +# idlePollPeriod The time in ms between polls when no axis is moving +# +# One per axis. Note: "ANG1" is the AMCI model. "ANG1_1" is the controller. "ANG1_1_1" is the axis. +# Also, ANG1_1_1 is the port name needed for motor.substitutions. +ANG1CreateController(ANG1_1_1, ANG1_1_1_In_Word, ANG1_1_1_Out_Word, 1, 100, 0) +ANG1CreateController(ANG1_1_2, ANG1_1_2_In_Word, ANG1_1_2_Out_Word, 1, 100, 0) +#ANG1CreateController(ANG1_1, ANG1_1_3_In_Word, ANG1_1_3_Out_Word, 1, 100, 0) +#ANG1CreateController(ANG1_1, ANG1_1_4_In_Word, ANG1_1_4_Out_Word, 1, 100, 0) +#ANG1CreateController(ANG1_1, ANG1_1_5_In_Word, ANG1_1_5_Out_Word, 1, 100, 0) +#ANG1CreateController(ANG1_1, ANG1_1_6_In_Word, ANG1_1_6_Out_Word, 1, 100, 0) diff --git a/iocBoot/iocWithAsyn/st.cmd.CONEX-PP b/iocBoot/iocWithAsyn/st.cmd.CONEX-PP new file mode 100644 index 0000000..4447b28 --- /dev/null +++ b/iocBoot/iocWithAsyn/st.cmd.CONEX-PP @@ -0,0 +1,45 @@ +#errlogInit(5000) +< envPaths +# Tell EPICS all about the record types, device-support modules, drivers, +# etc. +dbLoadDatabase("../../dbd/WithAsyn.dbd") +WithAsyn_registerRecordDeviceDriver(pdbbase) + +### Motors +dbLoadTemplate "motor.substitutions.CONEX-PP" + +# For Windows +drvAsynSerialPortConfigure("serial1", "COM8", 0, 0, 0) +# For Linux +#drvAsynSerialPortConfigure("serial1", "/dev/ttyUSB0", 0, 0, 0) +asynOctetSetInputEos("serial1",0,"\r\n") +asynOctetSetOutputEos("serial1",0,"\r\n") +asynSetOption("serial1",0,"baud","115200") +asynSetOption("serial1",0,"bits","8") +asynSetOption("serial1",0,"stop","1") +asynSetOption("serial1",0,"parity","none") +asynSetOption("serial1",0,"clocal","Y") +asynSetOption("serial1",0,"crtscts","N") + +asynSetTraceIOMask("serial1", 0, 2) +#asynSetTraceMask("serial1", 0, 9) + +# Load asyn record +dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=IOC:,R=serial1,PORT=serial1, ADDR=0,OMAX=256,IMAX=256") + +# AG_CONEXCreateController(asyn port, serial port, controllerID, +# active poll period (ms), idle poll period (ms)) +AG_CONEXCreateController("CONEX1", "serial1", 1, 50, 500) +asynSetTraceIOMask("CONEX1", 0, 2) +#asynSetTraceMask("CONEX1", 0, 255) +AG_CONEXCreateController("CONEX2", "serial1", 2, 50, 500) +asynSetTraceIOMask("CONEX2", 0, 2) +#asynSetTraceMask("CONEX2", 0, 255) +AG_CONEXCreateController("CONEX3", "serial1", 3, 50, 500) +asynSetTraceIOMask("CONEX3", 0, 2) +#asynSetTraceMask("CONEX3", 0, 255) + +iocInit + +dbpf IOC:m1.RTRY 0 +dbpf IOC:m1.NTM 0 diff --git a/iocBoot/iocWithAsyn/st.cmd.script b/iocBoot/iocWithAsyn/st.cmd.script new file mode 100644 index 0000000..a113cde --- /dev/null +++ b/iocBoot/iocWithAsyn/st.cmd.script @@ -0,0 +1,18 @@ +< envPaths + +dbLoadDatabase("$(TOP)/dbd/WithAsyn.dbd") +WithAsyn_registerRecordDeviceDriver(pdbbase) + +epicsEnvSet("LUA_SCRIPT_PATH", "./scripts") + +# Connect to virtual motor controller server +drvAsynIPPortConfigure("VMC","127.0.0.1:31337", 0, 0, 0) + +#ScriptControllerConfig( "PORT_NAME", num_axes, "lua_script", "PARAMS=") +ScriptControllerConfig("VMC_MOTOR", 1, "vmc.lua", "PORT=VMC") + +ScriptControllerConfig("SOFT_MOTOR", 1, "softMotor.lua", "DRIVE_PV='IOC:m1.VAL', READBACK_PV='IOC:m1.RBV'") + +dbLoadTemplate("motor.substitutions.script") + +iocInit diff --git a/iocBoot/iocWithAsyn/st.cmd.xps6 b/iocBoot/iocWithAsyn/st.cmd.xps6 new file mode 100755 index 0000000..cf7b7a5 --- /dev/null +++ b/iocBoot/iocWithAsyn/st.cmd.xps6 @@ -0,0 +1,46 @@ +#errlogInit(5000) +< envPaths +# Tell EPICS all about the record types, device-support modules, drivers, +# etc. in this build from CARS +dbLoadDatabase("../../dbd/WithAsyn.dbd") +WithAsyn_registerRecordDeviceDriver(pdbbase) + +### Motors +dbLoadTemplate "motor.substitutions.xps6" + +dbLoadTemplate "XPSAux.substitutions" + +# asyn port, IP address, IP port, number of axes, +# active poll period (ms), idle poll period (ms), +# enable set position, set position settling time (ms) +XPSCreateController("XPS1", "164.54.164.24", 5001, 4, 10, 500, 0, 500) +asynSetTraceIOMask("XPS1", 0, 2) +#asynSetTraceMask("XPS1", 0, 255) + +# asynPort, IP address, IP port, poll period (ms) +XPSAuxConfig("XPS_AUX1", "164.54.164.24", 5001, 50) +#asynSetTraceIOMask("XPS_AUX1", 0, 2) +#asynSetTraceMask("XPS_AUX1", 0, 255) + +# XPS asyn port, axis, groupName.positionerName, stepSize +XPSCreateAxis("XPS1",0,"Group1.Pos", "10000") +XPSCreateAxis("XPS1",1,"Group2.Pos", "10000") +XPSCreateAxis("XPS1",2,"Group3.Pos", "20000") +XPSCreateAxis("XPS1",3,"Group4.Pos", "2000") + +# XPS asyn port, max points, FTP username, FTP password +# Note: this must be done after configuring axes +XPSCreateProfile("XPS1", 2000, "Administrator", "Administrator") + +iocInit + +# This IOC does not use save/restore, so set values of some PVs +dbpf("IOC:m1.RTRY", "0") +dbpf("IOC:m1.TWV", "0.1") +dbpf("IOC:m2.RTRY", "0") +dbpf("IOC:m2.TWV", "0.1") +dbpf("IOC:m3.RTRY", "0") +dbpf("IOC:m3.TWV", "0.1") +dbpf("IOC:m4.RTRY", "0") +dbpf("IOC:m4.TWV", "0.1") + diff --git a/iocsh/ACS_MCB4B.iocsh b/iocsh/ACS_MCB4B.iocsh new file mode 100644 index 0000000..cc24ccc --- /dev/null +++ b/iocsh/ACS_MCB4B.iocsh @@ -0,0 +1,25 @@ +# ### ACS_MCB4B.iocsh ### + +#- ################################################### +#- PORT - Serial port for communications +#- INSTANCE - Name of asyn port to create +#- +#- NUM_AXES - Optional: Number of axes to create for this controller +#- Default: 1 +#- +#- MOVING_POLL - Optional: Moving poll rate (ms) +#- Default: POLL_RATE +#- +#- IDLE_POLL - Optional: Idle poll rate (ms) +#- Default: POLL_RATE +#- +#- POLL_RATE - Optional: Poll rate (ms) +#- Default: 100 +#- ################################################### + +# ACS MCB-4B serial connection settings +iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=19200, BITS=8, STOP=1, PARITY=none") +asynOctetSetInputEos( "$(PORT)", -1, "\r") +asynOctetSetOutputEos("$(PORT)", -1, "\r") + +MCB4BCreateController("$(INSTANCE)", "$(PORT)", $(NUM_AXES=1), $(MOVING_POLL=$(POLL_RATE=100)), $(IDLE_POLL=$(POLL_RATE=100))) diff --git a/iocsh/EXAMPLE_motorSim.substitutions b/iocsh/EXAMPLE_motorSim.substitutions new file mode 100644 index 0000000..4ce6874 --- /dev/null +++ b/iocsh/EXAMPLE_motorSim.substitutions @@ -0,0 +1,7 @@ +file "$(MOTOR)/db/asyn_motor.db" +{ +pattern +{N, M, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, INIT} +{1, "m$(N)", 0, "motor $(N)", degrees, Pos, 1, .1, .2, 0, 1, .2, 0.01, 5, ""} +#{2, "m$(N)", 1, "motor $(N)", degrees, Pos, 1, .1, .2, 0, 1, .2, 0.01, 5, ""} +} diff --git a/iocsh/McClennan_PM304.iocsh b/iocsh/McClennan_PM304.iocsh new file mode 100644 index 0000000..ee98bd8 --- /dev/null +++ b/iocsh/McClennan_PM304.iocsh @@ -0,0 +1,31 @@ +# ### McClennan_PM304.iocsh ### + +#- ################################################### +#- PORT - Serial port for communications +#- CONTROLLER - Optional: Which controller is being configured +#- Default: 0 +#- +#- NUM_AXES - Optional: Number of axes on this controller +#- Default: 1 +#- +#- MAX_CONTROLLERS - Optional: Max number of controllers that will be configured +#- Default: 1 +#- +#- POLL_RATE - Optional: Controller poll rate in hertz +#- Default: 10 +#- ################################################### + +#- McClennan PM304 driver setup parameters: +#- (1) maximum number of controllers in system +#- (2) motor task polling rate (min=1Hz, max=60Hz) +$(PM304_INIT_COMPLETE="") PM304Setup($(MAX_CONTROLLERS=1), $(POLL_RATE=10)) + +#- Insert serial port configuration settings here + +#- McClennan PM304 driver configuration parameters: +#- (1) controller being configured +#- (2) MPF serial server name (string) +#- (3) Number of axes on this controller +PM304Config($(CONTROLLER=0), "$(PORT)", $(NUM_AXES=1)) + +epicsEnvSet("PM304_INIT_COMPLETE", "#") diff --git a/iocsh/Newfocus_PMNC87xx.iocsh b/iocsh/Newfocus_PMNC87xx.iocsh new file mode 100644 index 0000000..f05693f --- /dev/null +++ b/iocsh/Newfocus_PMNC87xx.iocsh @@ -0,0 +1,37 @@ +# ### Newfocus_PMNC87xx.iocsh ### + +#- ################################################### +#- PORT - Serial port for communications +#- CONTROLLER - Optional: Which controller is being configured +#- Default: 0 +#- +#- NUM_AXES - Optional: Number of axes on this controller +#- Default: 1 +#- +#- MAX_CONTROLLERS - Optional: Max number of controllers that will be configured +#- Default: 1 +#- +#- MAX_DRIVES - Optional: Max number of drives per controller +#- Default: 1 +#- +#- POLL_RATE - Optional: Controller poll rate in hertz +#- Default: 10 +#- ################################################### + +#- NewFocus Picomotor driver setup parameters: +#- (1) maximum number of controllers in system +#- (2) maximum drives per controller +#- (3) motor task polling rate (min=1Hz, max=60Hz) +$(PMNC87XX_INIT_COMPLETE="") PMNC87xxSetup($(MAX_CONTROLLERS=1), $(MAX_DRIVES=1), $(POLL_RATE=10)) + +#- Serial port configuration +iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=19200, BITS=8, STOP=1, PARITY=none") +asynOctetSetInputEos( "$(PORT)", -1, "\r") +asynOctetSetOutputEos("$(PORT)", -1, "\r") + +#- NewFocus Picomotor driver configuration parameters: +#- (1) controller being configured +#- (2) asyn port name (string) +PMNC87xxConfig($(CONTROLLER=0), "$(PORT)") + +epicsEnvSet("PMNC87XX_INIT_COMPLETE", "#") diff --git a/iocsh/Newport_ESP300.iocsh b/iocsh/Newport_ESP300.iocsh new file mode 100644 index 0000000..e681164 --- /dev/null +++ b/iocsh/Newport_ESP300.iocsh @@ -0,0 +1,30 @@ +# ### Newport_ESP300.iocsh ### + +#- ################################################### +#- PORT - Serial port for communications +#- CONTROLLER - Optional: Which controller is being configured +#- Default: 0 +#- +#- MAX_CONTROLLERS - Optional: Max number of controllers that will be configured +#- Default: 1 +#- +#- POLL_RATE - Optional: Polling increment in 1/60 sec +#- Default: 6 +#- ################################################### + +#- Newport ESP300 driver setup parameters: +#- (1) maximum number of controllers in system +#- (2) motor task polling rate (min=1Hz,max=60Hz) +$(ESP300_INIT_COMPLETE="") ESP300Setup($(MAX_CONTROLLERS=1), $(POLL_RATE=10)) + +# Newport ESP300 serial connection settings +iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=9600, BITS=8, STOP=1, PARITY=none") +asynOctetSetInputEos( "$(PORT)", -1, "") +asynOctetSetOutputEos("$(PORT)", -1, "") + +#- Newport ESP300 driver configuration parameters: +#- (1) controller# being configured +#- (2) ASYN port name +ESP300Config($(CONTROLLER=0), "$(PORT)") + +epicsEnvSet("ESP300_INIT_COMPLETE", "#") diff --git a/iocsh/Newport_MM4000.iocsh b/iocsh/Newport_MM4000.iocsh new file mode 100644 index 0000000..5b33aad --- /dev/null +++ b/iocsh/Newport_MM4000.iocsh @@ -0,0 +1,32 @@ +# ### Newport_NM4000.iocsh ### + +#- ################################################### +#- PORT - Serial port for communications +#- CONTROLLER - Optional: Which controller is being configured +#- Default: 0 +#- +#- MAX_CONTROLLERS - Optional: Max number of controllers that will be configured +#- Default: 1 +#- +#- POLL_RATE - Optional: Controller poll rate in hertz +#- Default: 10 +#- ################################################### + + +#- Newport MM4000 driver setup parameters: +#- (1) maximum # of controllers, +#- (2) motor task polling rate (min=1Hz, max=60Hz) +$(MM4000_INIT_COMPLETE="") MM4000Setup($(MAX_CONTROLLERS=1), $(POLL_RATE=10)) + +# Newport MM4000 serial connection settings +iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=38400, BITS=8, STOP=1, PARITY=none") +asynOctetSetInputEos( "$(PORT)", -1, "\r") +asynOctetSetOutputEos("$(PORT)", -1, "\r") + +# Newport MM4000 driver configuration parameters: +# (1) controller +# (2) asyn port name (e.g. serial0 or gpib1) +# (3) GPIB address (0 for serial) +MM4000Config($(CONTROLLER=0), "$(PORT)", 0) + +epicsEnvSet("MM4000_INIT_COMPLETE", "#") diff --git a/iocsh/Newport_PM500.iocsh b/iocsh/Newport_PM500.iocsh new file mode 100644 index 0000000..bf37a27 --- /dev/null +++ b/iocsh/Newport_PM500.iocsh @@ -0,0 +1,30 @@ +# ### Newport_PM500.iocsh ### + +#- ################################################### +#- PORT - Serial port for communications +#- CONTROLLER - Optional: Which controller is being configured +#- Default: 0 +#- +#- MAX_CONTROLLERS - Optional: Max number of controllers that will be configured +#- Default: 1 +#- +#- POLL_RATE - Optional: Controller poll rate in hertz +#- Default: 10 +#- ################################################### + +#- Newport PM500 driver setup parameters: +#- (1) maximum number of controllers in system +#- (2) motor task polling rate (min=1Hz,max=60Hz) +$(PM500_INIT_COMPLETE="") PM500Setup($(MAX_CONTROLLERS=1), $(POLL_RATE=10)) + +#- Newport PM500 serial connection settings +iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=9600, BITS=7, STOP=2, PARITY=even, HANDSHAKE=hardware") +asynOctetSetInputEos( "$(PORT)", -1, "\r") +asynOctetSetOutputEos("$(PORT)", -1, "\r") + +#- Newport PM500 configuration parameters: +#- (1) controller +#- (2) asyn port name (e.g. serial0 or gpib1) +PM500Config($(CONTROLLER=0), "$(PORT)") + +epicsEnvSet("PM500_INIT_COMPLETE", "#") diff --git a/iocsh/PI_C630.iocsh b/iocsh/PI_C630.iocsh new file mode 100644 index 0000000..b9aab5b --- /dev/null +++ b/iocsh/PI_C630.iocsh @@ -0,0 +1,49 @@ +# ### PI_C630.iocsh ### + +#- ################################################### +#- PORT - Serial port for communications +#- CONTROLLER - Optional: Which controller is being configured +#- Default: 0 +#- +#- MAX_CONTROLLERS - Optional: Max number of controllers that will be configured +#- Default: 1 +#- +#- NUM_AXES - Optional: Max number of axes per controller +#- Default: 1 +#- +#- POLL_RATE - Optional: Controller poll rate in hertz +#- Default: 10 +#- +#- CURR[1-9] - Optional: Current settings for axes 1 through 9 +#- Current equals 100mA * setting, maximum 800mA. +#- Default: 0 (off) +#- ################################################### + + +#-################################################ +#- PI C-630 driver setup parameters: +#- Load PIC630Setup once. +#- (1) max # of controller groups. Controller groups are per serial port. +#- (2) max # axes per controller group. Maximum 9. (addr 1-9) +#- (3) motor task polling rate (min=1Hz, max=60Hz, 10Hz works well) +#- Example: +#- PIC630Setup(1, 2, 10) 1 group. 2 axes (controllers) in the group. 10Hz poll. +$(PI_C630_INIT_COMPLETE="") PIC630Setup($(MAX_CONTROLLERS=1), $(NUM_AXES=1), $(POLL_RATE=10)) + +# PI C630 serial connection settings +iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=19200, BITS=8, STOP=1, PARITY=none") +asynOctetSetInputEos( "$(PORT)", -1, "\r") +asynOctetSetOutputEos("$(PORT)", -1, "\r") + +#- PIC630 driver configuration parameters: +#- Load one PIC630Config for each group of PI C-630 drivers. +#- (1) "Controller group" number +#- (2) MPF card +#- (3)-(11) Current setting per axis (1-9). Leave at 0 if unused. +#- Choices: 0=OFF, 1=100mA, 2=200mA, ... 8=800mA. +#- Example: +#- PIC630Config(0, "serial1, 5, 3, 0, 0, 0, 0, 0, 0, 0") +#- Group 0, asyn serial port 1, Axis1=.5A, Axis2=.3A, others OFF +PIC630Config($(CONTROLLER=0), "$(PORT)", $(CURR1=0), $(CURR2=0), $(CURR3=0), $(CURR4=0), $(CURR5=0), $(CURR6=0), $(CURR7=0), $(CURR8=0), $(CURR9=0)) + +epicsEnvSet("PI_C630_INIT_COMPLETE", "#") diff --git a/iocsh/PI_C867.iocsh b/iocsh/PI_C867.iocsh new file mode 100644 index 0000000..39b04a2 --- /dev/null +++ b/iocsh/PI_C867.iocsh @@ -0,0 +1,28 @@ +# ### PI_C867.iocsh ### + +#- ################################################### +#- PORT - Serial port for communications +#- CONTROLLER - Optional: Which controller is being configured +#- Controller port name will be PIC867$(CONTROLLER) +#- Default: 0 +#- +#- NUM_AXES - Optional: Max number of axes per controller +#- Default: 1 +#- +#- MOVING_POLL - Optional: Moving poll rate (in msec) +#- Default: POLL_RATE +#- +#- IDLE_POLL - Optional: Idle poll rate (in msec) +#- Default: POLL_RATE +#- +#- POLL_RATE - Optional: Poll rate in msec +#- Default: 100 +#- ################################################### + + +# PI C867 serial connection settings +iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=38400, BITS=8, STOP=1, PARITY=none") +asynOctetSetInputEos( "$(PORT)", -1, "\n\r") +asynOctetSetOutputEos("$(PORT)", -1, "\n") + +PI_GCS2_CreateController("PIC867$(CONTROLLER)", "$(PORT)", $(NUM_AXES=0), 0, 0, $(MOVING_POLL=$(POLL_RATE=100)), $(IDLE_POLL=$(POLL_RATE=100))) diff --git a/iocsh/PI_E710.iocsh b/iocsh/PI_E710.iocsh new file mode 100644 index 0000000..b4bc213 --- /dev/null +++ b/iocsh/PI_E710.iocsh @@ -0,0 +1,31 @@ +# ### PI_E710.iocsh ### + +#- ################################################### +#- PORT - Serial port for communications +#- CONTROLLER - Optional: Which controller is being configured +#- Default: 0 +#- +#- MAX_CONTROLLERS - Optional: Max number of controllers that will be configured +#- Default: 1 +#- +#- POLL_RATE - Optional: Controller poll rate in hertz +#- Default: 10 +#- ################################################### + +#- PI E-710 driver setup parameters: +#- (1) maximum # of controllers, +#- (2) motor task polling rate (min=1Hz, max=60Hz) +$(E710_INIT_COMPLETE="") PIE710Setup($(MAX_CONTROLLERS=1), $(POLL_RATE=10)) + +# PI E710 serial connection settings +iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=9600, BITS=8, STOP=1, PARITY=none") +asynOctetSetInputEos( "$(PORT)", -1, "\n") +asynOctetSetOutputEos("$(PORT)", -1, "\n") + +#- PI E-710 driver configuration parameters: +#- (1) controller +#- (2) asyn port name (e.g. serial1 or gpib1) +#- (3) GPIB address (0 for serial) +PIE710Config($(CONTROLLER=0), "$(PORT)", 0) + +epicsEnvSet("E710_INIT_COMPLETE", "#") diff --git a/iocsh/PI_E816.iocsh b/iocsh/PI_E816.iocsh new file mode 100644 index 0000000..3007338 --- /dev/null +++ b/iocsh/PI_E816.iocsh @@ -0,0 +1,30 @@ +# ### PI_E816.iocsh ### + +#- ################################################### +#- PORT - Serial port for communications +#- CONTROLLER - Optional: Which controller is being configured +#- Default: 0 +#- +#- MAX_CONTROLLERS - Optional: Max number of controllers that will be configured +#- Default: 1 +#- +#- POLL_RATE - Optional: Controller poll rate in hertz +#- Default: 10 +#- ################################################### + +#- PI E-816 driver setup parameters: +#- (1) maximum number of controllers in system +#- (2) motor task polling rate (min=1Hz,max=60Hz) +$(E816_INIT_COMPLETE="") PIE816Setup($(MAX_CONTROLLERS=1), $(POLL_RATE=10)) + +# PI E816 serial connection settings +iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=38400, BITS=8, STOP=1, PARITY=none, HANDSHAKE=hardware") +asynOctetSetInputEos( "$(PORT)", -1, "\n") +asynOctetSetOutputEos("$(PORT)", -1, "\n") + +# PI E-816 driver configuration parameters: +# (1) controller# being configured, +# (2) ASYN port name +PIE816Config($(CONTROLLER=0), "$(PORT)") + +epicsEnvSet("E816_INIT_COMPLETE", "#") diff --git a/iocsh/allstop.iocsh b/iocsh/allstop.iocsh new file mode 100644 index 0000000..e611b50 --- /dev/null +++ b/iocsh/allstop.iocsh @@ -0,0 +1,10 @@ +# ### allstop.iocsh ### + +#- ################################################### +#- PREFIX - IOC Prefix +#- MOTOR - Location of motor module +#- ################################################### + +#- Allstop, alldone +dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=$(PREFIX)") +doAfterIocInit("motorUtilInit('$(PREFIX)')") diff --git a/iocsh/motorSim.iocsh b/iocsh/motorSim.iocsh new file mode 100644 index 0000000..80eb0ad --- /dev/null +++ b/iocsh/motorSim.iocsh @@ -0,0 +1,34 @@ +# ### motorSim.iocsh ### + +#- ################################################### +#- PREFIX - IOC Prefix +#- INSTANCE - Instance name, used to create the low-level driver drvet name +#- Combined with the controller number to create the asyn port name +#- +#- SUB - Optional: Subsitutions file (asyn_motor.db), Macros P, DTYP, PORT, +#- DHLM, DLLM, and INIT will be predefined. +#- Default: $(MOTOR)/iocsh/EXAMPLE_motorSim.substitutions +#- +#- CONTROLLER - Optional: Which controller is being configured +#- Default: 0 +#- +#- NUM_AXES - Optional: Number of axes on this controller +#- Default: 1 +#- +#- LOW_LIM - Optional: Low Limit +#- Default: -32000 +#- +#- HIGH_LIM - Optional: High Limit +#- Default: 32000 +#- +#- HOME_POS - Optional: Home position +#- Default: 0 +#- ################################################### + +# Create simulated motors: ( start card , start axis , low limit, high limit, home posn, # cards, # axes to setup) +motorSimCreate($(CONTROLLER=0), 0, $(LOW_LIM=-32000), $(HIGH_LIM=32000), $(HOME_POS=0), 1, $(NUM_AXES=1)) + +# Setup the Asyn layer (portname, low-level driver drvet name, card, number of axes on card) +drvAsynMotorConfigure("$(INSTANCE)$(CONTROLLER=0)", "$(INSTANCE)", $(CONTROLLER=0), $(NUM_AXES=1)) + +dbLoadTemplate("$(SUB=$(MOTOR)/iocsh/EXAMPLE_motorSim.substitutions)", "P=$(PREFIX), DTYP='asynMotor', PORT=$(INSTANCE)$(CONTROLLER=0), DHLM=$(HIGH_LIM=32000), DLLM=$(LOW_LIM=-32000)") diff --git a/motorApp/AMCISrc/AMCISupport.dbd b/motorApp/AMCISrc/AMCISupport.dbd new file mode 100644 index 0000000..48132bb --- /dev/null +++ b/motorApp/AMCISrc/AMCISupport.dbd @@ -0,0 +1,2 @@ +include "ANG1Support.dbd" +include "ANF2Support.dbd" diff --git a/motorApp/AMCISrc/ANF2Driver.cpp b/motorApp/AMCISrc/ANF2Driver.cpp new file mode 100644 index 0000000..993a0a4 --- /dev/null +++ b/motorApp/AMCISrc/ANF2Driver.cpp @@ -0,0 +1,1088 @@ +/* +FILENAME... ANF2Driver.cpp +USAGE... Motor record driver support for the AMCI ANF2 stepper motor controller over Modbus/TCP. + +Kevin Peterson + +Based on the AMCI ANG1 Model 3 device driver written by Kurt Goetze + +*/ + + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "ANF2Driver.h" +#include + +#define NINT(f) (int)((f)>0 ? (f)+0.5 : (f)-0.5) + +static const char *driverName = "ANF2MotorDriver"; + +/** Constructor, Creates a new ANF2Controller object. + * \param[in] portName The name of the asyn port that will be created for this driver + * \param[in] ANF2InPortName The name of the drvAsynSerialPort that was created previously to connect to the ANF2 controller + * \param[in] ANF2OutPortName The name of the drvAsynSerialPort that was created previously to connect to the ANF2 controller + * \param[in] numAxes The number of axes on the controller stack + */ +ANF2Controller::ANF2Controller(const char *portName, const char *ANF2InPortName, const char *ANF2OutPortName, + int numAxes) + : asynMotorController(portName, numAxes, NUM_ANF2_PARAMS, + asynInt32ArrayMask, // One additional interface beyond those in base class + asynInt32ArrayMask, // One additional callback interface beyond those in base class + ASYN_CANBLOCK | ASYN_MULTIDEVICE, + 1, // autoconnect + 0, 0) // Default priority and stack size +{ + int i, j; + asynStatus status = asynSuccess; + static const char *functionName = "ANF2Controller::ANF2Controller"; + + // Keep track of the number of axes created, so the poller can wait for all the axes to be created before starting + axesCreated_ = 0; + + inputDriver_ = epicsStrDup(ANF2InPortName); // Set this before calls to create Axis objects + + // Create controller-specific parameters + createParam(ANF2ResetErrorsString, asynParamInt32, &ANF2ResetErrors_); + createParam(ANF2GetInfoString, asynParamInt32, &ANF2GetInfo_); + //createParam(ANF2ReconfigString, asynParamInt32, &ANF2Reconfig_); + + numAxes_ = numAxes; + + for (j=0; jconnect(ANF2InPortName, i+j*AXIS_REG_OFFSET, &pasynUserInReg_[j][i], NULL); + } + status = pasynInt32ArraySyncIO->connect(ANF2OutPortName, j*AXIS_REG_OFFSET, &pasynUserOutReg_[j], NULL); + } + if (status) { + asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, + "%s: cannot connect to ANF2 controller\n", + functionName); + } + + /* Create the poller thread for this controller (do 2 forced-fast polls) + * NOTE: at this point the axis objects don't yet exist, but the poller tolerates this */ + //startPoller(movingPollPeriod, idlePollPeriod, 2); +} + + +/** Creates a new ANF2Controller object. + * Configuration command, called directly or from iocsh + * \param[in] portName The name of the asyn port that will be created for this driver + * \param[in] ANF2InPortName The name of the drvAsynIPPPort that was created previously to connect to the ANF2 controller + * \param[in] ANF2OutPortName The name of the drvAsynIPPPort that was created previously to connect to the ANF2 controller + * \param[in] numAxes The number of axes on the controller stack + */ +extern "C" int ANF2CreateController(const char *portName, const char *ANF2InPortName, const char *ANF2OutPortName, int numAxes) +{ + // Enforce max values + if (numAxes > MAX_AXES) { + numAxes = MAX_AXES; + } + + new ANF2Controller(portName, ANF2InPortName, ANF2OutPortName, numAxes); + return(asynSuccess); +} + +/** Starts the poller for a given controller + * \param[in] ANF2Name The name of the asyn port that for the controller + * \param[in] movingPollPeriod The time in ms between polls when any axis is moving + * \param[in] idlePollPeriod The time in ms between polls when no axis is moving + */ +extern "C" asynStatus ANF2StartPoller(const char *ANF2Name, int movingPollPeriod, int idlePollPeriod) +{ + ANF2Controller *pC; + static const char *functionName = "ANF2StartPoller"; + + pC = (ANF2Controller*) findAsynPortDriver(ANF2Name); + if (!pC) { + printf("%s:%s: Error port %s not found\n", + driverName, functionName, ANF2Name); + return asynError; + } + + pC->lock(); + pC->doStartPoller(movingPollPeriod/1000.0, idlePollPeriod/1000.0); + pC->unlock(); + return asynSuccess; +} + +void ANF2Controller::doStartPoller(double movingPollPeriod, double idlePollPeriod) +{ + // + movingPollPeriod_ = movingPollPeriod; + idlePollPeriod_ = idlePollPeriod; + + // + startPoller(movingPollPeriod_, idlePollPeriod_, 2); +} + + +/** Reports on status of the driver + * \param[in] fp The file pointer on which report information will be written + * \param[in] level The level of report detail desired + * + * If details > 0 then information is printed about each axis. + * After printing controller-specific information it calls asynMotorController::report() + */ +void ANF2Controller::report(FILE *fp, int level) +{ + int i, j; + ANF2Axis* pAxis[MAX_AXES]; + + fprintf(fp, "====================================\n"); + fprintf(fp, "ANF2 motor driver:\n"); + fprintf(fp, " asyn port: %s\n", this->portName); + fprintf(fp, " num axes: %i\n", numAxes_); + fprintf(fp, " axes created: %i\n", axesCreated_); + fprintf(fp, " moving poll period: %lf\n", movingPollPeriod_); + fprintf(fp, " idle poll period: %lf\n", idlePollPeriod_); + fprintf(fp, "\n"); + fprintf(fp, "Input registers:\n\n"); + + for (j=0; jgetInfo(); + } + + fprintf(fp, " Reg\t"); + for (j=0; jinputReg_[i]); + + } + fprintf(fp, "\n"); + } + + fprintf(fp, "\n"); + /*for (i=0; i(asynMotorController::getAxis(pANF2Axis methodsasynUser)); + return static_cast(asynMotorController::getAxis(pasynUser)); +} + +/** Returns a pointer to an ANF2Axis object. + * Returns NULL if the axis number encoded in pasynUser is invalid. + * \param[in] No Axis index number. */ +ANF2Axis* ANF2Controller::getAxis(int axisNo) +{ + return static_cast(asynMotorController::getAxis(axisNo)); +} + +/** Called when asyn clients call pasynInt32->write(). + * Extracts the function and axis number from pasynUser. + * Sets the value in the parameter library (?) + * + * If the function is ANF2Jerk_ it sets the jerk value in the controller. + * Calls any registered callbacks for this pasynUser->reason and address. + * + * For all other functions it calls asynMotorController::writeInt32. + * \param[in] pasynUser asynUser structure that encodes the reason and address. + * \param[in] value Value to write. */ +asynStatus ANF2Controller::writeInt32(asynUser *pasynUser, epicsInt32 value) +{ + int function = pasynUser->reason; + asynStatus status = asynSuccess; + ANF2Axis *pAxis = getAxis(pasynUser); + static const char *functionName = "writeInt32"; + + /* Set the parameter and readback in the parameter library. */ + status = setIntegerParam(pAxis->axisNo_, function, value); + + if (function == ANF2ResetErrors_) + { + // Only reset errors when value is 1 + if (value == 1) { + printf("ANF2Controller:writeInt32: Resetting errors for axis = %d\n", pAxis->axisNo_); + pAxis->resetErrors(); + + } + } else if (function == ANF2GetInfo_) + { + // Only get info when value is 1 + if (value == 1) { + printf("ANF2Controller:writeInt32: Getting info for axis = %d\n", pAxis->axisNo_); + pAxis->getInfo(); + + } + /* + } else if (function == ANF2Reconfig_) + { + // reconfig regardless of the value + pAxis->reconfig(value); + */ + } else { + // Call base class method + status = asynMotorController::writeInt32(pasynUser, value); + } + + /* Do callbacks so higher layers see any changes */ + pAxis->callParamCallbacks(); + if (status) + asynPrint(pasynUser, ASYN_TRACE_ERROR, + "%s:%s: error, status=%d function=%d, value=%d\n", + driverName, functionName, status, function, value); + else + asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, + "%s:%s: function=%d, value=%d\n", + driverName, functionName, function, value); + return status; +} + +asynStatus ANF2Controller::writeReg32Array(int axisNo, epicsInt32* output, int nElements, double timeout) +{ + asynStatus status; + ANF2Axis *pAxis = getAxis(axisNo); + static const char *functionName = "ANF2Controller::writeReg32Array"; + + // This message isn't very helpful. Print something better in the future. + asynPrint(pAxis->pasynUser_, ASYN_TRACEIO_DRIVER, + "%s: axisNo=%i, nElements=%d\n", + functionName, axisNo, nElements); + status = pasynInt32ArraySyncIO->write(pasynUserOutReg_[axisNo], output, nElements, timeout); + + return status; +} + +asynStatus ANF2Controller::readReg16(int axisNo, int axisReg, epicsInt32 *input, double timeout) +{ + asynStatus status; + + //printf("axisReg = %d\n", axisReg); + //asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,"readReg16 reg = %d\n", axisReg); + status = pasynInt32SyncIO->read(pasynUserInReg_[axisNo][axisReg], input, timeout); + + return status ; +} + +asynStatus ANF2Controller::readReg32(int axisNo, int axisReg, epicsInt32 *combo, double timeout) +{ + asynStatus status; + epicsInt32 lowerWord32, upperWord32; // only have pasynInt32SyncIO, not pasynInt16SyncIO , + + //printf("calling readReg16\n"); + status = readReg16(axisNo, axisReg, &upperWord32, timeout); //get Upper Word + + axisReg++; + status = readReg16(axisNo, axisReg, &lowerWord32, timeout); //get Lower Word + + *combo = NINT((upperWord32 << 16) | lowerWord32); + + return status ; +} + + +// ANF2Axis methods Here +// These are the ANF2Axis methods + +/** Creates a new ANF2Axis object. + * \param[in] pC Pointer to the ANF2Controller to which this axis belongs. + * \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1. + * + * Initializes register numbers, etc. + */ +ANF2Axis::ANF2Axis(ANF2Controller *pC, int axisNo, epicsInt32 config, epicsInt32 baseSpeed, epicsInt32 homingTimeout) + : asynMotorAxis(pC, axisNo), + pC_(pC) +{ + int status; + + axisNo_ = axisNo; + config_ = config; + baseSpeed_ = baseSpeed; + homingTimeout_ = homingTimeout; + + // These registers will always be zero + zeroRegisters(zeroReg_); + + status = pasynInt32SyncIO->connect(pC_->inputDriver_, axisNo_*AXIS_REG_OFFSET, &pasynUserForceRead_, "MODBUS_READ"); + if (status) { + //printf("%s:%s: Error, unable to connect pasynUserForceRead_ to Modbus input driver %s\n", pC_->inputDriver_, pC_->functionName, myModbusInputDriver); + printf("%s: Error, unable to connect pasynUserForceRead_ to Modbus input driver\n", pC_->inputDriver_); + } + + /* TODO: + * reduce the sleeps to see which ones are necessary + * make reconfig useful? + */ + + epicsThreadSleep(0.1); + + // Clear the command/configuration register (a good thing to do but doesn't appear to be necessary) + //status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); + + // Delay + //epicsThreadSleep(0.05); + + // These registers will always have the last config that was sent to the controller + zeroRegisters(confReg_); + + // Send the configuration (array) + // assemble the configuration bits; set the start speed to a non-zero value (100), which is required for the configuration to be accepted + confReg_[CONFIGURATION] = config; + confReg_[BASE_SPEED] = baseSpeed; + confReg_[HOME_TIMEOUT] = homingTimeout << 16; + + // Write all the registers + status = pC_->writeReg32Array(axisNo_, confReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); + + // Delay + epicsThreadSleep(0.05); + + // Parse the configuration (mostly for asynReport purposes) + // MSW + CaptInput_ = (config & (0x1 << 16)) >> 16; + ExtInput_ = (config & (0x2 << 16)) >> 17; + HomeInput_ = (config & (0x4 << 16)) >> 18; + CWInput_ = (config & (0x18 << 16)) >> 19; + CCWInput_ = (config & (0x60 << 16)) >> 21; + BHPO_ = (config & (0x80 << 16)) >> 23; + QuadEnc_ = (config & (0x100 << 16)) >> 24; + DiagFbk_ = (config & (0x200 << 16)) >> 25; + OutPulse_ = (config & (0x400 << 16)) >> 26; + HomeOp_ = (config & (0x800 << 16)) >> 27; + CardAxis_ = (config & (0x4000 << 16)) >> 30; + OpMode_ = (epicsUInt32)(config & (0x8000 << 16)) >> 31; + // LSW + CaptInputAS_ = config & 0x1; + ExtInputAS_ = (config & 0x2) >> 1; + HomeInputAS_ = (config & 0x4) >> 2; + CWInputAS_ = (config & 0x8) >> 3; + CCWInputAS_ = (config & 0x10) >> 4; + + // Only allow UEIP to be used if the axis is configured to have a quadrature encoder + if ((QuadEnc_ != 0x0) || (DiagFbk_ != 0x0)) { + setIntegerParam(pC_->motorStatusHasEncoder_, 1); + } else { + setIntegerParam(pC_->motorStatusHasEncoder_, 0); + } + + // set position to 0 to clear the "position invalid" status that results from configuring the axis + setPosition(0); + // Tell asynMotor device support the position is zero so that autosave will restore the saved position (doesn't appear to be necessary) + //setDoubleParam(pC_->motorPosition_, 0.0); + + // Delay + //epicsThreadSleep(1.0); + + // Initialize parameters to avoid ASYN_TRACE_FLOW errors + setIntegerParam(pC_->motorStatusDirection_, 1); + // The following are necessary after this commit: + // https://github.com/epics-modules/motor/commit/36dfab4a78725866fab5bd212c4c128a86e9f044 + setIntegerParam(pC_->motorPowerAutoOnOff_, 0); + setDoubleParam(pC_->motorPowerOnDelay_, 0.0); + setDoubleParam(pC_->motorPowerOffDelay_, 0.0); + + // Tell the driver the axis has been created + pC_->axesCreated_ += 1; + + //epicsThreadSleep(1.0); +} + +/* + Configuration Bits: + 0x1 - Caputure Input (0 = Disabled, 1 = Enabled) + 0x2 - External Input (0 = Disabled, 1 = Enabled) + 0x4 - Home Input (0 = Disabled, 1 = Enabled) + 0x8 - + + */ + +extern "C" asynStatus ANF2CreateAxis(const char *ANF2Name, /* specify which controller by port name */ + int axis, /* axis number 0-1 */ + const char *hexConfig, /* desired configuration in hex */ + epicsInt32 baseSpeed, /* base speed */ + epicsInt32 homingTimeout) /* homing timeout */ +{ + ANF2Controller *pC; + epicsInt32 config; + static const char *functionName = "ANF2CreateAxis"; + + pC = (ANF2Controller*) findAsynPortDriver(ANF2Name); + if (!pC) { + printf("%s:%s: Error port %s not found\n", + driverName, functionName, ANF2Name); + return asynError; + } + + errno = 0; + config = strtoul(hexConfig, NULL, 16); + if (errno != 0) { + printf("%s:%s: Error invalid config=%s\n", + driverName, functionName, hexConfig); + return asynError; + } else { + printf("%s:%s: Config=0x%x\n", + driverName, functionName, config); + } + + // baseSpeed is steps/second (1-1,000,000) + if (baseSpeed < 1) { + baseSpeed = 1; + } + if (baseSpeed > 1000000) { + baseSpeed = 1000000; + } + + // homingTimeout is seconds (0-300) + if (homingTimeout < 0) { + homingTimeout = 0; + } + if (homingTimeout > 300) { + homingTimeout = 300; + } + + pC->lock(); + new ANF2Axis(pC, axis, config, baseSpeed, homingTimeout); + pC->unlock(); + return asynSuccess; +} + +void ANF2Axis::zeroRegisters(epicsInt32 *reg) +{ + int i; + + for(i=0; i<5; i++) + { + reg[i] = 0x0; + } +} + +asynStatus ANF2Axis::resetErrors() +{ + asynStatus status; + epicsInt32 errorReg[5]; + static const char *functionName = "ANF2Axis::resetErrors"; + + asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, "%s: axisNo=%i\n", functionName, axisNo_); + + zeroRegisters(errorReg); + + errorReg[COMMAND] = 0x800 << 16; + + // Send the reset error command + status = pC_->writeReg32Array(axisNo_, errorReg, 5, DEFAULT_CONTROLLER_TIMEOUT); + + return status; +} + +void ANF2Axis::getInfo() +{ + asynStatus status; + int i; + + // For a read (not sure why this is necessary) + status = pasynInt32SyncIO->write(pasynUserForceRead_, 1, DEFAULT_CONTROLLER_TIMEOUT); + + //printf("Registers for axis %i:\n", axisNo_); + + for( i=0; ireadReg16(axisNo_, i, &inputReg_[i], DEFAULT_CONTROLLER_TIMEOUT); + //printf(" status=%d, register=%i, val=0x%x\n", status, i, inputReg_[i]); + } +} + +/* +// reconfig was used during development. It won't be generally useful without effort. +// It isn't obvious that this is a feature that should exist on-the-fly +void ANF2Axis::reconfig(epicsInt32 value) +{ + asynStatus status; + epicsInt32 confReg[5]; + + // TODO: modify this to use the base speed from the parameter, and instead accept a string for a new config + + printf("Reconfiguring axis %i\n", axisNo_); + + // Clear the command/configuration register + status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); + + // Construct the new config + zeroRegisters(confReg); + confReg[CONFIGURATION] = 0x86000000; + confReg[BASE_SPEED] = 0x00000064; + //confReg[HOME_TIMEOUT] = 0x0; + //confReg[CONFIG_REG_3] = 0x0; + //confReg[CONFIG_REG_4] = 0x0; + + epicsThreadSleep(0.05); + + // Send the new config + status = pC_->writeReg32Array(axisNo_, confReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); + + epicsThreadSleep(0.05); + + // Set the position to clear the invalid position error + setPosition(value); + + epicsThreadSleep(0.05); +} +*/ + +/** Reports on status of the axis + * \param[in] fp The file pointer on which report information will be written + * \param[in] level The level of report detail desired + * + * After printing device-specific information calls asynMotorAxis::report() + */ +void ANF2Axis::report(FILE *fp, int level) +{ + // TODO: make this more useful + + if (level > 0) { + fprintf(fp, "Configuration for axis %i [0x%x]:\n", axisNo_, config_); + fprintf(fp, " Base Speed: %i\n", baseSpeed_); + fprintf(fp, " Homing Timeout: %i\n", homingTimeout_); + fprintf(fp, " Capture Input: %i (Active State: %i)\n", CaptInput_, CaptInputAS_); + fprintf(fp, " External Input: %i (Active State: %i)\n", ExtInput_, ExtInputAS_); + fprintf(fp, " Home Input: %i (Active State: %i)\n", HomeInput_, HomeInputAS_); + fprintf(fp, " CW Input: %i (Active State: %i)\n", CWInput_, CWInputAS_); + fprintf(fp, " CCW Input: %i (Active State: %i)\n", CCWInput_, CCWInputAS_); + fprintf(fp, " Backplane Home Proximity Operation: %i\n", BHPO_); + fprintf(fp, " Quadrature Encoder: %i\n", QuadEnc_); + fprintf(fp, " Diagnostic Feedback: %i\n", DiagFbk_); + fprintf(fp, " Output Pulse Type: %i\n", OutPulse_); + fprintf(fp, " Home Operation: %i\n", HomeOp_); + fprintf(fp, " Card Axis: %i\n", CardAxis_); + fprintf(fp, " Operation Mode for Axis: %i\n", OpMode_); + fprintf(fp, "\n"); + } + + //printf("ANF2Axis::report -> BEFORE asynMotorAxis::report!!\n"); + + // Call the base class method + asynMotorAxis::report(fp, level); + + //printf("ANF2Axis::report -> AFTER asynMotorAxis::report!!\n"); + +} + +// SET VEL & ACCEL +asynStatus ANF2Axis::sendAccelAndVelocity(double acceleration, double velocity) +{ + // static const char *functionName = "ANF2Axis::sendAccelAndVelocity"; + + // ANF2 speed range is 1 to 1,000,000 steps/sec + if (velocity > 1000000.0) { + velocity = 1000000.0; + } + if (velocity < 1.0) { + velocity = 1.0; + } + + // Set the velocity register + motionReg_[SPEED] = NINT(velocity); + + // ANF2 acceleration range 1 to 2000 steps/ms/sec + // Therefore need to limit range received by motor record from 1000 to 2e6 steps/sec/sec + if (acceleration < 1000.0) { + //printf("Acceleration is < 1000: %lf\n", acceleration); + acceleration = 1000.0; + } + if (acceleration > 2000000.0) { + //printf("Acceleration is > 2000: %lf\n", acceleration); + acceleration = 2000000.0; + } + + // Set the accel/decel register + motionReg_[ACCEL_DECEL] = (NINT(acceleration/1000.0) << 16) | (NINT(acceleration/1000.0)); + + return asynSuccess; +} + +/* + * This driver only sets the base speed at initialization when the configuration is sent. + * It is possible that the base speed (VBAS) in the motor record is inconsistent with the + * base speed set at initialization, since there is no way for an asyn motor driver to force + * the base speed to be reset when a user changes it. The resulting acceleration calculated + * by the motor record is likely to be incorrect. The following method calculates the + * acceleration that will give the correct acceleration time (ACCL) for the base speed that + * was specified at initialization. + */ +double ANF2Axis::correctAccel(double minVelocity, double maxVelocity, double acceleration) +{ + double accelTime; + double newAccel; + static const char *functionName = "ANF2Axis::correctAccel"; + + accelTime = (maxVelocity - minVelocity) / acceleration; + newAccel = (maxVelocity - (double)baseSpeed_) / accelTime; + + asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, + "%s: axisNo=%i, old acceleration=%lf, new acceleration=%lf\n", + functionName, axisNo_, acceleration, newAccel); + + return newAccel; +} + + +// MOVE +asynStatus ANF2Axis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration) +{ + asynStatus status; + epicsInt32 posInt; + static const char *functionName = "ANF2Axis::move"; + + asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, + "%s: axisNo=%i, relative=%i, minVelocity=%f, maxVelocity=%f, acceleration=%f\n", + functionName, axisNo_, relative, minVelocity, maxVelocity, acceleration); + + // Clear the command/configuration register + status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); + + epicsThreadSleep(0.05); + + // Clear the motition registers + zeroRegisters(motionReg_); + + // Correct the acceleration + acceleration = correctAccel(minVelocity, maxVelocity, acceleration); + + // This sets indices 2 & 3 of motionReg_ + status = sendAccelAndVelocity(acceleration, maxVelocity); + + posInt = NINT(position); + + if (relative) { + //printf(" ** relative move called\n"); + + // Set position and cmd registers + motionReg_[COMMAND] = 0x2 << 16; + motionReg_[POSITION] = posInt; + + } else { + //printf(" ** absolute move called\n"); + + // Set position and cmd registers + motionReg_[COMMAND] = 0x1 << 16; + motionReg_[POSITION] = posInt; + } + + //printf(" ** position = %d\n", posInt); + + // The final registers are zero for absolute and relative moves (this shouldn't be necessary--DELETEME) + motionReg_[CMD_REG_4] = 0x0; + + // Write all the registers atomically + // The number of elements refers to the number of epicsInt32s registers_ + status = pC_->writeReg32Array(axisNo_, motionReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); + + // Delay the first status read, give the controller some time to return moving status + epicsThreadSleep(0.05); + return status; +} + +// HOME (needs work) +asynStatus ANF2Axis::home(double minVelocity, double maxVelocity, double acceleration, int forwards) +{ + asynStatus status; + static const char *functionName = "ANF2Axis::home"; + + asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, + "%s: axisNo=%i, forwards=%i, minVelocity=%f, maxVelocity=%f, acceleration=%f\n", + functionName, axisNo_, forwards, minVelocity, maxVelocity, acceleration); + + // Clear the command/configuration register + status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); + + epicsThreadSleep(0.05); + + // Clear the motition registers + zeroRegisters(motionReg_); + + // Correct the acceleration + acceleration = correctAccel(minVelocity, maxVelocity, acceleration); + + // This sets indices 2 & 3 of motionReg_ + status = sendAccelAndVelocity(acceleration, maxVelocity); + + // Note: if the home input is active when the home command is sent, the axis will appear to move in the wrong direction + if (forwards) { + printf(" ** HOMING FORWARDS **\n"); + // The +Find Home (CW) command + motionReg_[COMMAND] = 0x20 << 16; + } else { + printf(" ** HOMING REVERSE **\n"); + // The -Find Home (CCW) command + motionReg_[COMMAND] = 0x40 << 16; + } + + // Write all the registers atomically + status = pC_->writeReg32Array(axisNo_, motionReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); + + return status; +} + +// JOG +asynStatus ANF2Axis::moveVelocity(double minVelocity, double maxVelocity, double acceleration) +{ + asynStatus status; + //int velo, distance; + static const char *functionName = "ANF2Axis::moveVelocity"; + + asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, + "%s: axisNo=%d, minVelocity=%f, maxVelocity=%f, acceleration=%f\n", + functionName, axisNo_, minVelocity, maxVelocity, acceleration); + + // + // The jog command requires a different stop than a move command + + // Set a jogging flag + jogging_ = true; + + // Clear the command/configuration register + status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); + + epicsThreadSleep(0.05); + + // Clear the motition registers + zeroRegisters(motionReg_); + + // Note: the jog acceleration doesn't need to be corrected; the JAR field has units of egu/s/s + + if (maxVelocity > 0.0) { + //printf(" ** positive jog called\n"); + + // Set cmd register + motionReg_[COMMAND] = 0x80 << 16; + + // Do nothing to the velocity + + } else { + //printf(" ** negative jog called\n"); + + // Set cmd register + motionReg_[COMMAND] = 0x100 << 16; + + // ANF2 only accepts speeds > 0 + maxVelocity = fabs(maxVelocity); + } + + // This sets indices 2 & 3 of motionReg_ + status = sendAccelAndVelocity(acceleration, maxVelocity); + + // Write all the registers atomically + status = pC_->writeReg32Array(axisNo_, motionReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); + // + + /* + velo = NINT(fabs(maxVelocity)); + + // Simulate a jog like the ANG1 driver does. Move 1 million steps + distance = 1000000; + if (maxVelocity > 0.) { + // This is a positive move in ANF2 coordinates + //printf(" ** relative move (JOG pos) called\n"); + status = move(distance, 0, minVelocity, velo, acceleration); + } else { + // This is a negative move in ANF2 coordinates + //printf(" ** relative move (JOG neg) called\n"); + status = move((distance * -1.0), 0, minVelocity, velo, acceleration); + } + */ + + // Delay the first status read, give the controller some time to return moving status + epicsThreadSleep(0.05); + return status; +} + + +// STOP +asynStatus ANF2Axis::stop(double acceleration) +{ + asynStatus status; + epicsInt32 stopReg; + static const char *functionName = "ANF2Axis::stop"; + + asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, "%s: axisNo=%i\n", functionName, axisNo_); + + //printf("\n STOP \n\n"); + + // The stop commands ignore all 32-bit registers beyond the first + + // Clear the command/configuration register (this causes a jog to stop) + status = pC_->writeReg32Array(axisNo_, zeroReg_, 1, DEFAULT_CONTROLLER_TIMEOUT); + + if (jogging_ == false) + { + //printf("stopping a normal move\n"); + // The immediate stop command cuts the pulses off without any deceleration and causes the position to become invalid + //stopReg = 0x10 << 16; // Immediate stop + // Hold move works very well with normal moves + stopReg = 0x4 << 16; // Hold move + + // This causes a normal move to stop + status = pC_->writeReg32Array(axisNo_, &stopReg, 1, DEFAULT_CONTROLLER_TIMEOUT); + + // Clear the command/configuration register + //status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); + } else { + // Reset the jogging flag (assume the stop was successful) + //printf("resetting the jog flag\n"); + jogging_ = false; + } + + return status; +} + +// SET +asynStatus ANF2Axis::setPosition(double position) +{ + asynStatus status; + epicsInt32 set_position; + epicsInt32 posReg[5]; + static const char *functionName = "ANF2Axis::setPosition"; + + asynPrint(pasynUser_, ASYN_TRACEIO_DRIVER, "%s: axisNo=%i, position=%lf\n", functionName, axisNo_, position); + + // Clear the command/configuration register + status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); + + epicsThreadSleep(0.1); + + set_position = NINT(position); + + zeroRegisters(posReg); + posReg[COMMAND] = 0x200 << 16; + posReg[POSITION] = set_position; + + // Write all the registers atomically + status = pC_->writeReg32Array(axisNo_, posReg, 5, DEFAULT_CONTROLLER_TIMEOUT); + + // Can this delay be shorter? + epicsThreadSleep(0.2); + + // The ANG1 driver does this; do we need to? + // Clear the command/configuration register + //status = pC_->writeReg32Array(axisNo_, zeroReg_, 5, DEFAULT_CONTROLLER_TIMEOUT); + + return status; +} + +// ENABLE TORQUE +asynStatus ANF2Axis::setClosedLoop(bool closedLoop) +{ + //asynStatus status; + //epicsInt32 clReg[5]; + //static const char *functionName = "ANF2Axis::setClosedLoop"; + + // The ANF2 doesn't have a closed-loop enable/disable command, so do nothing. + // The configuration of an axis: + // * can be changed so that an axis is disabled, but that doesn't disable torque + // * can be changed to disable the use of encoder inputs, but that isn't currently allowed on-the-fly + + /*printf(" ** setClosedLoop called \n"); + if (closedLoop) { + printf("setting enable true\n"); + + setIntegerParam(pC_->motorStatusPowerOn_, 1); + } else { + printf("setting disable false\n"); + setIntegerParam(pC_->motorStatusPowerOn_, 0); + } + return status;*/ + + return asynSuccess; +} + +// POLL +/** Polls the axis. + * This function reads motor position, limit status, home status, and moving status + * It calls setIntegerParam() and setDoubleParam() for each item that it polls, + * and then calls callParamCallbacks() at the end. + * \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false). */ +asynStatus ANF2Axis::poll(bool *moving) +{ + int done; + int lowLimit; + int highLimit; + int enabled; + int cmdError; + int direction; + double position; + double encPosition; + asynStatus status; + epicsInt32 read_val; // don't use a pointer here. The _address_ of read_val should be passed to the read function. + + // Don't do any polling until ALL the axes have been created; this ensures that we don't interpret the configuration values as command values + // This is probably not necessary now that the poller can be started after iocInit + if (pC_->axesCreated_ != pC_->numAxes_) { + *moving = false; + return asynSuccess; + } + + // Force a read operation + //printf(" . . . . . Calling pasynInt32SyncIO->write\n"); + //printf("Calling pasynInt32SyncIO->write(pasynUserForceRead_, 1, TIMEOUT), pasynUserForceRead_->reason=%d\n", pasynUserForceRead_->reason); + status = pasynInt32SyncIO->write(pasynUserForceRead_, 1, DEFAULT_CONTROLLER_TIMEOUT); + //printf(" . . . . . status = %d\n", status); + // if status goto end + + // Read the current motor position + status = pC_->readReg32(axisNo_, POS_RD_UPR, &read_val, DEFAULT_CONTROLLER_TIMEOUT); + //printf("ANF2Axis::poll: Motor position raw: %d\n", read_val); + position = (double) read_val; + setDoubleParam(pC_->motorPosition_, position); + //printf("ANF2Axis::poll: Motor #%i position: %f\n", axisNo_, position); + + // Read encoder position + status = pC_->readReg32(axisNo_, EN_POS_UPR, &read_val, DEFAULT_CONTROLLER_TIMEOUT); + //printf("ANF2Axis::poll: Motor encoder position raw: %d\n", read_val); + encPosition = (double) read_val; + setDoubleParam(pC_->motorEncoderPosition_, encPosition); + //printf("ANF2Axis::poll: Motor #%i encoder position: %f\n", axisNo_, encPosition); + + // Read the moving status of this motor + // + status = pC_->readReg16(axisNo_, STATUS_1, &read_val, DEFAULT_CONTROLLER_TIMEOUT); + //printf("status 1 is 0x%X\n", read_val); + + // Done logic + done = ((read_val & 0x8) >> 3); // status word 1 bit 3 set to 1 when the motor is not in motion. + setIntegerParam(pC_->motorStatusDone_, done); + *moving = done ? false:true; + //printf("done is %d\n", done); + + // Initialize the direction bit to the last value + status = pC_->getIntegerParam(pC_->motorStatusDirection_, &direction); + + // Direction (only set the direction of the controller is moving) + if (!done) { + if (read_val & 0x1) { + direction = 1; + } + if ((read_val & 0x2) >> 1) { + direction = 0; + } + setIntegerParam(pC_->motorStatusDirection_, direction); + } + + // Check for command errors + cmdError = (read_val & 0x1000) ? 1 : 0; + + // Check for enable/disable (not actually the torque status) and set accordingly. + // Enable/disable is determined by the configuration and it isn't obvious why one would disable an axis. + enabled = (read_val & 0x4000); + if (enabled) + setIntegerParam(pC_->motorStatusPowerOn_, 1); + else + setIntegerParam(pC_->motorStatusPowerOn_, 0); + + // Read the limit status + // + status = pC_->readReg16(axisNo_, STATUS_2, &read_val, DEFAULT_CONTROLLER_TIMEOUT); + //printf("status 2 is 0x%X\n", read_val); + + // Set the high limit only when moving in the positive direction + highLimit = (read_val & 0x8) ? (direction & 1) : 0; // a cw limit has been reached + setIntegerParam(pC_->motorStatusHighLimit_, highLimit); + //printf("+limit %d\n", highLimit); + + // Set the low limit only when moving in the negative direction + lowLimit = (read_val & 0x10) ? (!direction & 1) : 0; // a ccw limit has been reached + setIntegerParam(pC_->motorStatusLowLimit_, lowLimit); + //printf("-limit %d\n", lowLimit); + + // Clear command errors so we can attempt to move again + if (cmdError) { + printf("poll: resetting errors\n"); + resetErrors(); + } + + // Should be in init routine? Allows CNEN to be used. + setIntegerParam(pC_->motorStatusGainSupport_, 1); + + // Notify asynMotorController polling routine that we're ready + callParamCallbacks(); + + return status; +} + +/** Code for iocsh registration */ + +/* ANF2CreateController */ +static const iocshArg ANF2CreateControllerArg0 = {"Port name", iocshArgString}; +static const iocshArg ANF2CreateControllerArg1 = {"ANF2 In port name", iocshArgString}; +static const iocshArg ANF2CreateControllerArg2 = {"ANF2 Out port name", iocshArgString}; +static const iocshArg ANF2CreateControllerArg3 = {"Number of axes", iocshArgInt}; +static const iocshArg * const ANF2CreateControllerArgs[] = {&ANF2CreateControllerArg0, + &ANF2CreateControllerArg1, + &ANF2CreateControllerArg2, + &ANF2CreateControllerArg3}; +static const iocshFuncDef ANF2CreateControllerDef = {"ANF2CreateController", 4, ANF2CreateControllerArgs}; +static void ANF2CreateControllerCallFunc(const iocshArgBuf *args) +{ + ANF2CreateController(args[0].sval, args[1].sval, args[2].sval, args[3].ival); +} + +/* ANF2StartPoller */ +static const iocshArg ANF2StartPollerArg0 = {"Port name", iocshArgString}; +static const iocshArg ANF2StartPollerArg1 = {"Moving poll period (ms)", iocshArgInt}; +static const iocshArg ANF2StartPollerArg2 = {"Idle poll period (ms)", iocshArgInt}; +static const iocshArg * const ANF2StartPollerArgs[] = {&ANF2StartPollerArg0, + &ANF2StartPollerArg1, + &ANF2StartPollerArg2}; +static const iocshFuncDef ANF2StartPollerDef = {"ANF2StartPoller", 3, ANF2StartPollerArgs}; +static void ANF2StartPollerCallFunc(const iocshArgBuf *args) +{ + ANF2StartPoller(args[0].sval, args[1].ival, args[2].ival); +} + +/* ANF2CreateAxis */ +static const iocshArg ANF2CreateAxisArg0 = {"Port name", iocshArgString}; +static const iocshArg ANF2CreateAxisArg1 = {"Axis number", iocshArgInt}; +static const iocshArg ANF2CreateAxisArg2 = {"Hex config", iocshArgString}; +static const iocshArg ANF2CreateAxisArg3 = {"Base speed", iocshArgInt}; +static const iocshArg ANF2CreateAxisArg4 = {"Homing timeout", iocshArgInt}; +static const iocshArg * const ANF2CreateAxisArgs[] = {&ANF2CreateAxisArg0, + &ANF2CreateAxisArg1, + &ANF2CreateAxisArg2, + &ANF2CreateAxisArg3, + &ANF2CreateAxisArg4}; +static const iocshFuncDef ANF2CreateAxisDef = {"ANF2CreateAxis", 5, ANF2CreateAxisArgs}; +static void ANF2CreateAxisCallFunc(const iocshArgBuf *args) +{ + ANF2CreateAxis(args[0].sval, args[1].ival, args[2].sval, args[3].ival, args[4].ival); +} + + +static void ANF2Register(void) +{ + iocshRegister(&ANF2CreateControllerDef, ANF2CreateControllerCallFunc); + iocshRegister(&ANF2StartPollerDef, ANF2StartPollerCallFunc); + iocshRegister(&ANF2CreateAxisDef, ANF2CreateAxisCallFunc); +} + +extern "C" { +epicsExportRegistrar(ANF2Register); +} diff --git a/motorApp/AMCISrc/ANF2Driver.h b/motorApp/AMCISrc/ANF2Driver.h new file mode 100644 index 0000000..97e7d84 --- /dev/null +++ b/motorApp/AMCISrc/ANF2Driver.h @@ -0,0 +1,151 @@ +/* +FILENAME... ANF2Driver.h +USAGE... Motor driver support for the AMCI ANF2 controller. + +Kevin Peterson + +Based on the AMCI ANG1 Model 3 device driver written by Kurt Goetze + +*/ + +#include "asynMotorController.h" +#include "asynMotorAxis.h" +//#include +#include + +#define MAX_AXES 12 + +#define MAX_INPUT_REGS 10 +#define MAX_OUTPUT_REGS 10 + +#define AXIS_REG_OFFSET 10 + +/*** Input CMD Registers (16-bit) ***/ +#define STATUS_1 0 +#define STATUS_2 1 +#define POS_RD_UPR 2 +#define POS_RD_LWR 3 +#define EN_POS_UPR 4 +#define EN_POS_LWR 5 +#define EN_CAP_UPR 6 +#define EN_CAP_LWR 7 +// Not used must equal zero #define RESERVED 8 +#define NET_CONN 9 + +/*** Output Command Registers (32-bit) ***/ +#define COMMAND 0 +#define POSITION 1 +#define SPEED 2 +#define ACCEL_DECEL 3 +#define CMD_REG_4 4 + +/*** Output Configuration Registers (32-bit) ***/ +#define CONFIGURATION 0 +#define BASE_SPEED 1 +#define HOME_TIMEOUT 2 +#define CONFIG_REG_3 3 +#define CONFIG_REG_4 4 + +// No. of controller-specific parameters +#define NUM_ANF2_PARAMS 2 + +/** drvInfo strings for extra parameters that the ACR controller supports */ +#define ANF2ResetErrorsString "ANF2_RESET_ERRORS" +#define ANF2GetInfoString "ANF2_GET_INFO" +//#define ANF2ReconfigString "ANF2_RECONFIG" + +class ANF2Axis : public asynMotorAxis +{ +public: + /* These are the methods we override from the base class */ + ANF2Axis(class ANF2Controller *pC, int axisNo, epicsInt32 config, epicsInt32 baseSpeed, epicsInt32 homingTimeout); + void report(FILE *fp, int level); + asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration); + asynStatus moveVelocity(double min_velocity, double max_velocity, double acceleration); + asynStatus home(double min_velocity, double max_velocity, double acceleration, int forwards); + asynStatus stop(double acceleration); + asynStatus poll(bool *moving); + asynStatus setPosition(double position); + asynStatus setClosedLoop(bool closedLoop); + +private: + ANF2Controller *pC_; /**< Pointer to the asynMotorController to which this axis belongs. + * Abbreviated because it is used very frequently */ + asynStatus sendAccelAndVelocity(double accel, double velocity); + double correctAccel(double minVelocity, double maxVelocity, double acceleration); + asynStatus resetErrors(); + void getInfo(); + epicsInt32 inputReg_[10]; + //void reconfig(epicsInt32 value); + void zeroRegisters(epicsInt32 *reg); + asynUser *pasynUserForceRead_; + int axisNo_; + epicsInt32 baseSpeed_; + epicsInt32 homingTimeout_; + epicsInt32 config_; + epicsInt32 motionReg_[5]; + epicsInt32 confReg_[5]; + epicsInt32 zeroReg_[5]; + bool jogging_; + // Configuration bits + short CaptInput_; + short ExtInput_; + short HomeInput_; + short CWInput_; + short CCWInput_; + short BHPO_; + short QuadEnc_; + short DiagFbk_; + short OutPulse_; + short HomeOp_; + short CardAxis_; + short OpMode_; + // LSW + short CaptInputAS_; + short ExtInputAS_; + short HomeInputAS_; + short CWInputAS_; + short CCWInputAS_; + +friend class ANF2Controller; +}; + +class ANF2Controller : public asynMotorController { +public: + ANF2Controller(const char *portName, const char *ANF2InPortName, const char *ANF2OutPortName, int numAxes); + void doStartPoller(double movingPollPeriod, double idlePollPeriod); + + void report(FILE *fp, int level); + ANF2Axis* getAxis(asynUser *pasynUser); + ANF2Axis* getAxis(int axisNo); + asynUser *pasynUserInReg_[MAX_AXES][MAX_INPUT_REGS]; + asynUser *pasynUserOutReg_[MAX_AXES]; + + /* These are the methods that we override from asynMotorDriver */ + asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); + //asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value); + //void report(FILE *fp, int level); + + /* These are the methods that are new to this class */ + +protected: + int ANF2ResetErrors_; /** Reset Errors parameter index */ + int ANF2GetInfo_; /**< Get Info parameter index */ + //int ANF2Reconfig_; /**< Reconfig parameter index */ + +private: + asynStatus writeReg16(int, int, int, double); + asynStatus writeReg32(int, int, int, double); + asynStatus writeReg32Array(int, epicsInt32*, int, double); + asynStatus readReg16(int, int, epicsInt32*, double); + asynStatus readReg32(int, int, epicsInt32*, double); + char *inputDriver_; + int numAxes_; + int numModules_; + int axesPerModule_; + double movingPollPeriod_; + double idlePollPeriod_; + int axesCreated_; + +friend class ANF2Axis; +}; diff --git a/motorApp/AMCISrc/ANF2Support.dbd b/motorApp/AMCISrc/ANF2Support.dbd new file mode 100644 index 0000000..7367820 --- /dev/null +++ b/motorApp/AMCISrc/ANF2Support.dbd @@ -0,0 +1,2 @@ +#registrar(ANF2MotorRegister) +registrar(ANF2Register) diff --git a/motorApp/AMCISrc/ANG1Driver.cpp b/motorApp/AMCISrc/ANG1Driver.cpp new file mode 100644 index 0000000..9b16ed9 --- /dev/null +++ b/motorApp/AMCISrc/ANG1Driver.cpp @@ -0,0 +1,640 @@ +/* +FILENAME... ANG1Driver.cpp +USAGE... Motor record driver support for the AMCI ANG1 stepper motor controller over Modbus/TCP. + +Kurt Goetze + +Based on the ACS MCB-4B Model 3 device driver written by Mark Rivers + +*/ + + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "ANG1Driver.h" +#include + +#define NINT(f) (int)((f)>0 ? (f)+0.5 : (f)-0.5) + +static const char *driverName = "ANG1MotorDriver"; + +/*** Input Registers ***/ +#define STATUS_1 0 +#define STATUS_2 1 +#define POS_RD_UPR 2 +#define POS_RD_LWR 3 +#define EN_POS_UPR 4 +#define EN_POS_LWR 5 +#define EN_CAP_UPR 6 +#define EN_CAP_LWR 7 +#define MOT_CUR 8 // programmed motor current (x10) +#define JERK_RD 9 + +/*** Output Registers ***/ +#define CMD_MSW 0 // module 0 starts at register address 1024. This is set in drvModbusAsynConfigure. +#define CMD_LSW 1 +#define POS_WR_UPR 2 +#define POS_WR_LWR 3 +#define SPD_UPR 4 +#define SPD_LWR 5 +#define ACCEL 6 +#define DECEL 7 +// Not used must equal zero #define RESERVED 8 +#define JERK 9 + +/** Constructor, Creates a new ANG1Controller object. + * \param[in] portName The name of the asyn port that will be created for this driver + * \param[in] ANG1InPortName The name of the drvAsynSerialPort that was created previously to connect to the ANG1 controller + * \param[in] ANG1OutPortName The name of the drvAsynSerialPort that was created previously to connect to the ANG1 controller + * \param[in] numAxes The number of axes that this controller supports + * \param[in] movingPollPeriod The time between polls when any axis is moving + * \param[in] idlePollPeriod The time between polls when no axis is moving + */ +ANG1Controller::ANG1Controller(const char *portName, const char *ANG1InPortName, const char *ANG1OutPortName, int numAxes, + double movingPollPeriod, double idlePollPeriod) + : asynMotorController(portName, numAxes, NUM_ANG1_PARAMS, + 0, // No additional interfaces beyond those in base class + 0, // No additional callback interfaces beyond those in base class + ASYN_CANBLOCK | ASYN_MULTIDEVICE, + 1, // autoconnect + 0, 0) // Default priority and stack size +{ + int axis, i; + asynStatus status; + ANG1Axis *pAxis; + static const char *functionName = "ANG1Controller::ANG1Controller"; + + inputDriver_ = epicsStrDup(ANG1InPortName); // Set this before calls to create Axis objects + + // Create controller-specific parameters + createParam(ANG1JerkString, asynParamInt32, &ANG1Jerk_); + + /* Connect to ANG1 controller */ + for (i=0; iconnect(ANG1InPortName, i, &pasynUserInReg_[i], NULL); + } + for (i=0; iconnect(ANG1OutPortName, i, &pasynUserOutReg_[i], NULL); + } + if (status) { + asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, + "%s: cannot connect to ANG1 controller\n", + functionName); + } + for (axis=0; axis 0 then information is printed about each axis. + * After printing controller-specific information it calls asynMotorController::report() + */ +void ANG1Controller::report(FILE *fp, int level) +{ + fprintf(fp, "ANG1 motor driver %s, numAxes=%d, moving poll period=%f, idle poll period=%f\n", + this->portName, numAxes_, movingPollPeriod_, idlePollPeriod_); + + // Call the base class method + asynMotorController::report(fp, level); +} + +/** Returns a pointer to an ANG1Axis object. + * Returns NULL if the axis number encoded in pasynUser is invalid. + * \param[in] pasynUser asynUser structure that encodes the axis index number. */ +ANG1Axis* ANG1Controller::getAxis(asynUser *pasynUser) +{ +// ? return static_cast(asynMotorController::getAxis(pANG1Axis methodsasynUser)); + return static_cast(asynMotorController::getAxis(pasynUser)); +} + +/** Returns a pointer to an ANG1Axis object. + * Returns NULL if the axis number encoded in pasynUser is invalid. + * \param[in] No Axis index number. */ +ANG1Axis* ANG1Controller::getAxis(int axisNo) +{ + return static_cast(asynMotorController::getAxis(axisNo)); +} + +/** Called when asyn clients call pasynInt32->write(). + * Extracts the function and axis number from pasynUser. + * Sets the value in the parameter library (?) + * If the function is ANG1Jerk_ it sets the jerk value in the controller. + * Calls any registered callbacks for this pasynUser->reason and address. + * For all other functions it calls asynMotorController::writeInt32. + * \param[in] pasynUser asynUser structure that encodes the reason and address. + * \param[in] value Value to write. */ +asynStatus ANG1Controller::writeInt32(asynUser *pasynUser, epicsInt32 value) +{ + int function = pasynUser->reason; + asynStatus status = asynSuccess; + ANG1Axis *pAxis = getAxis(pasynUser); + static const char *functionName = "writeInt32"; + + /* Set the parameter and readback in the parameter library. */ + status = setIntegerParam(pAxis->axisNo_, function, value); + + if (function == ANG1Jerk_) + { + // Jerk in units steps/sec/sec/sec (0 - 5000) + printf("Jerk = %d\n", value); + status = writeReg16(JERK, value, DEFAULT_CONTROLLER_TIMEOUT); + +// sprintf(outString_, "%s JOG JRK %f", pAxis->axisName_, value); +// status = writeController(); + + } else { + /* Call base class method */ + status = asynMotorController::writeInt32(pasynUser, value); + } + + /* Do callbacks so higher layers see any changes */ + pAxis->callParamCallbacks(); + if (status) + asynPrint(pasynUser, ASYN_TRACE_ERROR, + "%s:%s: error, status=%d function=%d, value=%d\n", + driverName, functionName, status, function, value); + else + asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, + "%s:%s: function=%d, value=%d\n", + driverName, functionName, function, value); + return status; +} + +asynStatus ANG1Controller::writeReg16(int reg, int output, double timeout) +{ + asynStatus status; + + //printf("writeReg16: writing %d to register %d\n", output, reg); + asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,"writeReg16: writing %d to register %d\n", output, reg); + status = pasynInt32SyncIO->write(pasynUserOutReg_[reg], output, timeout); + epicsThreadSleep(0.01); + + return status ; +} + +asynStatus ANG1Controller::writeReg32(int reg, int output, double timeout) +{ +//.. break 32-bit integer into 2 pieces +//.. write the pieces into ANG1 registers + + asynStatus status; + float fnum; + int lower,upper; + + fnum = (output / 1000.0); + upper = (int)fnum; + fnum = fnum - upper; + fnum = NINT(fnum * 1000); + lower = (int)fnum; + +//could write the words this way +// status = pasynInt32SyncIO->write(pasynUserOutReg_[reg], upper, timeout); +// status = pasynInt32SyncIO->write(pasynUserOutReg_[reg+1], lower, timeout); + +//or this way +// writeReg16(piece1 ie MSW ... + status = writeReg16(reg, upper, DEFAULT_CONTROLLER_TIMEOUT); + +// writeReg16(piece2 ie LSW ... + reg++; + status = writeReg16(reg, lower, DEFAULT_CONTROLLER_TIMEOUT); + + return status ; +} + +asynStatus ANG1Controller::readReg16(int reg, epicsInt32 *input, double timeout) +{ + asynStatus status; + + //printf("reg = %d\n", reg); + asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,"readReg16 reg = %d\n", reg); + status = pasynInt32SyncIO->read(pasynUserInReg_[reg], input, timeout); + + return status ; +} + +asynStatus ANG1Controller::readReg32(int reg, epicsInt32 *combo, double timeout) +{ +//.. read 2 16-bit words from ANG1 registers +//.. assemble 2 16-bit pieces into 1 32-bit integer + + asynStatus status; +// float fnum; + epicsInt32 lowerWord32, upperWord32; // only have pasynInt32SyncIO, not pasynInt16SyncIO , + epicsInt16 lowerWord16, upperWord16; // so we need to get 32-bits and cast to 16-bit integer + + //printf("calling readReg16\n"); + status = readReg16(reg, &upperWord32, timeout); //get Upper Word + upperWord16 = (epicsInt16)upperWord32; + //printf("upperWord16: %d\n", upperWord16); + asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,"readReg32 upperWord16: %d\n", upperWord16); + + // if status != 1 : + reg++; + status = readReg16(reg, &lowerWord32, timeout); //get Lower Word + lowerWord16 = (epicsInt16)lowerWord32; + //printf("lowerWord16: %d\n", lowerWord16); + asynPrint(this->pasynUserSelf, ASYN_TRACEIO_DRIVER,"readReg32 lowerWord16: %d\n", lowerWord16); + + *combo = NINT((upperWord16 * 1000) + lowerWord16); + + return status ; +} + + +// ANG1Axis methods Here +// These are the ANG1Axis methods + +/** Creates a new ANG1Axis object. + * \param[in] pC Pointer to the ANG1Controller to which this axis belongs. + * \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1. + * + * Initializes register numbers, etc. + */ +ANG1Axis::ANG1Axis(ANG1Controller *pC, int axisNo) + : asynMotorAxis(pC, axisNo), + pC_(pC) +{ + int status; + + //status = pasynInt32SyncIO->connect(myModbusInputDriver, 0, &pasynUserForceRead_, "MODBUS_READ"); + status = pasynInt32SyncIO->connect(pC_->inputDriver_, 0, &pasynUserForceRead_, "MODBUS_READ"); + if (status) { + //printf("%s:%s: Error, unable to connect pasynUserForceRead_ to Modbus input driver %s\n", pC_->inputDriver_, pC_->functionName, myModbusInputDriver); + printf("%s: Error, unable to connect pasynUserForceRead_ to Modbus input driver\n", pC_->inputDriver_); + } + printf("ANG1Axis::ANG1Axis : pasynUserForceRead_->reason=%d\n", pasynUserForceRead_->reason); + + // set position to 0 + setPosition(0); +} + +/** Reports on status of the axis + * \param[in] fp The file pointer on which report information will be written + * \param[in] level The level of report detail desired + * + * After printing device-specific information calls asynMotorAxis::report() + */ +void ANG1Axis::report(FILE *fp, int level) +{ + if (level > 0) { + fprintf(fp, " axis %d\n", + axisNo_); + } + + // Call the base class method + asynMotorAxis::report(fp, level); +} + +// SET VEL & ACCEL +asynStatus ANG1Axis::sendAccelAndVelocity(double acceleration, double velocity) +{ + asynStatus status; + // static const char *functionName = "ANG1::sendAccelAndVelocity"; + + // Send the velocity in egus + //sprintf(pC_->outString_, "%1dVA%f", axisNo_ + 1, (velocity*stepSize_)); + //status = pC_->writeController(); + status = pC_->writeReg32(SPD_UPR, NINT(velocity), DEFAULT_CONTROLLER_TIMEOUT); + + // Send the acceleration in egus/sec/sec + //printf(" velocity: %f\n", velocity); + //printf(" acceleration: %f\n", acceleration); + // ANG1 acceleration range 1 to 5000 steps/ms/sec + // Therefore need to limit range received by motor record from 1000 to 5e6 steps/sec/sec + if (acceleration < 1000) { + // print message noting that accel has been capped low + acceleration = 1000; + } + if (acceleration > 5000000) { + // print message noting that accel has been capped high + acceleration = 5000000; + } + // ANG1 acceleration units are steps/millisecond/second, so we divide by 1000 here + status = pC_->writeReg16(ACCEL, NINT(acceleration/1000.0), DEFAULT_CONTROLLER_TIMEOUT); + status = pC_->writeReg16(DECEL, NINT(acceleration/1000.0), DEFAULT_CONTROLLER_TIMEOUT); + return status; +} + +// MOVE +asynStatus ANG1Axis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration) +{ + asynStatus status; + int velo, distance, move_bit; + + printf(" ** ANG1Axis::move called, relative = %d\n", relative); + + status = sendAccelAndVelocity(acceleration, maxVelocity); + + //velo = maxVelocity * SOME_SCALE_FACTOR + velo = NINT(maxVelocity); + if (relative) { + printf(" ** relative move called\n"); + //status = pC_->writeReg32(SPD_UPR, velo, DEFAULT_CONTROLLER_TIMEOUT); + //distance = position * SOM_OTHER_SCALE_FACTOR; + distance = NINT(position); + status = pC_->writeReg32(POS_WR_UPR, distance, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x0; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x2; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + } else { + // absolute + printf(" ** absolute move called\n"); + //status = pC_->writeReg32(SPD_UPR, velo, DEFAULT_CONTROLLER_TIMEOUT); + //distance = position * SOM_OTHER_SCALE_FACTOR; + distance = NINT(position); + printf(" ** distance = %d\n", distance); + status = pC_->writeReg32(POS_WR_UPR, distance, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x0; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x1; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + } + // Delay the first status read, give the controller some time to return moving status + epicsThreadSleep(0.05); + return status; +} + +// HOME (needs work) +asynStatus ANG1Axis::home(double minVelocity, double maxVelocity, double acceleration, int forwards) +{ + asynStatus status; + int home_bit; + // static const char *functionName = "ANG1Axis::home"; + + //status = sendAccelAndVelocity(acceleration, maxVelocity); + + if (forwards) { + printf(" ** HOMING FORWARDS **\n"); + home_bit = 0x20; + status = pC_->writeReg16(CMD_MSW, home_bit, DEFAULT_CONTROLLER_TIMEOUT); + } else { + home_bit = 0x40; + status = pC_->writeReg16(CMD_MSW, home_bit, DEFAULT_CONTROLLER_TIMEOUT); + } + return status; +} + +// JOG +asynStatus ANG1Axis::moveVelocity(double minVelocity, double maxVelocity, double acceleration) +{ + asynStatus status; + int velo, distance, move_bit; + static const char *functionName = "ANG1Axis::moveVelocity"; + + asynPrint(pasynUser_, ASYN_TRACE_FLOW, + "%s: minVelocity=%f, maxVelocity=%f, acceleration=%f\n", + functionName, minVelocity, maxVelocity, acceleration); + + velo = NINT(fabs(maxVelocity)); + + status = sendAccelAndVelocity(acceleration, velo); + + /* ANG1 does not have jog command. Move 1 million steps */ + if (maxVelocity > 0.) { + /* This is a positive move in ANG1 coordinates */ + //printf(" ** relative move (JOG pos) called\n"); + distance = 1000000; + status = pC_->writeReg32(POS_WR_UPR, distance, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x0; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x2; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + } else { + /* This is a negative move in ANG1 coordinates */ + //printf(" ** relative move (JOG neg) called\n"); + distance = -1000000; + status = pC_->writeReg32(POS_WR_UPR, distance, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x0; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + move_bit = 0x2; + status = pC_->writeReg16(CMD_MSW, move_bit, DEFAULT_CONTROLLER_TIMEOUT); + } + // Delay the first status read, give the controller some time to return moving status + epicsThreadSleep(0.05); + return status; +} + + +// STOP +asynStatus ANG1Axis::stop(double acceleration) +{ + asynStatus status; + int stop_bit; + //static const char *functionName = "ANG1Axis::stop"; + + printf("\n STOP \n\n"); + + stop_bit = 0x0; + status = pC_->writeReg16(CMD_MSW, stop_bit, DEFAULT_CONTROLLER_TIMEOUT); + +// stop_bit = 0x10; Immediate stop + stop_bit = 0x4; // Hold move + status = pC_->writeReg16(CMD_MSW, stop_bit, DEFAULT_CONTROLLER_TIMEOUT); + + return status; +} + +// SET +asynStatus ANG1Axis::setPosition(double position) +{ + asynStatus status; + int set_position, set_bit; + //static const char *functionName = "ANG1Axis::setPosition"; + + //status = writeReg32(SPD_UPR, velo, DEFAULT_CONTROLLER_TIMEOUT); + //distance = position * SOM_OTHER_SCALE_FACTOR; + set_position = NINT(position); + + status = pC_->writeReg32(POS_WR_UPR, set_position, DEFAULT_CONTROLLER_TIMEOUT); + + set_bit = 0x200; + status = pC_->writeReg16(CMD_MSW, set_bit, DEFAULT_CONTROLLER_TIMEOUT); + + set_bit = 0x0; + status = pC_->writeReg16(CMD_MSW, set_bit, DEFAULT_CONTROLLER_TIMEOUT); + + return status; +} + +// ENABLE TORQUE +asynStatus ANG1Axis::setClosedLoop(bool closedLoop) +{ + asynStatus status; + int enable = 0x8000; + int disable = 0x0000; + int cmd; + + printf(" ** setClosedLoop called \n"); + if (closedLoop) { + printf("setting enable %X\n", enable); + // Let's reset errors first + cmd = 0x0; + status = pC_->writeReg16(CMD_MSW, cmd, DEFAULT_CONTROLLER_TIMEOUT); + + cmd = 0x400; + status = pC_->writeReg16(CMD_MSW, cmd, DEFAULT_CONTROLLER_TIMEOUT); + + cmd = 0x0; + status = pC_->writeReg16(CMD_MSW, cmd, DEFAULT_CONTROLLER_TIMEOUT); + status = pC_->writeReg16(CMD_LSW, enable, DEFAULT_CONTROLLER_TIMEOUT); + setIntegerParam(pC_->motorStatusPowerOn_, 1); + + } else { + printf("setting disable %X\n", disable); + status = pC_->writeReg16(CMD_LSW, disable, DEFAULT_CONTROLLER_TIMEOUT); + setIntegerParam(pC_->motorStatusPowerOn_, 0); + } + + return status; +} + +// POLL +/** Polls the axis. + * This function reads motor position, limit status, home status, and moving status + * It calls setIntegerParam() and setDoubleParam() for each item that it polls, + * and then calls callParamCallbacks() at the end. + * \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false). */ +asynStatus ANG1Axis::poll(bool *moving) +{ + int done; + int limit; + int enabled; + double position; + asynStatus status; + epicsInt32 read_val; // don't use a pointer here. The _address_ of read_val should be passed to the read function. + + // Force a read operation + //printf(" . . . . . Calling pasynInt32SyncIO->write\n"); + //printf("Calling pasynInt32SyncIO->write(pasynUserForceRead_, 1, TIMEOUT), pasynUserForceRead_->reason=%d\n", pasynUserForceRead_->reason); + status = pasynInt32SyncIO->write(pasynUserForceRead_, 1, DEFAULT_CONTROLLER_TIMEOUT); + //printf(" . . . . . status = %d\n", status); + // if status goto end + + // Read the current motor position + // + //readReg32(int reg, epicsInt32 *combo, double timeout) + status = pC_->readReg32(POS_RD_UPR, &read_val, DEFAULT_CONTROLLER_TIMEOUT); + printf("ANG1Axis::poll: Motor position raw: %d\n", read_val); + position = (double) read_val; + setDoubleParam(pC_->motorPosition_, position); + printf("ANG1Axis::poll: Motor position: %f\n", position); + + // Read the moving status of this motor + // + status = pC_->readReg16(STATUS_1, &read_val, DEFAULT_CONTROLLER_TIMEOUT); + //printf("status 1 is 0x%X\n", read_val); + + // Done logic + done = ((read_val & 0x8) >> 3); // status word 1 bit 3 set to 1 when the motor is not in motion. + setIntegerParam(pC_->motorStatusDone_, done); + *moving = done ? false:true; + printf("done is %d\n", done); + + // Read the limit status + // + status = pC_->readReg16(STATUS_2, &read_val, DEFAULT_CONTROLLER_TIMEOUT); + printf("status 2 is 0x%X\n", read_val); + + limit = (read_val & 0x1); // a cw limit has been reached + setIntegerParam(pC_->motorStatusHighLimit_, limit); + //printf("+limit %d\n", limit); + if (limit) { // reset error and set position so we can move off of the limit + // Reset error + setClosedLoop(1); + // Reset position + //printf(" Reset Position\n"); + setPosition(position); + } + + limit = (read_val & 0x2); // a ccw limit has been reached + setIntegerParam(pC_->motorStatusLowLimit_, limit); + //printf("-limit %d\n", limit); + if (limit) { // reset error and set position so we can move off of the limit + // Reset error + setClosedLoop(1); + // Reset position + setPosition(position); + } + + // test for home + + // Should be in init routine? Allows CNEN to be used. + setIntegerParam(pC_->motorStatusGainSupport_, 1); + + // Check for the torque status and set accordingly. + enabled = (read_val & 0x8000); + if (enabled) + setIntegerParam(pC_->motorStatusPowerOn_, 1); + else + setIntegerParam(pC_->motorStatusPowerOn_, 0); + + // Notify asynMotorController polling routine that we're ready + callParamCallbacks(); + + return status; +} + +/** Code for iocsh registration */ +static const iocshArg ANG1CreateControllerArg0 = {"Port name", iocshArgString}; +static const iocshArg ANG1CreateControllerArg1 = {"ANG1 In port name", iocshArgString}; +static const iocshArg ANG1CreateControllerArg2 = {"ANG1 Out port name", iocshArgString}; +static const iocshArg ANG1CreateControllerArg3 = {"Number of axes", iocshArgInt}; +static const iocshArg ANG1CreateControllerArg4 = {"Moving poll period (ms)", iocshArgInt}; +static const iocshArg ANG1CreateControllerArg5 = {"Idle poll period (ms)", iocshArgInt}; +static const iocshArg * const ANG1CreateControllerArgs[] = {&ANG1CreateControllerArg0, + &ANG1CreateControllerArg1, + &ANG1CreateControllerArg2, + &ANG1CreateControllerArg3, + &ANG1CreateControllerArg4, + &ANG1CreateControllerArg5,}; +static const iocshFuncDef ANG1CreateControllerDef = {"ANG1CreateController", 6, ANG1CreateControllerArgs}; +static void ANG1CreateContollerCallFunc(const iocshArgBuf *args) +{ + ANG1CreateController(args[0].sval, args[1].sval, args[2].sval, args[3].ival, args[4].ival, args[5].ival); +} + +static void ANG1Register(void) +{ + iocshRegister(&ANG1CreateControllerDef, ANG1CreateContollerCallFunc); +} + +extern "C" { +epicsExportRegistrar(ANG1Register); +} diff --git a/motorApp/AMCISrc/ANG1Driver.h b/motorApp/AMCISrc/ANG1Driver.h new file mode 100644 index 0000000..09160f3 --- /dev/null +++ b/motorApp/AMCISrc/ANG1Driver.h @@ -0,0 +1,88 @@ +/* +FILENAME... ANG1Driver.h +USAGE... Motor driver support for the AMCI ANG1 controller. + +Based on MCB-4B driver written by +Mark Rivers +March 1, 2012 + +K. Goetze 2014-03-24 + +*/ + +#include "asynMotorController.h" +#include "asynMotorAxis.h" + +#define MAX_ANG1_AXES 1 + +#define MAX_INPUT_REGS 10 +#define MAX_OUTPUT_REGS 10 + +// No. of controller-specific parameters +#define NUM_ANG1_PARAMS 1 + +/** drvInfo strings for extra parameters that the ACR controller supports */ +#define ANG1JerkString "ANG1_JERK" +//#define ACRReadBinaryIOString "ACR_READ_BINARY_IO" +//#define ACRBinaryInString "ACR_BINARY_IN" +//#define ACRBinaryOutString "ACR_BINARY_OUT" +//#define ACRBinaryOutRBVString "ACR_BINARY_OUT_RBV" + +class ANG1Axis : public asynMotorAxis +{ +public: + /* These are the methods we override from the base class */ + ANG1Axis(class ANG1Controller *pC, int axis); + void report(FILE *fp, int level); + asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration); + asynStatus moveVelocity(double min_velocity, double max_velocity, double acceleration); + asynStatus home(double min_velocity, double max_velocity, double acceleration, int forwards); + asynStatus stop(double acceleration); + asynStatus poll(bool *moving); + asynStatus setPosition(double position); + asynStatus setClosedLoop(bool closedLoop); + +private: + ANG1Controller *pC_; /**< Pointer to the asynMotorController to which this axis belongs. + * Abbreviated because it is used very frequently */ + asynStatus sendAccelAndVelocity(double accel, double velocity); + asynUser *pasynUserForceRead_; + +friend class ANG1Controller; +}; + +class ANG1Controller : public asynMotorController { +public: + ANG1Controller(const char *portName, const char *ANG1InPortName, const char *ANG1OutPortName, int numAxes, double movingPollPeriod, double idlePollPeriod); + + void report(FILE *fp, int level); + ANG1Axis* getAxis(asynUser *pasynUser); + ANG1Axis* getAxis(int axisNo); + asynUser *pasynUserInReg_[MAX_INPUT_REGS]; + asynUser *pasynUserOutReg_[MAX_OUTPUT_REGS]; +// asynUser *pasynUserForceRead_; + + + /* These are the methods that we override from asynMotorDriver */ + asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); + //asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value); + //void report(FILE *fp, int level); + //ACRAxis* getAxis(asynUser *pasynUser); + //ACRAxis* getAxis(int axisNo); + + + /* These are the methods that are new to this class */ + +protected: + int ANG1Jerk_; /**< Jerk time parameter index */ + + +private: + asynStatus writeReg16(int, int, double); + asynStatus writeReg32(int, int, double); + asynStatus readReg16(int, epicsInt32*, double); + asynStatus readReg32(int, epicsInt32*, double); + char *inputDriver_; + +friend class ANG1Axis; +}; diff --git a/motorApp/AMCISrc/ANG1Support.dbd b/motorApp/AMCISrc/ANG1Support.dbd new file mode 100644 index 0000000..ab5549c --- /dev/null +++ b/motorApp/AMCISrc/ANG1Support.dbd @@ -0,0 +1,2 @@ +#registrar(ANG1MotorRegister) +registrar(ANG1Register) diff --git a/motorApp/AMCISrc/Makefile b/motorApp/AMCISrc/Makefile new file mode 100644 index 0000000..ac94d32 --- /dev/null +++ b/motorApp/AMCISrc/Makefile @@ -0,0 +1,30 @@ +TOP=../.. + +include $(TOP)/configure/CONFIG +#---------------------------------------- +# ADD MACRO DEFINITIONS AFTER THIS LINE +#============================= + +#================================================== +# Build an IOC support library + +LIBRARY_IOC += AMCI + +# motorRecord.h will be created from motorRecord.dbd +# install devMotorSoft.dbd into /dbd +DBD += AMCISupport.dbd +DBD += ANG1Support.dbd +DBD += ANF2Support.dbd + +# The following are compiled and added to the Support library +AMCI_SRCS += ANG1Driver.cpp +AMCI_SRCS += ANF2Driver.cpp + +AMCI_LIBS += motor +AMCI_LIBS += asyn +AMCI_LIBS += $(EPICS_BASE_IOC_LIBS) + +include $(TOP)/configure/RULES +#---------------------------------------- +# ADD RULES AFTER THIS LINE + diff --git a/motorApp/AMCISrc/README b/motorApp/AMCISrc/README new file mode 100644 index 0000000..57dc499 --- /dev/null +++ b/motorApp/AMCISrc/README @@ -0,0 +1,49 @@ +AMCI ANG1 +========= + +Asyn model 3 driver support for the AMCI ANG1 stepper motor +controller/driver. + +Modbus/TCP communication, using Mark Rivers' modbus module + +Currently some basic parameters, such as IP address, motor current, +etc., will need to be set up on the controller using AMCI's PC/Win software. +Limits and Home also need to be configured with this software: * + + Limit -> ANG1 Input 1 + - Limit -> ANG1 Input 2 + Home -> ANG1 Input 3 + +ANG1 configuration software is available from AMCI's website: + +www.amci.com/product-software.asp + +Eventually I would like to implement the "Configuration Mode" options +down in the driver, making the AMCI PC software necessary only for +initial comms (IP) setup. + +The ANG1 controller/driver is available with or without an ethernet +port. A group of controller/drivers can contain up to 6 modules, one of +which needs to have the ethernet option. A single-channel +implementation would need the module with ethernet. This software is +intended to support configurations of multiple groups of 1 to 6 modules. +Again, each group will need 1 ethernet enabled module (ANG1-E). + + + +asyn model 3 driver files: +-------------------------- +ANG1Driver.cpp +ANG1Driver.h +ANG1Support.dbd + + +* Note: 1.) At some point I would like to add the capability to set these + parameters at boot-time, using the ANG1 "configuration mode". + + 2.) VBAS can only be set in configuration mode (which is not + currently supported) or by using the PC configuration software. + To use VBAS, set the desired value for the axis using the AMCI + PC configuration interface, then set the VBAS field in the + motor record accordingly. That way this value will be used by + the record to correctly calculate acceleration. + diff --git a/motorApp/AMCISrc/README_ANF2.md b/motorApp/AMCISrc/README_ANF2.md new file mode 100644 index 0000000..f72ca19 --- /dev/null +++ b/motorApp/AMCISrc/README_ANF2.md @@ -0,0 +1,70 @@ +# AMCI ANF2 + +Asyn model 3 driver support for the AMCI ANF2 stepper motor controller + +Modbus/TCP communication, using Mark Rivers' modbus module + +## Supported Controller Models + +The following ANF controller versions are supported: +``` +ANF1E: 1-axis stepper controller, modbus tcp/ip +ANF1: 1-axis stepper controller, no network interface +ANF2E: 2-axis stepper controller, modbus tcp/ip +ANF2: 2-axis stepper controller, no network interface +``` +A stack of controller can contain up to 6 modules, one of +which needs to have the ethernet option. A single-channel +implementation would need the module with ethernet. + +## Vendor Software + +ANF2 configuration software is available from AMCI's website: + +www.amci.com/product-software.asp + +Note: The AMCI Net Configurator only works (allows a motor to be moved) if +the controller is configured for EtherNet/IP, however, the EPICS support +requires the device to be configured for Modbus-TCP. + +## Controller Quirks + +* The controller doesn't allow absolute moves when a limit is active; +The only way to move a motor off of a limit is by **jogging**. + +* The base speed is set when an axis is configured. This driver corrects +the acceleration sent by the motor record (VBAS isn't guaranteed to match +the base speed) and sends the acceleration necessary to achieve the desired +acceleration time. + +* The controller doesn't remember its configuration after it is power-cycled. + +* Sending the configuration to the controller invalidates the position +requiring either a home search or the redefinition of the current position. + +* The configuration can't be read after a configuration is accepted by the +controller, after which it automatically switches into command mode. + +* The command to stop an abosolute move generates an error if a jog is in +progress. The command to stop a jog doesn't stop an absolute move. + +## Controller Configuration + +The AMCI Net Configurator can be used to: + +* Change the ip address from the default (192.168.0.50) + +* Change the protocol to Modbus-TCP + +* Determine hex config strings for each axis + +### Example axis configuration + +``` +0x86000000 - Step & Direction pulses, Diagnostic Feedback, No home switch, No limits +0x86280000 - Step & Direction pulses, Diagnostic Feedback, No home switch, Active-low CW/CCW limits +0x84000000 - Step & Direction pulses, No Feedback, No home switch, No Limits +0x84280000 - Step & Direction pulses, No Feedback, No home switch, Active-low CW/CCW limits +0x842C0004 - Step & Direction pulses, No Feedback, Active-high home switch, Active-low CW/CCW limits +0x85280000 - Step & Direction pulses, Quadrature Feedback, No home switch, Active-low CW/CCW limits +``` diff --git a/motorApp/AcsSrc/AcsRegister.cc b/motorApp/AcsSrc/AcsRegister.cc index 5e594ea..384d5fb 100644 --- a/motorApp/AcsSrc/AcsRegister.cc +++ b/motorApp/AcsSrc/AcsRegister.cc @@ -2,9 +2,6 @@ FILENAME... AcsRegister.cc USAGE... Register ACS motor device driver shell commands. -Version: $Revision: 1.4 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2004-07-16 19:06:58 $ */ /***************************************************************** diff --git a/motorApp/AcsSrc/AcsRegister.h b/motorApp/AcsSrc/AcsRegister.h index c4ceab1..00e0480 100644 --- a/motorApp/AcsSrc/AcsRegister.h +++ b/motorApp/AcsSrc/AcsRegister.h @@ -2,9 +2,6 @@ FILENAME... AcsRegister.h USAGE... This file contains function prototypes for ACS IOC shell commands. -Version: $Revision: 1.3 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2004-07-16 19:06:58 $ */ /* diff --git a/motorApp/AcsSrc/devMCB4B.cc b/motorApp/AcsSrc/devMCB4B.cc index d4a394e..73e43d1 100644 --- a/motorApp/AcsSrc/devMCB4B.cc +++ b/motorApp/AcsSrc/devMCB4B.cc @@ -52,7 +52,7 @@ static inline void Debug(int level, const char *format, ...) { /* ----------------Create the dsets for devMCB4B----------------- */ STATIC struct driver_table *drvtabptr; -STATIC long MCB4B_init(void *); +STATIC long MCB4B_init(int); STATIC long MCB4B_init_record(void *); STATIC long MCB4B_start_trans(struct motorRecord *); STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -105,13 +105,12 @@ static struct board_stat **MCB4B_cards; /* initialize device support for MCB4B stepper motor */ -STATIC long MCB4B_init(void *arg) +STATIC long MCB4B_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; Debug(5, "MCB4B_init: entry\n"); - if (after == 0) + if (!after) { drvtabptr = &MCB4B_access; (drvtabptr->init)(); diff --git a/motorApp/AcsSrc/drvMCB4B.cc b/motorApp/AcsSrc/drvMCB4B.cc index ea18292..d888947 100644 --- a/motorApp/AcsSrc/drvMCB4B.cc +++ b/motorApp/AcsSrc/drvMCB4B.cc @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include "motor.h" #include "AcsRegister.h" #include "drvMCB4B.h" @@ -262,7 +264,7 @@ STATIC int set_status(int card, int signal) /* Test for post-move string. */ if ((status.Bits.RA_DONE || ls_active == true) && nodeptr != 0 && nodeptr->postmsgptr != 0) { - send_mess(card, nodeptr->postmsgptr, (char) NULL); + send_mess(card, nodeptr->postmsgptr, (char*) NULL); /* The MCB4B always sends back a response, read it and discard */ recv_mess(card, buff, WAIT); nodeptr->postmsgptr = NULL; diff --git a/motorApp/AcsTech80Src/ACSTech80Register.cc b/motorApp/AcsTech80Src/ACSTech80Register.cc index c40e553..e83788f 100644 --- a/motorApp/AcsTech80Src/ACSTech80Register.cc +++ b/motorApp/AcsTech80Src/ACSTech80Register.cc @@ -2,9 +2,6 @@ FILENAME... ACSTech80Register.cc USAGE... Register ACS Tech80 motor device driver shell commands. -Version: $Revision: 1.2 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2008-05-21 21:18:52 $ */ /***************************************************************** diff --git a/motorApp/AcsTech80Src/devSPiiPlus.cc b/motorApp/AcsTech80Src/devSPiiPlus.cc index cf90438..569acba 100644 --- a/motorApp/AcsTech80Src/devSPiiPlus.cc +++ b/motorApp/AcsTech80Src/devSPiiPlus.cc @@ -2,9 +2,6 @@ FILENAME... devSPiiPlus.cc USAGE... Motor record device level support for ACS Tech80 SPiiPlus -Version: $Revision: 1.3 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2008-05-21 21:18:52 $ */ /* @@ -40,6 +37,7 @@ Last Modified: $Date: 2008-05-21 21:18:52 $ #include #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -52,7 +50,7 @@ extern struct driver_table SPiiPlus_access; /* ----------------Create the dsets for devSPiiPlus----------------- */ STATIC struct driver_table *drvtabptr; -STATIC long SPiiPlus_init(void *); +STATIC long SPiiPlus_init(int); STATIC long SPiiPlus_init_record(void *); STATIC long SPiiPlus_start_trans(struct motorRecord *); STATIC RTN_STATUS SPiiPlus_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -106,12 +104,11 @@ static struct board_stat **SPiiPlus_cards; /* initialize device support for SPiiPlus stepper motor */ -STATIC long SPiiPlus_init(void *arg) +STATIC long SPiiPlus_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &SPiiPlus_access; (drvtabptr->init)(); diff --git a/motorApp/AcsTech80Src/drvSPiiPlus.cc b/motorApp/AcsTech80Src/drvSPiiPlus.cc index d4d1f86..f944cc9 100644 --- a/motorApp/AcsTech80Src/drvSPiiPlus.cc +++ b/motorApp/AcsTech80Src/drvSPiiPlus.cc @@ -3,10 +3,6 @@ FILENAME... drvSPiiPlus.cc USAGE... Motor record driver level support for ACS Tech80 SPiiPlus -Version: $Revision: 14155 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/AcsTech80Src/drvSPiiPlus.cc $ */ @@ -51,6 +47,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#include +#include #include "motor.h" #include "ACSTech80Register.h" #include "drvSPiiPlus.h" @@ -406,7 +404,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strncpy(send_buff, nodeptr->postmsgptr, 80); - send_mess(card, send_buff, (char) NULL); + send_mess(card, send_buff, (char*) NULL); nodeptr->postmsgptr = NULL; } diff --git a/motorApp/AcsTech80Src/drvSPiiPlus.h b/motorApp/AcsTech80Src/drvSPiiPlus.h index 80dae1c..b91ec86 100644 --- a/motorApp/AcsTech80Src/drvSPiiPlus.h +++ b/motorApp/AcsTech80Src/drvSPiiPlus.h @@ -3,9 +3,6 @@ FILENAME... drvSPiiPlus.h USAGE... This file contains ACS Tech80 driver "include" information that is specific to the SPiiPlus serial controller -Version: $Revision: 1.2 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2008-05-21 21:18:53 $ */ diff --git a/motorApp/AerotechSrc/AerotechRegister.cc b/motorApp/AerotechSrc/AerotechRegister.cc index 9a71904..60cc6be 100644 --- a/motorApp/AerotechSrc/AerotechRegister.cc +++ b/motorApp/AerotechSrc/AerotechRegister.cc @@ -2,10 +2,6 @@ FILENAME... AerotechRegister.cc USAGE... Register Aerotech motor device driver shell commands. -Version: $Revision: 17434 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2014-05-21 11:43:51 -0500 (Wed, 21 May 2014) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/AerotechSrc/AerotechRegister.cc $ */ /***************************************************************** @@ -49,40 +45,24 @@ static const iocshArg ensembleAsynConfigArg2 = {"asyn address (GPIB)", iocshArgI static const iocshArg ensembleAsynConfigArg3 = {"Number of Axes", iocshArgInt}; static const iocshArg ensembleAsynConfigArg4 = {"Moving poll rate", iocshArgInt}; static const iocshArg ensembleAsynConfigArg5 = {"Idle poll rate", iocshArgInt}; +static const iocshArg a3200AsynConfigArg6 = {"Task number", iocshArgInt}; +static const iocshArg a3200AsynConfigArg7 = {"Linear move commands", iocshArgInt}; -// A3200 Asyn Setup arguments -static const iocshArg a3200AsynSetupArg0 = {"Max. controller count", iocshArgInt}; -// A3200 Asyn Config arguments -static const iocshArg a3200AsynConfigArg0 = {"Card being configured", iocshArgInt}; -static const iocshArg a3200AsynConfigArg1 = {"asyn port name", iocshArgString}; -static const iocshArg a3200AsynConfigArg2 = {"asyn address", iocshArgInt}; -static const iocshArg a3200AsynConfigArg3 = {"Number of Axes", iocshArgInt}; -static const iocshArg a3200AsynConfigArg4 = {"Task number", iocshArgInt}; -static const iocshArg a3200AsynConfigArg5 = {"Moving poll rate", iocshArgInt}; -static const iocshArg a3200AsynConfigArg6 = {"Idle poll rate", iocshArgInt}; - -static const iocshArg * const EnsembleAsynSetupArgs[2] = {&ensembleAsynSetupArg0}; -static const iocshArg * const EnsembleAsynConfigArgs[6] = {&ensembleAsynConfigArg0, +static const iocshArg * const EnsembleAsynSetupArgs[1] = {&ensembleAsynSetupArg0}; +static const iocshArg * const EnsembleAsynConfigArgs[8] = {&ensembleAsynConfigArg0, &ensembleAsynConfigArg1, &ensembleAsynConfigArg2, &ensembleAsynConfigArg3, &ensembleAsynConfigArg4, - &ensembleAsynConfigArg5}; + &ensembleAsynConfigArg5, + &a3200AsynConfigArg6, + &a3200AsynConfigArg7}; static const iocshFuncDef setupEnsembleAsyn = {"EnsembleAsynSetup", 1, EnsembleAsynSetupArgs}; static const iocshFuncDef configEnsembleAsyn = {"EnsembleAsynConfig", 6, EnsembleAsynConfigArgs}; -static const iocshArg * const A3200AsynSetupArgs[2] = {&a3200AsynSetupArg0}; -static const iocshArg * const A3200AsynConfigArgs[7] = {&a3200AsynConfigArg0, - &a3200AsynConfigArg1, - &a3200AsynConfigArg2, - &a3200AsynConfigArg3, - &a3200AsynConfigArg4, - &a3200AsynConfigArg5, - &a3200AsynConfigArg6}; - -static const iocshFuncDef setupA3200Asyn = {"A3200AsynSetup", 1, A3200AsynSetupArgs}; -static const iocshFuncDef configA3200Asyn = {"A3200AsynConfig", 7, A3200AsynConfigArgs}; +static const iocshFuncDef setupA3200Asyn = {"A3200AsynSetup", 1, EnsembleAsynSetupArgs}; +static const iocshFuncDef configA3200Asyn = {"A3200AsynConfig", 8, EnsembleAsynConfigArgs}; static void setupSoloistCallFunc(const iocshArgBuf *args) { @@ -99,8 +79,7 @@ static void setupEnsembleAsynCallFunc(const iocshArgBuf *args) } static void configEnsembleAsynCallFunc(const iocshArgBuf *args) { - EnsembleAsynConfig(args[0].ival, args[1].sval, args[2].ival, - args[3].ival, args[4].ival, args[5].ival); + EnsembleAsynConfig(args[0].ival, args[1].sval, args[2].ival, args[3].ival, args[4].ival, args[5].ival); } static void setupA3200AsynCallFunc(const iocshArgBuf *args) @@ -109,8 +88,7 @@ static void setupA3200AsynCallFunc(const iocshArgBuf *args) } static void configA3200AsynCallFunc(const iocshArgBuf *args) { - A3200AsynConfig(args[0].ival, args[1].sval, args[2].ival, - args[3].ival, args[4].ival, args[5].ival, args[6].ival); + A3200AsynConfig(args[0].ival, args[1].sval, args[2].ival, args[3].ival, args[4].ival, args[5].ival, args[6].ival, args[7].ival); } static void AerotechRegister(void) diff --git a/motorApp/AerotechSrc/AerotechRegister.h b/motorApp/AerotechSrc/AerotechRegister.h index e7a0cd3..4f34d36 100644 --- a/motorApp/AerotechSrc/AerotechRegister.h +++ b/motorApp/AerotechSrc/AerotechRegister.h @@ -2,10 +2,6 @@ FILENAME... AerotechRegister.h USAGE... This file contains function prototypes for ACS IOC shell commands. -Version: $Revision: 17434 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2014-05-21 11:43:51 -0500 (Wed, 21 May 2014) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/AerotechSrc/AerotechRegister.h $ */ /* diff --git a/motorApp/AerotechSrc/EnsembleCommonStructures.h b/motorApp/AerotechSrc/EnsembleCommonStructures.h new file mode 100755 index 0000000..a94e716 --- /dev/null +++ b/motorApp/AerotechSrc/EnsembleCommonStructures.h @@ -0,0 +1,927 @@ +/// \file EnsembleCommonStructures.h +/// \brief Contains some common structures and enumerations. +/// +/// Copyright (c) Aerotech, Inc. 2010-2017. +/// + +#ifndef __Ensemble_COMMON_STRUCTURES_H__ +#define __Ensemble_COMMON_STRUCTURES_H__ + +/// \brief Represents the servo update rates +typedef enum +{ + /// \brief 1 kHz rate (1 msec update time) + SERVORATEPARAMETER_OnekHz = 0, + /// \brief 2 kHz rate (0.5 msec update time) + SERVORATEPARAMETER_TwokHz = 1, + /// \brief 4 kHz rate (0.25 msec update time) + SERVORATEPARAMETER_FourkHz = 2, + /// \brief 5 kHz rate (0.2 msec update time) + SERVORATEPARAMETER_FivekHz = 3, + /// \brief 10 kHz rate (0.1 msec update time) + SERVORATEPARAMETER_TenkHz = 4, + /// \brief 20 kHz rate (0.05 msec update time) + SERVORATEPARAMETER_TwentykHz = 5, +} SERVORATEPARAMETER; + +/// \brief This value represents information about the state of this task. +typedef enum +{ + /// \brief This task was disabled by the TaskExecutionSetup parameter. + TASKSTATE_Inactive = 0, + /// \brief No program is associated or running. + TASKSTATE_Idle = 1, + /// \brief A program is associated but not running. + TASKSTATE_ProgramReady = 2, + /// \brief A program is associated and running. + TASKSTATE_ProgramRunning = 3, + /// \brief A program is associated, was run, and was paused. + TASKSTATE_ProgramPaused = 4, + /// \brief A program is associated, was run, and completed. + TASKSTATE_ProgramComplete = 5, + /// \brief A task error occurred on this task. + TASKSTATE_Error = 6, + /// \brief A task-based plugin is running in this task. + TASKSTATE_RunningPlugin = 10, +} TASKSTATE; + +/// \brief Represents plane status +typedef enum +{ + /// \brief The plane is generating motion on one or more axes. + PLANESTATUS_MotionActive = (1u << 0), + /// \brief The plane is generating a contoured motion on one or more axes. + PLANESTATUS_VelocityProfilingActive = (1u << 1), + /// \brief The plane is accelerating to the commanded velocity. + PLANESTATUS_AccelerationPhaseActive = (1u << 2), + /// \brief The plane is decelerating to the commanded velocity. + PLANESTATUS_DecelerationPhaseActive = (1u << 3), + /// \brief The plane is decelerating to zero velocity when commanded to abort. + PLANESTATUS_MotionAborting = (1u << 4), + /// \brief The plane is waiting for the START command to begin motion. + PLANESTATUS_HoldModeActive = (1u << 5), +} PLANESTATUS; +typedef enum +{ + /// \brief The plane is generating motion on one or more axes. + PLANESTATUSBITS_MotionActiveBit = 0, + /// \brief The plane is generating a contoured motion on one or more axes. + PLANESTATUSBITS_VelocityProfilingActiveBit = 1, + /// \brief The plane is accelerating to the commanded velocity. + PLANESTATUSBITS_AccelerationPhaseActiveBit = 2, + /// \brief The plane is decelerating to the commanded velocity. + PLANESTATUSBITS_DecelerationPhaseActiveBit = 3, + /// \brief The plane is decelerating to zero velocity when commanded to abort. + PLANESTATUSBITS_MotionAbortingBit = 4, + /// \brief The plane is waiting for the START command to begin motion. + PLANESTATUSBITS_HoldModeActiveBit = 5, +} PLANESTATUSBITS; + +/// \brief Represents the debug flags on the controller +typedef enum +{ + /// \brief + DEBUGFLAGS_PrintStringCallbackPending = (1u << 0), + /// \brief + DEBUGFLAGS_CollectionTriggered = (1u << 1), + /// \brief + DEBUGFLAGS_CollectionDone = (1u << 2), + /// \brief + DEBUGFLAGS_InputBoxCallbackPending = (1u << 3), +} DEBUGFLAGS; +typedef enum +{ + /// \brief + DEBUGFLAGSBITS_PrintStringCallbackPendingBit = 0, + /// \brief + DEBUGFLAGSBITS_CollectionTriggeredBit = 1, + /// \brief + DEBUGFLAGSBITS_CollectionDoneBit = 2, + /// \brief + DEBUGFLAGSBITS_InputBoxCallbackPendingBit = 3, +} DEBUGFLAGSBITS; + +/// \brief Represents an axis status +typedef enum +{ + /// \brief The axis is enabled. + AXISSTATUS_Enabled = (1u << 0), + /// \brief The axis is homed. + AXISSTATUS_Homed = (1u << 1), + /// \brief The axis is considered to be in position as configured by the InPositionDistance and InPositionTime parameters. + AXISSTATUS_InPosition = (1u << 2), + /// \brief The axis is performing drive generated motion. + AXISSTATUS_MoveActive = (1u << 3), + /// \brief The axis is accelerating. + AXISSTATUS_AccelerationPhase = (1u << 4), + /// \brief The axis is decelerating. + AXISSTATUS_DecelerationPhase = (1u << 5), + /// \brief Position capture is armed on the axis and waiting for a trigger signal. + AXISSTATUS_PositionCaptureActive = (1u << 6), + /// \brief For piezo drives, the controller clamps the motor output to the value of the PiezoVoltageClampLow or the PiezoVoltageClampHigh parameter. For all other drives, the controller clamps the motor output to the value of the MaxCurrentClamp parameter. + AXISSTATUS_CurrentClamp = (1u << 7), + /// \brief This represents the state of the dedicated brake output. + AXISSTATUS_BrakeOutput = (1u << 8), + /// \brief Indicates the direction of the active (or last) motion. + AXISSTATUS_MotionIsCw = (1u << 9), + /// \brief Gearing or camming is currently active on the axis. + AXISSTATUS_MasterSlaveControl = (1u << 10), + /// \brief The correction table for this axis is currently being applied. + AXISSTATUS_CalibrationActive = (1u << 11), + /// \brief A calibration file contains a calibration table that corrects this axis. The state of this bit is not affected by the CALENABLE or CALDISABLE commands. + AXISSTATUS_CalibrationEnabled = (1u << 12), + /// \brief The axis is currently performing motion under control of the JOYSTICK command. + AXISSTATUS_JoystickControl = (1u << 13), + /// \brief The axis is currently performing motion as part of the home cycle. + AXISSTATUS_Homing = (1u << 14), + /// \brief The axis position lost synchronization with the master and is ignoring profiled position. + AXISSTATUS_MasterMotionSuppressed = (1u << 15), + /// \brief This gantry is actively part of a gantry pair. + AXISSTATUS_GantryModeActive = (1u << 16), + /// \brief This axis is a gantry master in a gantry pair. + AXISSTATUS_GantryMasterActive = (1u << 17), + /// \brief This axis is operating under control of the AUTOFOCUS loop. + AXISSTATUS_AutofocusActive = (1u << 18), + /// \brief The filter defined by the Command Shaping Parameters is complete. + AXISSTATUS_CommandShapingFilterDone = (1u << 19), + /// \brief The axis is considered to be in position as configured by the InPosition2Distance and InPosition2Time parameters. + AXISSTATUS_InPosition2 = (1u << 20), + /// \brief The axis is operating under servo control. + AXISSTATUS_ServoControl = (1u << 21), + /// \brief This represents the state of the CW end of travel limit input. It is not affected by the active polarity, which is configured by the EndOfTravelLimitSetup parameter. + AXISSTATUS_CwEndOfTravelLimitInput = (1u << 22), + /// \brief This represents the state of the CCW end of travel limit input. It is not affected by the active polarity, which is configured by the EndOfTravelLimitSetup parameter. + AXISSTATUS_CcwEndOfTravelLimitInput = (1u << 23), + /// \brief This represents the state of the home limit input. It is not affected by the active polarity, which is configured by the EndOfTravelLimitSetup parameter. + AXISSTATUS_HomeLimitInput = (1u << 24), + /// \brief This represents the state of the marker input. + AXISSTATUS_MarkerInput = (1u << 25), + /// \brief This represents the state of the Hall-effect sensor A input. + AXISSTATUS_HallAInput = (1u << 26), + /// \brief This represents the state of the Hall-effect sensor B input. + AXISSTATUS_HallBInput = (1u << 27), + /// \brief This represents the state of the Hall-effect sensor C input. + AXISSTATUS_HallCInput = (1u << 28), + /// \brief An error condition is present on the Sine encoder input of the position feedback device. + AXISSTATUS_SineEncoderError = (1u << 29), + /// \brief An error condition is present on the Cosine encoder input of the position feedback device. + AXISSTATUS_CosineEncoderError = (1u << 30), + /// \brief This represents the state of the emergency stop sense input. + AXISSTATUS_EmergencyStopInput = (1u << 31), +} AXISSTATUS; +typedef enum +{ + /// \brief The axis is enabled. + AXISSTATUSBITS_EnabledBit = 0, + /// \brief The axis is homed. + AXISSTATUSBITS_HomedBit = 1, + /// \brief The axis is considered to be in position as configured by the InPositionDistance and InPositionTime parameters. + AXISSTATUSBITS_InPositionBit = 2, + /// \brief The axis is performing drive generated motion. + AXISSTATUSBITS_MoveActiveBit = 3, + /// \brief The axis is accelerating. + AXISSTATUSBITS_AccelerationPhaseBit = 4, + /// \brief The axis is decelerating. + AXISSTATUSBITS_DecelerationPhaseBit = 5, + /// \brief Position capture is armed on the axis and waiting for a trigger signal. + AXISSTATUSBITS_PositionCaptureActiveBit = 6, + /// \brief For piezo drives, the controller clamps the motor output to the value of the PiezoVoltageClampLow or the PiezoVoltageClampHigh parameter. For all other drives, the controller clamps the motor output to the value of the MaxCurrentClamp parameter. + AXISSTATUSBITS_CurrentClampBit = 7, + /// \brief This represents the state of the dedicated brake output. + AXISSTATUSBITS_BrakeOutputBit = 8, + /// \brief Indicates the direction of the active (or last) motion. + AXISSTATUSBITS_MotionIsCwBit = 9, + /// \brief Gearing or camming is currently active on the axis. + AXISSTATUSBITS_MasterSlaveControlBit = 10, + /// \brief The correction table for this axis is currently being applied. + AXISSTATUSBITS_CalibrationActiveBit = 11, + /// \brief A calibration file contains a calibration table that corrects this axis. The state of this bit is not affected by the CALENABLE or CALDISABLE commands. + AXISSTATUSBITS_CalibrationEnabledBit = 12, + /// \brief The axis is currently performing motion under control of the JOYSTICK command. + AXISSTATUSBITS_JoystickControlBit = 13, + /// \brief The axis is currently performing motion as part of the home cycle. + AXISSTATUSBITS_HomingBit = 14, + /// \brief The axis position lost synchronization with the master and is ignoring profiled position. + AXISSTATUSBITS_MasterMotionSuppressedBit = 15, + /// \brief This gantry is actively part of a gantry pair. + AXISSTATUSBITS_GantryModeActiveBit = 16, + /// \brief This axis is a gantry master in a gantry pair. + AXISSTATUSBITS_GantryMasterActiveBit = 17, + /// \brief This axis is operating under control of the AUTOFOCUS loop. + AXISSTATUSBITS_AutofocusActiveBit = 18, + /// \brief The filter defined by the Command Shaping Parameters is complete. + AXISSTATUSBITS_CommandShapingFilterDoneBit = 19, + /// \brief The axis is considered to be in position as configured by the InPosition2Distance and InPosition2Time parameters. + AXISSTATUSBITS_InPosition2Bit = 20, + /// \brief The axis is operating under servo control. + AXISSTATUSBITS_ServoControlBit = 21, + /// \brief This represents the state of the CW end of travel limit input. It is not affected by the active polarity, which is configured by the EndOfTravelLimitSetup parameter. + AXISSTATUSBITS_CwEndOfTravelLimitInputBit = 22, + /// \brief This represents the state of the CCW end of travel limit input. It is not affected by the active polarity, which is configured by the EndOfTravelLimitSetup parameter. + AXISSTATUSBITS_CcwEndOfTravelLimitInputBit = 23, + /// \brief This represents the state of the home limit input. It is not affected by the active polarity, which is configured by the EndOfTravelLimitSetup parameter. + AXISSTATUSBITS_HomeLimitInputBit = 24, + /// \brief This represents the state of the marker input. + AXISSTATUSBITS_MarkerInputBit = 25, + /// \brief This represents the state of the Hall-effect sensor A input. + AXISSTATUSBITS_HallAInputBit = 26, + /// \brief This represents the state of the Hall-effect sensor B input. + AXISSTATUSBITS_HallBInputBit = 27, + /// \brief This represents the state of the Hall-effect sensor C input. + AXISSTATUSBITS_HallCInputBit = 28, + /// \brief An error condition is present on the Sine encoder input of the position feedback device. + AXISSTATUSBITS_SineEncoderErrorBit = 29, + /// \brief An error condition is present on the Cosine encoder input of the position feedback device. + AXISSTATUSBITS_CosineEncoderErrorBit = 30, + /// \brief This represents the state of the emergency stop sense input. + AXISSTATUSBITS_EmergencyStopInputBit = 31, +} AXISSTATUSBITS; + +/// \brief Represents the motor type +typedef enum +{ + /// \brief AC Brushless (Hall-Effect Switches) + MOTORTYPE_ACBrushlessHallEffect = 0, + /// \brief AC Brushless (Auto-MSET) + MOTORTYPE_ACBrushlessAutoMSET = 1, + /// \brief DC Brush + MOTORTYPE_DCBrush = 2, + /// \brief Stepper Motor + MOTORTYPE_StepperMotor = 3, + /// \brief 2-Phase AC Brushless + MOTORTYPE_TwoPhaseACBrushless = 6, + /// \brief AC Brushless (Commutation Search) + MOTORTYPE_ACBrushlessCommutationSearch = 7, + /// \brief Piezo Actuator + MOTORTYPE_PiezoActuator = 8, +} MOTORTYPE; + +/// \brief Represents the home type +typedef enum +{ + /// \brief Home Past Limit to Marker + HOMETYPE_PastLimittoMarker = 0, + /// \brief Home to Limit and Reverse to Marker + HOMETYPE_ToLimitandReversetoMarker = 1, + /// \brief Home to Marker Only + HOMETYPE_ToMarkerOnly = 2, + /// \brief Home to Limit Only + HOMETYPE_ToLimitOnly = 3, + /// \brief Home at Current Position + HOMETYPE_AtCurrentPosition = 4, + /// \brief Home at Current Position Absolute + HOMETYPE_AtCurrentPositionAbsolute = 6, +} HOMETYPE; + +/// \brief Represents the position feedback type +typedef enum +{ + /// \brief None (Open-Loop) + POSITIONFEEDBACKTYPE_None = 0, + /// \brief Local Encoder Counter + POSITIONFEEDBACKTYPE_LocalEncoderCounter = 1, + /// \brief Encoder Multiplier + POSITIONFEEDBACKTYPE_EncoderMultiplier = 2, + /// \brief Analog Input + POSITIONFEEDBACKTYPE_AnalogInput = 3, + /// \brief EnDat Absolute Encoder + POSITIONFEEDBACKTYPE_EnDatAbsoluteEncoder = 4, + /// \brief Hall-Effect Switches + POSITIONFEEDBACKTYPE_HallEffectSwitches = 5, + /// \brief Resolver + POSITIONFEEDBACKTYPE_Resolver = 6, + /// \brief Resolute Absolute Encoder + POSITIONFEEDBACKTYPE_ResoluteAbsoluteEncoder = 9, + /// \brief Capacitance Sensor + POSITIONFEEDBACKTYPE_CapacitanceSensor = 11, +} POSITIONFEEDBACKTYPE; + +/// \brief Represents the velocity feedback type +typedef enum +{ + /// \brief None (Use Position Feedback) + VELOCITYFEEDBACKTYPE_None = 0, + /// \brief Local Encoder Counter + VELOCITYFEEDBACKTYPE_LocalEncoderCounter = 1, + /// \brief Encoder Multiplier + VELOCITYFEEDBACKTYPE_EncoderMultiplier = 2, + /// \brief Analog Input + VELOCITYFEEDBACKTYPE_AnalogInput = 3, + /// \brief Resolver + VELOCITYFEEDBACKTYPE_Resolver = 6, +} VELOCITYFEEDBACKTYPE; + +/// \brief Specifies the status flags of data collection +typedef enum +{ + /// \brief Data collection was triggered + DATACOLLECTIONFLAGS_Triggered = (1u << 2), + /// \brief Data collection is done + DATACOLLECTIONFLAGS_Done = (1u << 3), + /// \brief Data collection buffer overflowed + DATACOLLECTIONFLAGS_Overflow = (1u << 5), + /// \brief Data collection was started by a SCOPETRIG + DATACOLLECTIONFLAGS_IsScopeTrigInitiated = (1u << 6), +} DATACOLLECTIONFLAGS; +typedef enum +{ + /// \brief Data collection was triggered + DATACOLLECTIONFLAGSBITS_TriggeredBit = 2, + /// \brief Data collection is done + DATACOLLECTIONFLAGSBITS_DoneBit = 3, + /// \brief Data collection buffer overflowed + DATACOLLECTIONFLAGSBITS_OverflowBit = 5, + /// \brief Data collection was started by a SCOPETRIG + DATACOLLECTIONFLAGSBITS_IsScopeTrigInitiatedBit = 6, +} DATACOLLECTIONFLAGSBITS; + +/// \brief Represents the piezo default servo state. +typedef enum +{ + /// \brief Servo Off + PIEZODEFAULTSERVOSTATE_Off = 0, + /// \brief Servo On + PIEZODEFAULTSERVOSTATE_On = 1, +} PIEZODEFAULTSERVOSTATE; + +/// \brief Specifies which status item to collect +typedef enum +{ + /// \brief Position command + STATUSITEM_PositionCommand = 0, + /// \brief Position feedback + STATUSITEM_PositionFeedback = 1, + /// \brief Position feedback auxiliary + STATUSITEM_PositionFeedbackAuxiliary = 2, + /// \brief Axis status + STATUSITEM_AxisStatus = 3, + /// \brief Axis fault + STATUSITEM_AxisFault = 4, + /// \brief Analog input #0 + STATUSITEM_AnalogInput0 = 5, + /// \brief Analog input #1 + STATUSITEM_AnalogInput1 = 6, + /// \brief Analog output #0 + STATUSITEM_AnalogOutput0 = 7, + /// \brief Analog output #1 + STATUSITEM_AnalogOutput1 = 8, + /// \brief Digital input #0 + STATUSITEM_DigitalInput0 = 9, + /// \brief Digital input #1 + STATUSITEM_DigitalInput1 = 10, + /// \brief Digital input #2 + STATUSITEM_DigitalInput2 = 11, + /// \brief Digital output #0 + STATUSITEM_DigitalOutput0 = 12, + /// \brief Digital output #1 + STATUSITEM_DigitalOutput1 = 13, + /// \brief Digital output #2 + STATUSITEM_DigitalOutput2 = 14, + /// \brief Current command + STATUSITEM_CurrentCommand = 15, + /// \brief Current feedback + STATUSITEM_CurrentFeedback = 16, + /// \brief Amplifier temperature + STATUSITEM_AmplifierTemperature = 17, + /// \brief Auxiliary flags + STATUSITEM_DebugFlags = 18, + /// \brief Program position command + STATUSITEM_ProgramPositionCommand = 19, + /// \brief Program count of library task + STATUSITEM_ProgramCountTaskLibrary = 20, + /// \brief Program count of task #1 + STATUSITEM_ProgramCountTask1 = 21, + /// \brief Program count of task #2 + STATUSITEM_ProgramCountTask2 = 22, + /// \brief Program count of task #3 + STATUSITEM_ProgramCountTask3 = 23, + /// \brief Program count of task #4 + STATUSITEM_ProgramCountTask4 = 24, + /// \brief Time of the packet retrieval in milliseconds + STATUSITEM_PacketTime = 25, + /// \brief Program position feedback + STATUSITEM_ProgramPositionFeedback = 26, + /// \brief Absolute feedback + STATUSITEM_AbsoluteFeedback = 27, + /// \brief Status of plane #0 + STATUSITEM_PlaneStatus0 = 28, + /// \brief Status of plane #1 + STATUSITEM_PlaneStatus1 = 29, + /// \brief Status of plane #2, Epaq only + STATUSITEM_PlaneStatus2 = 30, + /// \brief Status of plane #3, Epaq only + STATUSITEM_PlaneStatus3 = 31, + /// \brief State of task #1 + STATUSITEM_TaskState1 = 33, + /// \brief State of task #2 + STATUSITEM_TaskState2 = 34, + /// \brief State of task #3 + STATUSITEM_TaskState3 = 35, + /// \brief State of task #4 + STATUSITEM_TaskState4 = 36, + /// \brief Analog input #2 + STATUSITEM_AnalogInput2 = 38, + /// \brief Analog input #3 + STATUSITEM_AnalogInput3 = 39, + /// \brief Analog output #2 + STATUSITEM_AnalogOutput2 = 40, + /// \brief Analog output #3 + STATUSITEM_AnalogOutput3 = 41, + /// \brief Velocity Command + STATUSITEM_VelocityCommand = 42, + /// \brief Velocity Feedback + STATUSITEM_VelocityFeedback = 43, + /// \brief Acceleration Command + STATUSITEM_AccelerationCommand = 44, + /// \brief Velocity Error + STATUSITEM_VelocityError = 45, + /// \brief Position Error + STATUSITEM_PositionError = 46, + /// \brief Current Error + STATUSITEM_CurrentError = 47, + /// \brief Acceleration Feedback + STATUSITEM_AccelerationFeedback = 48, + /// \brief Acceleration Error + STATUSITEM_AccelerationError = 49, + /// \brief Analog output #4 + STATUSITEM_AnalogOutput4 = 50, + /// \brief Piezo Voltage Feedback + STATUSITEM_PiezoVoltageFeedback = 51, + /// \brief Piezo Voltage Command + STATUSITEM_PiezoVoltageCommand = 52, +} STATUSITEM; + +/// \brief The type of loop transmission disturbance to use +typedef enum +{ + /// \brief Turn off loop transmission + LOOPTRANSMISSIONMODE_Off = 0, + /// \brief Uses a sinusoid disturbance + LOOPTRANSMISSIONMODE_Sinusoid = 1, + /// \brief Uses a sinusoid disturbance and excites both axes of a gantry + LOOPTRANSMISSIONMODE_SinusoidGantry = 2, + /// \brief Uses a white noise disturbance + LOOPTRANSMISSIONMODE_WhiteNoise = 3, + /// \brief Use a white noise disturbance and excites both axes of a gantry + LOOPTRANSMISSIONMODE_WhiteNoiseGantry = 4, +} LOOPTRANSMISSIONMODE; + +/// \brief The loop transmission type to use +typedef enum +{ + /// \brief Open Loop + LOOPTRANSMISSIONTYPE_OpenLoop = 0, + /// \brief Closed Loop + LOOPTRANSMISSIONTYPE_ClosedLoop = 1, + /// \brief Current Loop + LOOPTRANSMISSIONTYPE_CurrentLoop = 2, + /// \brief AF Open Loop + LOOPTRANSMISSIONTYPE_AFOpenLoop = 3, + /// \brief AF Closed Loop + LOOPTRANSMISSIONTYPE_AFClosedLoop = 4, +} LOOPTRANSMISSIONTYPE; + +/// \brief Represents the OnOff mode in AeroBasic +typedef enum +{ + /// \brief Off or 0 is issued + ONOFF_Off = 0, + /// \brief On or 1 is issued + ONOFF_On = 1, +} ONOFF; + +/// \brief Represents the PSO mode in AeroBasic +typedef enum +{ + /// \brief Reset PSO + PSOMODE_Reset = 0, + /// \brief Turn off PSO + PSOMODE_Off = 1, + /// \brief Arm PSO + PSOMODE_Arm = 2, + /// \brief Fire PSO + PSOMODE_Fire = 3, + /// \brief Turn on PSO + PSOMODE_On = 4, + /// \brief Fire Continuous + PSOMODE_FireContinuous = 5, +} PSOMODE; + +/// \brief The ethernet status information +typedef enum +{ + /// \brief Whether there is data to be transmitted + ETHERNETSTATUS_DataInTransmitter = (1u << 0), + /// \brief Whether there is data to be processed + ETHERNETSTATUS_DataInReceiver = (1u << 1), +} ETHERNETSTATUS; +typedef enum +{ + /// \brief Whether there is data to be transmitted + ETHERNETSTATUSBITS_DataInTransmitterBit = 0, + /// \brief Whether there is data to be processed + ETHERNETSTATUSBITS_DataInReceiverBit = 1, +} ETHERNETSTATUSBITS; + +/// \brief Represents the semaphores in AeroBasic +typedef enum +{ + /// \brief Modbus registers semaphore + SEMAPHORES_ModbusRegisters = 0, + /// \brief Global integers semaphore + SEMAPHORES_GlobalIntegers = 1, + /// \brief Global doubles semaphore + SEMAPHORES_GlobalDoubles = 2, +} SEMAPHORES; + +/// \brief The wait option for waiting for a move to be completed +typedef enum +{ + /// \brief Wait in position + WAITOPTION_InPosition = 0, + /// \brief Wait for move done + WAITOPTION_MoveDone = 1, +} WAITOPTION; + +/// \brief Represents the wait mode in AeroBasic +typedef enum +{ + /// \brief Do not wait for motion to be done + WAITTYPE_NoWait = 0, + /// \brief Wait for motion to be done + WAITTYPE_MoveDone = 1, + /// \brief Wait for axis to be in position + WAITTYPE_InPos = 2, +} WAITTYPE; + +/// \brief The Mode types that can be retrieved by using the GETMODE immediate command. +typedef enum +{ + /// \brief Returns the Motion Mode type (absolute/incremental). + MODETYPE_MotionMode = 0, + /// \brief Returns the Wait Mode type (in position / move done / no wait). + MODETYPE_WaitMode = 1, + /// \brief Returns the Ramp Mode type (linear / SCurve). + MODETYPE_RampMode = 2, + /// \brief Returns the Velocity Mode type (profiled / not profiled). + MODETYPE_VelocityMode = 3, + /// \brief Returns the S-curve value. + MODETYPE_ScurveValue = 4, + /// \brief Returns the Timescale value. + MODETYPE_TimeScaleValue = 5, + /// \brief Returns the default velocity value. + MODETYPE_DefaultVelocityValue = 6, + /// \brief Returns the acceleration rate value. + MODETYPE_AccelRateValue = 7, + /// \brief Returns the acceleration time value. + MODETYPE_AccelTimeValue = 8, + /// \brief Returns the acceleration distance value. + MODETYPE_AccelDistValue = 9, + /// \brief Returns the deceleration rate value. + MODETYPE_DecelRateValue = 10, + /// \brief Returns the deceleration time value. + MODETYPE_DecelTimeValue = 11, + /// \brief Returns the deceleration distance value. + MODETYPE_DecelDistValue = 12, + /// \brief Returns the current plane number for the task. + MODETYPE_Plane = 14, +} MODETYPE; + +/// \brief The type of error that occured during compilation +typedef enum +{ + /// \brief The syntax does not follow AeroBasic + COMPILERERRORTYPE_Syntax = 0, + /// \brief Specific testing detected an error (ex: unknown register set) + COMPILERERRORTYPE_Process = 1, + /// \brief The operating system blocked an operation (ex: file access restriction) + COMPILERERRORTYPE_System = 2, + /// \brief An unrecoverable error occured (ex: out of memory) + COMPILERERRORTYPE_Unrecoverable = 3, + /// \brief The message given is a warning + COMPILERERRORTYPE_Warning = 4, +} COMPILERERRORTYPE; + +/// \brief +typedef enum +{ + /// \brief + DAYOFWEEK_Sunday = 0, + /// \brief + DAYOFWEEK_Monday = 1, + /// \brief + DAYOFWEEK_Tuesday = 2, + /// \brief + DAYOFWEEK_Wednesday = 3, + /// \brief + DAYOFWEEK_Thursday = 4, + /// \brief + DAYOFWEEK_Friday = 5, + /// \brief + DAYOFWEEK_Saturday = 6, +} DAYOFWEEK; + +/// \brief If this is different from , corrective measures should be taken. +typedef enum +{ + /// \brief There are no mismatches between the axes + AXISMISMATCH_None = 0, + /// \brief The version of firmware is different between the axes, update the firmware + AXISMISMATCH_FirmwareVersion = 1, + /// \brief The axes numbers are different from expected, please setup the axes that are expected + AXISMISMATCH_AxisMask = 2, +} AXISMISMATCH; + +/// \brief This is an enumeration of the Register types used when calling the Register immediate command functions found in . +typedef enum +{ + /// \brief Global Integers + REGISTERTYPE_GlobalIntegers = 0, + /// \brief Global Doubles + REGISTERTYPE_GlobalDoubles = 1, + /// \brief Conversion Registers + REGISTERTYPE_ConversionRegisters = 2, + /// \brief Modbus Master Input Registers + REGISTERTYPE_ModbusMasterInputWords = 3, + /// \brief Modbus Master Output Registers + REGISTERTYPE_ModbusMasterOutputWords = 4, + /// \brief Modbus Master Input Bit Registers + REGISTERTYPE_ModbusMasterInputBits = 5, + /// \brief Modbus Master Output Bit Registers + REGISTERTYPE_ModbusMasterOutputBits = 6, + /// \brief Modbus Master Status Registers + REGISTERTYPE_ModbusMasterStatusWords = 7, + /// \brief Modbus Master Status Bit Registers + REGISTERTYPE_ModbusMasterStatusBits = 8, + /// \brief Modbus Master Virtual Input Registers + REGISTERTYPE_ModbusMasterVirtualInputs = 9, + /// \brief Modbus Master Virtual Output Registers + REGISTERTYPE_ModbusMasterVirtualOutputs = 10, + /// \brief Modbus Slave Input Registers + REGISTERTYPE_ModbusSlaveInputWords = 11, + /// \brief Modbus Slave Output Registers + REGISTERTYPE_ModbusSlaveOutputWords = 12, + /// \brief Modbus Slave Input Bit Registers + REGISTERTYPE_ModbusSlaveInputBits = 13, + /// \brief Modbus Slave Output Bit Registers + REGISTERTYPE_ModbusSlaveOutputBits = 14, +} REGISTERTYPE; + +/// \brief The type of the component +typedef enum +{ + /// \brief Compact pulse width modulation + COMPONENTTYPE_CP = 32773, + /// \brief Micro pulse width modulation + COMPONENTTYPE_MP = 32774, + /// \brief Ensemble control board + COMPONENTTYPE_Control = 32775, + /// \brief Compact Linear + COMPONENTTYPE_CL = 32776, + /// \brief High performance pulse width modulation enhanced + COMPONENTTYPE_HPE = 32777, + /// \brief High performance linear enhanced + COMPONENTTYPE_HLE = 32778, + /// \brief Micro pulse linear + COMPONENTTYPE_ML = 32779, + /// \brief Obsolete + COMPONENTTYPE_PMT = 32780, + /// \brief Ensemble Lab controller + COMPONENTTYPE_Lab = 32781, + /// \brief Ensemble QLab controller + COMPONENTTYPE_QLab = 32782, + /// \brief High Performance Single Axis Piezo Drive + COMPONENTTYPE_QDe = 32784, + /// \brief Single Axis Piezo Drive + COMPONENTTYPE_QL = 32785, + /// \brief High Performance Single Axis Piezo Drive + COMPONENTTYPE_QLe = 32786, +} COMPONENTTYPE; + +/// \brief The communication type used to communicate with a controller +typedef enum +{ + /// \brief Communications are over ethernet + COMMUNICATIONTYPE_Ethernet = 2, + /// \brief Communications are over USB + COMMUNICATIONTYPE_Usb = 3, +} COMMUNICATIONTYPE; + +/// \brief Specifies the build result kind +typedef enum +{ + /// \brief The build result describes a warning that occurred during the compilation + BUILDRESULTKIND_Warning = 0, + /// \brief The build result describes an error that occurred during the compilation + BUILDRESULTKIND_Error = 1, +} BUILDRESULTKIND; + +/// \brief Contains information about configuration of FlashConfig in a stage. +typedef enum +{ + /// \brief Whether the FlashConfig memory is present and FlashConfig feature is supported. + FLASHCONFIGSTATUS_Supported = (1u << 0), + /// \brief FlashConfig data is valid. + FLASHCONFIGSTATUS_DataValid = (1u << 1), + /// \brief Connected Stage serial number does not match expected Stage serial number. + FLASHCONFIGSTATUS_SerialMismatch = (1u << 2), +} FLASHCONFIGSTATUS; +typedef enum +{ + /// \brief Whether the FlashConfig memory is present and FlashConfig feature is supported. + FLASHCONFIGSTATUSBITS_SupportedBit = 0, + /// \brief FlashConfig data is valid. + FLASHCONFIGSTATUSBITS_DataValidBit = 1, + /// \brief Connected Stage serial number does not match expected Stage serial number. + FLASHCONFIGSTATUSBITS_SerialMismatchBit = 2, +} FLASHCONFIGSTATUSBITS; + +/// \brief Represents the faults of an axis +typedef enum +{ + /// \brief The absolute value of the difference between the position command and the position feedback exceeded the threshold specified by the PositionErrorThreshold parameter. + AXISFAULT_PositionErrorFault = (1u << 0), + /// \brief The average motor current exceeded the threshold specified by the AverageCurrentThreshold and AverageCurrentTime parameters. + AXISFAULT_OverCurrentFault = (1u << 1), + /// \brief The axis encountered the clockwise (positive) end-of-travel limit switch. + AXISFAULT_CwEndOfTravelLimitFault = (1u << 2), + /// \brief The axis encountered the counter-clockwise (negative) end-of-travel limit switch. + AXISFAULT_CcwEndOfTravelLimitFault = (1u << 3), + /// \brief The axis was commanded to move beyond the position specified by the SoftwareLimitHigh parameter. + AXISFAULT_CwSoftwareLimitFault = (1u << 4), + /// \brief The axis was commanded to move beyond the position specified by the SoftwareLimitLow parameter. + AXISFAULT_CcwSoftwareLimitFault = (1u << 5), + /// \brief The amplifier for this axis exceeded its maximum current rating or experienced an internal error. + AXISFAULT_AmplifierFault = (1u << 6), + /// \brief The drive detected a problem with the feedback device specified by the PositionFeedbackType and PositionFeedbackChannel parameters. + AXISFAULT_PositionFeedbackFault = (1u << 7), + /// \brief The drive detected a problem with the feedback device specified by the VelocityFeedbackType and VelocityFeedbackChannel parameters. + AXISFAULT_VelocityFeedbackFault = (1u << 8), + /// \brief The drive detected an invalid state (all high or all low) for the Hall-effect sensor inputs on this axis. + AXISFAULT_HallSensorFault = (1u << 9), + /// \brief The commanded velocity is more than the velocity command threshold. Before the axis is homed, this threshold is specified by the VelocityCommandThresholdBeforeHome parameter. After the axis is homed, this threshold is specified by the VelocityCommandThreshold parameter. + AXISFAULT_MaxVelocityCommandFault = (1u << 10), + /// \brief The emergency stop sense input, specified by the ESTOPFaultInput parameter, was triggered. + AXISFAULT_EmergencyStopFault = (1u << 11), + /// \brief The absolute value of the difference between the velocity command and the velocity feedback exceeded the threshold specified by the VelocityErrorThreshold parameter. + AXISFAULT_VelocityErrorFault = (1u << 12), + /// \brief The external fault input, specified by the ExternalFaultAnalogInput or ExternalFaultDigitalInput parameters, was triggered. + AXISFAULT_ExternalFault = (1u << 15), + /// \brief The motor thermistor input was triggered, which indicates that the motor exceeded its maximum recommended operating temperature. + AXISFAULT_MotorTemperatureFault = (1u << 17), + /// \brief The amplifier exceeded its maximum recommended operating temperature. + AXISFAULT_AmplifierTemperatureFault = (1u << 18), + /// \brief The encoder fault input on the motor feedback connector was triggered. + AXISFAULT_EncoderFault = (1u << 19), + /// \brief One or more of the drives on the network lost communications with the controller. + AXISFAULT_CommunicationLostFault = (1u << 20), + /// \brief The difference between the position feedback and the scaled (adjusted by GainKv) velocity feedback exceeds the threshold specified by the PositionErrorThreshold parameter. + AXISFAULT_FeedbackScalingFault = (1u << 23), + /// \brief The distance that the axis moved while searching for the marker exceeded the threshold specified by the MarkerSearchThreshold parameter. + AXISFAULT_MarkerSearchFault = (1u << 24), + /// \brief The commanded voltage output exceeded the value of the PiezoVoltageClampLow or PiezoVoltageClampHigh parameter. + AXISFAULT_VoltageClampFault = (1u << 27), + /// \brief The power supply output has exceeded the allowable power or temperature threshold. + AXISFAULT_PowerSupplyFault = (1u << 28), + /// \brief The drive failed has encountered an internal error and had to disable. For assistance, contact Aerotech Customer Service. + AXISFAULT_InternalFault = (1u << 30), +} AXISFAULT; +typedef enum +{ + /// \brief The absolute value of the difference between the position command and the position feedback exceeded the threshold specified by the PositionErrorThreshold parameter. + AXISFAULTBITS_PositionErrorFaultBit = 0, + /// \brief The average motor current exceeded the threshold specified by the AverageCurrentThreshold and AverageCurrentTime parameters. + AXISFAULTBITS_OverCurrentFaultBit = 1, + /// \brief The axis encountered the clockwise (positive) end-of-travel limit switch. + AXISFAULTBITS_CwEndOfTravelLimitFaultBit = 2, + /// \brief The axis encountered the counter-clockwise (negative) end-of-travel limit switch. + AXISFAULTBITS_CcwEndOfTravelLimitFaultBit = 3, + /// \brief The axis was commanded to move beyond the position specified by the SoftwareLimitHigh parameter. + AXISFAULTBITS_CwSoftwareLimitFaultBit = 4, + /// \brief The axis was commanded to move beyond the position specified by the SoftwareLimitLow parameter. + AXISFAULTBITS_CcwSoftwareLimitFaultBit = 5, + /// \brief The amplifier for this axis exceeded its maximum current rating or experienced an internal error. + AXISFAULTBITS_AmplifierFaultBit = 6, + /// \brief The drive detected a problem with the feedback device specified by the PositionFeedbackType and PositionFeedbackChannel parameters. + AXISFAULTBITS_PositionFeedbackFaultBit = 7, + /// \brief The drive detected a problem with the feedback device specified by the VelocityFeedbackType and VelocityFeedbackChannel parameters. + AXISFAULTBITS_VelocityFeedbackFaultBit = 8, + /// \brief The drive detected an invalid state (all high or all low) for the Hall-effect sensor inputs on this axis. + AXISFAULTBITS_HallSensorFaultBit = 9, + /// \brief The commanded velocity is more than the velocity command threshold. Before the axis is homed, this threshold is specified by the VelocityCommandThresholdBeforeHome parameter. After the axis is homed, this threshold is specified by the VelocityCommandThreshold parameter. + AXISFAULTBITS_MaxVelocityCommandFaultBit = 10, + /// \brief The emergency stop sense input, specified by the ESTOPFaultInput parameter, was triggered. + AXISFAULTBITS_EmergencyStopFaultBit = 11, + /// \brief The absolute value of the difference between the velocity command and the velocity feedback exceeded the threshold specified by the VelocityErrorThreshold parameter. + AXISFAULTBITS_VelocityErrorFaultBit = 12, + /// \brief The external fault input, specified by the ExternalFaultAnalogInput or ExternalFaultDigitalInput parameters, was triggered. + AXISFAULTBITS_ExternalFaultBit = 15, + /// \brief The motor thermistor input was triggered, which indicates that the motor exceeded its maximum recommended operating temperature. + AXISFAULTBITS_MotorTemperatureFaultBit = 17, + /// \brief The amplifier exceeded its maximum recommended operating temperature. + AXISFAULTBITS_AmplifierTemperatureFaultBit = 18, + /// \brief The encoder fault input on the motor feedback connector was triggered. + AXISFAULTBITS_EncoderFaultBit = 19, + /// \brief One or more of the drives on the network lost communications with the controller. + AXISFAULTBITS_CommunicationLostFaultBit = 20, + /// \brief The difference between the position feedback and the scaled (adjusted by GainKv) velocity feedback exceeds the threshold specified by the PositionErrorThreshold parameter. + AXISFAULTBITS_FeedbackScalingFaultBit = 23, + /// \brief The distance that the axis moved while searching for the marker exceeded the threshold specified by the MarkerSearchThreshold parameter. + AXISFAULTBITS_MarkerSearchFaultBit = 24, + /// \brief The commanded voltage output exceeded the value of the PiezoVoltageClampLow or PiezoVoltageClampHigh parameter. + AXISFAULTBITS_VoltageClampFaultBit = 27, + /// \brief The power supply output has exceeded the allowable power or temperature threshold. + AXISFAULTBITS_PowerSupplyFaultBit = 28, + /// \brief The drive failed has encountered an internal error and had to disable. For assistance, contact Aerotech Customer Service. + AXISFAULTBITS_InternalFaultBit = 30, +} AXISFAULTBITS; + +/// \brief Represents the ramp type in AeroBasic +typedef enum +{ + /// \brief Linear-based ramp type + RAMPTYPE_Linear = 0, + /// \brief S-curve-based ramp type + RAMPTYPE_Scurve = 1, + /// \brief Sine-based ramp type + RAMPTYPE_Sine = 2, +} RAMPTYPE; + +/// \brief Represents the ramp mode in AeroBasic +typedef enum +{ + /// \brief Distance-based acceleration and deceleration + RAMPMODE_Dist = 0, + /// \brief Rate-based acceleration and deceleration + RAMPMODE_Rate = 1, + /// \brief Time-based acceleration and deceleration + RAMPMODE_Time = 2, +} RAMPMODE; + +/// \brief Represents the type of output an axis generates. +typedef enum +{ + /// \brief No output is generated. + COMMANDOUTPUTTYPE_None = 0, + /// \brief Current output is generated. + COMMANDOUTPUTTYPE_Current = 1, + /// \brief Voltage output is generated. + COMMANDOUTPUTTYPE_Voltage = 2, +} COMMANDOUTPUTTYPE; + +/// \brief Specifies the type of calibration table associated with a calibration file action. +typedef enum +{ + /// \brief 1D calibration table. + BINARYCALIBRATIONACTIONTABLETYPE_Calibration1D = 0, + /// \brief 2D calibration table. + BINARYCALIBRATIONACTIONTABLETYPE_Calibration2D = 1, +} BINARYCALIBRATIONACTIONTABLETYPE; + +/// \brief Specifies the status of a binary calibration file action. +typedef enum +{ + /// \brief The calibration table was added. + BINARYCALIBRATIONACTIONSTATUS_TableAdded = 0, + /// \brief The calibration table was removed. + BINARYCALIBRATIONACTIONSTATUS_TableRemoved = 1, + /// \brief The calibration table was not added. + BINARYCALIBRATIONACTIONSTATUS_TableNotAdded = 2, +} BINARYCALIBRATIONACTIONSTATUS; + +/// \brief Represents the position feedback channel type +typedef enum +{ + /// \brief Default + POSITIONFEEDBACKCHANNEL_Default = -1, + /// \brief Channel 0 + POSITIONFEEDBACKCHANNEL_Channel0 = 0, + /// \brief Channel 1 + POSITIONFEEDBACKCHANNEL_Channel1 = 1, + /// \brief Channel 2 + POSITIONFEEDBACKCHANNEL_Channel2 = 2, + /// \brief Channel 3 + POSITIONFEEDBACKCHANNEL_Channel3 = 3, + /// \brief Channel 4 + POSITIONFEEDBACKCHANNEL_Channel4 = 4, +} POSITIONFEEDBACKCHANNEL; + +/// \brief Represents the velocity feedback channel type +typedef enum +{ + /// \brief Default + VELOCITYFEEDBACKCHANNEL_Default = -1, + /// \brief Channel 0 + VELOCITYFEEDBACKCHANNEL_Channel0 = 0, + /// \brief Channel 1 + VELOCITYFEEDBACKCHANNEL_Channel1 = 1, + /// \brief Channel 2 + VELOCITYFEEDBACKCHANNEL_Channel2 = 2, + /// \brief Channel 3 + VELOCITYFEEDBACKCHANNEL_Channel3 = 3, + /// \brief Channel 4 + VELOCITYFEEDBACKCHANNEL_Channel4 = 4, +} VELOCITYFEEDBACKCHANNEL; + +#endif // __Ensemble_COMMON_STRUCTURES_H__ + diff --git a/motorApp/AerotechSrc/EnsembleParameterId.h b/motorApp/AerotechSrc/EnsembleParameterId.h new file mode 100755 index 0000000..f2f0aed --- /dev/null +++ b/motorApp/AerotechSrc/EnsembleParameterId.h @@ -0,0 +1,877 @@ +/// \file EnsembleParameterId.h +/// \brief Contains parameter identifiers +/// +/// This file is version dependent and needs to match the rest of the software +/// +/// Copyright (c) Aerotech, Inc. 2010-2017. +/// + +#ifndef __Ensemble_PARAMETER_ID_H__ +#define __Ensemble_PARAMETER_ID_H__ + + +/// \brief Represents a parameter identifier +typedef enum { + /// \brief The AxisType parameter + PARAMETERID_AxisType = ( (0 << 24) | 0 ), + /// \brief The ReverseMotionDirection parameter + PARAMETERID_ReverseMotionDirection = ( (0 << 24) | 1 ), + /// \brief The CountsPerUnit parameter + PARAMETERID_CountsPerUnit = ( (0 << 24) | 2 ), + /// \brief The ServoRate parameter + PARAMETERID_ServoRate = ( (0 << 24) | 3 ), + /// \brief The ServoSetup parameter + PARAMETERID_ServoSetup = ( (0 << 24) | 4 ), + /// \brief The GainKpos parameter + PARAMETERID_GainKpos = ( (0 << 24) | 5 ), + /// \brief The GainKi parameter + PARAMETERID_GainKi = ( (0 << 24) | 6 ), + /// \brief The GainKp parameter + PARAMETERID_GainKp = ( (0 << 24) | 7 ), + /// \brief The GainVff parameter + PARAMETERID_GainVff = ( (0 << 24) | 8 ), + /// \brief The GainAff parameter + PARAMETERID_GainAff = ( (0 << 24) | 9 ), + /// \brief The GainKv parameter + PARAMETERID_GainKv = ( (0 << 24) | 10 ), + /// \brief The GainKpi parameter + PARAMETERID_GainKpi = ( (0 << 24) | 11 ), + /// \brief The ServoFilter0CoeffN0 parameter + PARAMETERID_ServoFilter0CoeffN0 = ( (0 << 24) | 12 ), + /// \brief The ServoFilter0CoeffN1 parameter + PARAMETERID_ServoFilter0CoeffN1 = ( (0 << 24) | 13 ), + /// \brief The ServoFilter0CoeffN2 parameter + PARAMETERID_ServoFilter0CoeffN2 = ( (0 << 24) | 14 ), + /// \brief The ServoFilter0CoeffD1 parameter + PARAMETERID_ServoFilter0CoeffD1 = ( (0 << 24) | 15 ), + /// \brief The ServoFilter0CoeffD2 parameter + PARAMETERID_ServoFilter0CoeffD2 = ( (0 << 24) | 16 ), + /// \brief The ServoFilter1CoeffN0 parameter + PARAMETERID_ServoFilter1CoeffN0 = ( (0 << 24) | 17 ), + /// \brief The ServoFilter1CoeffN1 parameter + PARAMETERID_ServoFilter1CoeffN1 = ( (0 << 24) | 18 ), + /// \brief The ServoFilter1CoeffN2 parameter + PARAMETERID_ServoFilter1CoeffN2 = ( (0 << 24) | 19 ), + /// \brief The ServoFilter1CoeffD1 parameter + PARAMETERID_ServoFilter1CoeffD1 = ( (0 << 24) | 20 ), + /// \brief The ServoFilter1CoeffD2 parameter + PARAMETERID_ServoFilter1CoeffD2 = ( (0 << 24) | 21 ), + /// \brief The AmplifierDeadtime parameter + PARAMETERID_AmplifierDeadtime = ( (0 << 24) | 22 ), + /// \brief The RolloverCounts parameter + PARAMETERID_RolloverCounts = ( (0 << 24) | 23 ), + /// \brief The CurrentGainKi parameter + PARAMETERID_CurrentGainKi = ( (0 << 24) | 24 ), + /// \brief The CurrentGainKp parameter + PARAMETERID_CurrentGainKp = ( (0 << 24) | 25 ), + /// \brief The FaultMask parameter + PARAMETERID_FaultMask = ( (0 << 24) | 26 ), + /// \brief The FaultMaskDisable parameter + PARAMETERID_FaultMaskDisable = ( (0 << 24) | 27 ), + /// \brief The FaultMaskDecel parameter + PARAMETERID_FaultMaskDecel = ( (0 << 24) | 28 ), + /// \brief The EnableBrakeControl parameter + PARAMETERID_EnableBrakeControl = ( (0 << 24) | 29 ), + /// \brief The FaultMaskOutput parameter + PARAMETERID_FaultMaskOutput = ( (0 << 24) | 30 ), + /// \brief The ESTOPFaultInput parameter + PARAMETERID_ESTOPFaultInput = ( (0 << 24) | 31 ), + /// \brief The PositionErrorThreshold parameter + PARAMETERID_PositionErrorThreshold = ( (0 << 24) | 32 ), + /// \brief The AverageCurrentThreshold parameter + PARAMETERID_AverageCurrentThreshold = ( (0 << 24) | 33 ), + /// \brief The AverageCurrentTime parameter + PARAMETERID_AverageCurrentTime = ( (0 << 24) | 34 ), + /// \brief The VelocityCommandThreshold parameter + PARAMETERID_VelocityCommandThreshold = ( (0 << 24) | 35 ), + /// \brief The VelocityErrorThreshold parameter + PARAMETERID_VelocityErrorThreshold = ( (0 << 24) | 36 ), + /// \brief The SoftwareLimitLow parameter + PARAMETERID_SoftwareLimitLow = ( (0 << 24) | 37 ), + /// \brief The SoftwareLimitHigh parameter + PARAMETERID_SoftwareLimitHigh = ( (0 << 24) | 38 ), + /// \brief The MaxCurrentClamp parameter + PARAMETERID_MaxCurrentClamp = ( (0 << 24) | 39 ), + /// \brief The InPositionDistance parameter + PARAMETERID_InPositionDistance = ( (0 << 24) | 40 ), + /// \brief The MotorType parameter + PARAMETERID_MotorType = ( (0 << 24) | 41 ), + /// \brief The CyclesPerRev parameter + PARAMETERID_CyclesPerRev = ( (0 << 24) | 42 ), + /// \brief The CountsPerRev parameter + PARAMETERID_CountsPerRev = ( (0 << 24) | 43 ), + /// \brief The CommutationOffset parameter + PARAMETERID_CommutationOffset = ( (0 << 24) | 44 ), + /// \brief The AutoMsetTime parameter + PARAMETERID_AutoMsetTime = ( (0 << 24) | 45 ), + /// \brief The AutoMsetCurrent parameter + PARAMETERID_AutoMsetCurrent = ( (0 << 24) | 46 ), + /// \brief The PositionFeedbackType parameter + PARAMETERID_PositionFeedbackType = ( (0 << 24) | 47 ), + /// \brief The PositionFeedbackChannel parameter + PARAMETERID_PositionFeedbackChannel = ( (0 << 24) | 48 ), + /// \brief The VelocityFeedbackType parameter + PARAMETERID_VelocityFeedbackType = ( (0 << 24) | 49 ), + /// \brief The VelocityFeedbackChannel parameter + PARAMETERID_VelocityFeedbackChannel = ( (0 << 24) | 50 ), + /// \brief The EncoderMultiplicationFactor parameter + PARAMETERID_EncoderMultiplicationFactor = ( (0 << 24) | 51 ), + /// \brief The EncoderSineGain parameter + PARAMETERID_EncoderSineGain = ( (0 << 24) | 52 ), + /// \brief The EncoderSineOffset parameter + PARAMETERID_EncoderSineOffset = ( (0 << 24) | 53 ), + /// \brief The EncoderCosineGain parameter + PARAMETERID_EncoderCosineGain = ( (0 << 24) | 54 ), + /// \brief The EncoderCosineOffset parameter + PARAMETERID_EncoderCosineOffset = ( (0 << 24) | 55 ), + /// \brief The EncoderPhase parameter + PARAMETERID_EncoderPhase = ( (0 << 24) | 56 ), + /// \brief The GantryMasterAxis parameter + PARAMETERID_GantryMasterAxis = ( (0 << 24) | 57 ), + /// \brief The LimitDecelDistance parameter + PARAMETERID_LimitDecelDistance = ( (0 << 24) | 59 ), + /// \brief The LimitDebounceTime parameter + PARAMETERID_LimitDebounceTime = ( (0 << 24) | 60 ), + /// \brief The EndOfTravelLimitSetup parameter + PARAMETERID_EndOfTravelLimitSetup = ( (0 << 24) | 61 ), + /// \brief The BacklashDistance parameter + PARAMETERID_BacklashDistance = ( (0 << 24) | 62 ), + /// \brief The FaultOutputSetup parameter + PARAMETERID_FaultOutputSetup = ( (0 << 24) | 63 ), + /// \brief The FaultOutputState parameter + PARAMETERID_FaultOutputState = ( (0 << 24) | 64 ), + /// \brief The IOSetup parameter + PARAMETERID_IOSetup = ( (0 << 24) | 65 ), + /// \brief The BrakeOutput parameter + PARAMETERID_BrakeOutput = ( (0 << 24) | 66 ), + /// \brief The EncoderDivider parameter + PARAMETERID_EncoderDivider = ( (0 << 24) | 67 ), + /// \brief The ExternalFaultDigitalInput parameter + PARAMETERID_ExternalFaultDigitalInput = ( (0 << 24) | 68 ), + /// \brief The BrakeDisableDelay parameter + PARAMETERID_BrakeDisableDelay = ( (0 << 24) | 69 ), + /// \brief The MaxJogDistance parameter + PARAMETERID_MaxJogDistance = ( (0 << 24) | 70 ), + /// \brief The DefaultSpeed parameter + PARAMETERID_DefaultSpeed = ( (0 << 24) | 71 ), + /// \brief The DefaultRampRate parameter + PARAMETERID_DefaultRampRate = ( (0 << 24) | 72 ), + /// \brief The AbortDecelRate parameter + PARAMETERID_AbortDecelRate = ( (0 << 24) | 73 ), + /// \brief The HomeType parameter + PARAMETERID_HomeType = ( (0 << 24) | 74 ), + /// \brief The HomeSetup parameter + PARAMETERID_HomeSetup = ( (0 << 24) | 75 ), + /// \brief The HomeSpeed parameter + PARAMETERID_HomeSpeed = ( (0 << 24) | 76 ), + /// \brief The HomeOffset parameter + PARAMETERID_HomeOffset = ( (0 << 24) | 77 ), + /// \brief The HomeRampRate parameter + PARAMETERID_HomeRampRate = ( (0 << 24) | 78 ), + /// \brief The DefaultWaitMode parameter + PARAMETERID_DefaultWaitMode = ( (0 << 24) | 79 ), + /// \brief The DefaultSCurve parameter + PARAMETERID_DefaultSCurve = ( (0 << 24) | 80 ), + /// \brief The DataCollectionPoints parameter + PARAMETERID_DataCollectionPoints = ( (0 << 24) | 81 ), + /// \brief The StepperResolution parameter + PARAMETERID_StepperResolution = ( (0 << 24) | 83 ), + /// \brief The StepperRunningCurrent parameter + PARAMETERID_StepperRunningCurrent = ( (0 << 24) | 84 ), + /// \brief The StepperHoldingCurrent parameter + PARAMETERID_StepperHoldingCurrent = ( (0 << 24) | 85 ), + /// \brief The StepperVerificationSpeed parameter + PARAMETERID_StepperVerificationSpeed = ( (0 << 24) | 86 ), + /// \brief The LimitDebounceDistance parameter + PARAMETERID_LimitDebounceDistance = ( (0 << 24) | 87 ), + /// \brief The ServoFilter2CoeffN0 parameter + PARAMETERID_ServoFilter2CoeffN0 = ( (0 << 24) | 88 ), + /// \brief The ServoFilter2CoeffN1 parameter + PARAMETERID_ServoFilter2CoeffN1 = ( (0 << 24) | 89 ), + /// \brief The ServoFilter2CoeffN2 parameter + PARAMETERID_ServoFilter2CoeffN2 = ( (0 << 24) | 90 ), + /// \brief The ServoFilter2CoeffD1 parameter + PARAMETERID_ServoFilter2CoeffD1 = ( (0 << 24) | 91 ), + /// \brief The ServoFilter2CoeffD2 parameter + PARAMETERID_ServoFilter2CoeffD2 = ( (0 << 24) | 92 ), + /// \brief The ServoFilter3CoeffN0 parameter + PARAMETERID_ServoFilter3CoeffN0 = ( (0 << 24) | 93 ), + /// \brief The ServoFilter3CoeffN1 parameter + PARAMETERID_ServoFilter3CoeffN1 = ( (0 << 24) | 94 ), + /// \brief The ServoFilter3CoeffN2 parameter + PARAMETERID_ServoFilter3CoeffN2 = ( (0 << 24) | 95 ), + /// \brief The ServoFilter3CoeffD1 parameter + PARAMETERID_ServoFilter3CoeffD1 = ( (0 << 24) | 96 ), + /// \brief The ServoFilter3CoeffD2 parameter + PARAMETERID_ServoFilter3CoeffD2 = ( (0 << 24) | 97 ), + /// \brief The GearCamSource parameter + PARAMETERID_GearCamSource = ( (0 << 24) | 98 ), + /// \brief The GearCamIndex parameter + PARAMETERID_GearCamIndex = ( (0 << 24) | 99 ), + /// \brief The GearCamScaleFactor parameter + PARAMETERID_GearCamScaleFactor = ( (0 << 24) | 100 ), + /// \brief The GearCamAnalogDeadband parameter + PARAMETERID_GearCamAnalogDeadband = ( (0 << 24) | 105 ), + /// \brief The PrintBufferSize parameter + PARAMETERID_PrintBufferSize = ( (0 << 24) | 106 ), + /// \brief The SerialPort0XonCharacter parameter + PARAMETERID_SerialPort0XonCharacter = ( (0 << 24) | 109 ), + /// \brief The SerialPort0XoffCharacter parameter + PARAMETERID_SerialPort0XoffCharacter = ( (0 << 24) | 110 ), + /// \brief The SerialPort0BaudRate parameter + PARAMETERID_SerialPort0BaudRate = ( (0 << 24) | 111 ), + /// \brief The SerialPort0Setup parameter + PARAMETERID_SerialPort0Setup = ( (0 << 24) | 112 ), + /// \brief The TaskExecutionSetup parameter + PARAMETERID_TaskExecutionSetup = ( (0 << 24) | 113 ), + /// \brief The CodeSize parameter + PARAMETERID_CodeSize = ( (0 << 24) | 114 ), + /// \brief The DataSize parameter + PARAMETERID_DataSize = ( (0 << 24) | 115 ), + /// \brief The StackSize parameter + PARAMETERID_StackSize = ( (0 << 24) | 116 ), + /// \brief The AutoRunProgram parameter + PARAMETERID_AutoRunProgram = ( (0 << 24) | 118 ), + /// \brief The MaxJogSpeed parameter + PARAMETERID_MaxJogSpeed = ( (0 << 24) | 123 ), + /// \brief The GlobalIntegers parameter + PARAMETERID_GlobalIntegers = ( (0 << 24) | 124 ), + /// \brief The GlobalDoubles parameter + PARAMETERID_GlobalDoubles = ( (0 << 24) | 125 ), + /// \brief The DecimalPlaces parameter + PARAMETERID_DecimalPlaces = ( (0 << 24) | 126 ), + /// \brief The TaskErrorAbortAxes parameter + PARAMETERID_TaskErrorAbortAxes = ( (0 << 24) | 127 ), + /// \brief The CalibrationFile1D parameter + PARAMETERID_CalibrationFile1D = ( (0 << 24) | 128 ), + /// \brief The UnitsName parameter + PARAMETERID_UnitsName = ( (0 << 24) | 129 ), + /// \brief The Socket2RemoteIPAddress parameter + PARAMETERID_Socket2RemoteIPAddress = ( (0 << 24) | 130 ), + /// \brief The Socket2Port parameter + PARAMETERID_Socket2Port = ( (0 << 24) | 131 ), + /// \brief The Socket2Setup parameter + PARAMETERID_Socket2Setup = ( (0 << 24) | 132 ), + /// \brief The Socket2TransmissionSize parameter + PARAMETERID_Socket2TransmissionSize = ( (0 << 24) | 133 ), + /// \brief The Socket3RemoteIPAddress parameter + PARAMETERID_Socket3RemoteIPAddress = ( (0 << 24) | 134 ), + /// \brief The Socket3Port parameter + PARAMETERID_Socket3Port = ( (0 << 24) | 135 ), + /// \brief The Socket3Setup parameter + PARAMETERID_Socket3Setup = ( (0 << 24) | 136 ), + /// \brief The Socket3TransmissionSize parameter + PARAMETERID_Socket3TransmissionSize = ( (0 << 24) | 137 ), + /// \brief The Socket2Timeout parameter + PARAMETERID_Socket2Timeout = ( (0 << 24) | 138 ), + /// \brief The Socket3Timeout parameter + PARAMETERID_Socket3Timeout = ( (0 << 24) | 139 ), + /// \brief The AxisName parameter + PARAMETERID_AxisName = ( (0 << 24) | 140 ), + /// \brief The UserInteger0 parameter + PARAMETERID_UserInteger0 = ( (0 << 24) | 141 ), + /// \brief The UserInteger1 parameter + PARAMETERID_UserInteger1 = ( (0 << 24) | 142 ), + /// \brief The UserDouble0 parameter + PARAMETERID_UserDouble0 = ( (0 << 24) | 143 ), + /// \brief The UserDouble1 parameter + PARAMETERID_UserDouble1 = ( (0 << 24) | 144 ), + /// \brief The UserString0 parameter + PARAMETERID_UserString0 = ( (0 << 24) | 145 ), + /// \brief The UserString1 parameter + PARAMETERID_UserString1 = ( (0 << 24) | 146 ), + /// \brief The EnDatEncoderSetup parameter + PARAMETERID_EnDatEncoderSetup = ( (0 << 24) | 147 ), + /// \brief The EnDatEncoderResolution parameter + PARAMETERID_EnDatEncoderResolution = ( (0 << 24) | 148 ), + /// \brief The EnDatEncoderTurns parameter + PARAMETERID_EnDatEncoderTurns = ( (0 << 24) | 149 ), + /// \brief The CommandSetup parameter + PARAMETERID_CommandSetup = ( (0 << 24) | 150 ), + /// \brief The SerialPort1XonCharacter parameter + PARAMETERID_SerialPort1XonCharacter = ( (0 << 24) | 152 ), + /// \brief The SerialPort1XoffCharacter parameter + PARAMETERID_SerialPort1XoffCharacter = ( (0 << 24) | 153 ), + /// \brief The SerialPort1BaudRate parameter + PARAMETERID_SerialPort1BaudRate = ( (0 << 24) | 154 ), + /// \brief The SerialPort1Setup parameter + PARAMETERID_SerialPort1Setup = ( (0 << 24) | 155 ), + /// \brief The RequiredAxes parameter + PARAMETERID_RequiredAxes = ( (0 << 24) | 156 ), + /// \brief The JoystickInput1MinVoltage parameter + PARAMETERID_JoystickInput1MinVoltage = ( (0 << 24) | 157 ), + /// \brief The JoystickInput1MaxVoltage parameter + PARAMETERID_JoystickInput1MaxVoltage = ( (0 << 24) | 158 ), + /// \brief The JoystickInput1Deadband parameter + PARAMETERID_JoystickInput1Deadband = ( (0 << 24) | 159 ), + /// \brief The JoystickInput0MinVoltage parameter + PARAMETERID_JoystickInput0MinVoltage = ( (0 << 24) | 160 ), + /// \brief The JoystickInput0MaxVoltage parameter + PARAMETERID_JoystickInput0MaxVoltage = ( (0 << 24) | 161 ), + /// \brief The JoystickInput0Deadband parameter + PARAMETERID_JoystickInput0Deadband = ( (0 << 24) | 162 ), + /// \brief The JoystickLowSpeed parameter + PARAMETERID_JoystickLowSpeed = ( (0 << 24) | 163 ), + /// \brief The JoystickHighSpeed parameter + PARAMETERID_JoystickHighSpeed = ( (0 << 24) | 164 ), + /// \brief The JoystickSetup parameter + PARAMETERID_JoystickSetup = ( (0 << 24) | 165 ), + /// \brief The HomePositionSet parameter + PARAMETERID_HomePositionSet = ( (0 << 24) | 166 ), + /// \brief The TaskTerminationAxes parameter + PARAMETERID_TaskTerminationAxes = ( (0 << 24) | 167 ), + /// \brief The TaskStopAbortAxes parameter + PARAMETERID_TaskStopAbortAxes = ( (0 << 24) | 168 ), + /// \brief The CalibrationFile2D parameter + PARAMETERID_CalibrationFile2D = ( (0 << 24) | 169 ), + /// \brief The FaultMaskDisableDelay parameter + PARAMETERID_FaultMaskDisableDelay = ( (0 << 24) | 170 ), + /// \brief The DefaultCoordinatedSpeed parameter + PARAMETERID_DefaultCoordinatedSpeed = ( (0 << 24) | 171 ), + /// \brief The DefaultCoordinatedRampRate parameter + PARAMETERID_DefaultCoordinatedRampRate = ( (0 << 24) | 172 ), + /// \brief The DefaultDependentCoordinatedRampRate parameter + PARAMETERID_DefaultDependentCoordinatedRampRate = ( (0 << 24) | 173 ), + /// \brief The GpibTerminatingCharacter parameter + PARAMETERID_GpibTerminatingCharacter = ( (0 << 24) | 174 ), + /// \brief The GpibPrimaryAddress parameter + PARAMETERID_GpibPrimaryAddress = ( (0 << 24) | 175 ), + /// \brief The GpibParallelResponse parameter + PARAMETERID_GpibParallelResponse = ( (0 << 24) | 176 ), + /// \brief The CommandTerminatingCharacter parameter + PARAMETERID_CommandTerminatingCharacter = ( (0 << 24) | 177 ), + /// \brief The CommandSuccessCharacter parameter + PARAMETERID_CommandSuccessCharacter = ( (0 << 24) | 178 ), + /// \brief The CommandInvalidCharacter parameter + PARAMETERID_CommandInvalidCharacter = ( (0 << 24) | 179 ), + /// \brief The CommandFaultCharacter parameter + PARAMETERID_CommandFaultCharacter = ( (0 << 24) | 180 ), + /// \brief The FaultAbortAxes parameter + PARAMETERID_FaultAbortAxes = ( (0 << 24) | 182 ), + /// \brief The HarmonicCancellation0Type parameter + PARAMETERID_HarmonicCancellation0Type = ( (0 << 24) | 185 ), + /// \brief The HarmonicCancellation0Period parameter + PARAMETERID_HarmonicCancellation0Period = ( (0 << 24) | 186 ), + /// \brief The HarmonicCancellation0Gain parameter + PARAMETERID_HarmonicCancellation0Gain = ( (0 << 24) | 188 ), + /// \brief The HarmonicCancellation0Phase parameter + PARAMETERID_HarmonicCancellation0Phase = ( (0 << 24) | 189 ), + /// \brief The HarmonicCancellation1Type parameter + PARAMETERID_HarmonicCancellation1Type = ( (0 << 24) | 190 ), + /// \brief The HarmonicCancellation1Period parameter + PARAMETERID_HarmonicCancellation1Period = ( (0 << 24) | 191 ), + /// \brief The HarmonicCancellation1Gain parameter + PARAMETERID_HarmonicCancellation1Gain = ( (0 << 24) | 193 ), + /// \brief The HarmonicCancellation1Phase parameter + PARAMETERID_HarmonicCancellation1Phase = ( (0 << 24) | 194 ), + /// \brief The HarmonicCancellation2Type parameter + PARAMETERID_HarmonicCancellation2Type = ( (0 << 24) | 195 ), + /// \brief The HarmonicCancellation2Period parameter + PARAMETERID_HarmonicCancellation2Period = ( (0 << 24) | 196 ), + /// \brief The HarmonicCancellation2Gain parameter + PARAMETERID_HarmonicCancellation2Gain = ( (0 << 24) | 198 ), + /// \brief The HarmonicCancellation2Phase parameter + PARAMETERID_HarmonicCancellation2Phase = ( (0 << 24) | 199 ), + /// \brief The CommandTimeout parameter + PARAMETERID_CommandTimeout = ( (0 << 24) | 202 ), + /// \brief The CommandTimeoutCharacter parameter + PARAMETERID_CommandTimeoutCharacter = ( (0 << 24) | 203 ), + /// \brief The ResolverReferenceGain parameter + PARAMETERID_ResolverReferenceGain = ( (0 << 24) | 204 ), + /// \brief The ResolverSetup parameter + PARAMETERID_ResolverSetup = ( (0 << 24) | 205 ), + /// \brief The ResolverReferencePhase parameter + PARAMETERID_ResolverReferencePhase = ( (0 << 24) | 206 ), + /// \brief The SoftwareLimitSetup parameter + PARAMETERID_SoftwareLimitSetup = ( (0 << 24) | 210 ), + /// \brief The SSINet1Setup parameter + PARAMETERID_SSINet1Setup = ( (0 << 24) | 211 ), + /// \brief The SSINet2Setup parameter + PARAMETERID_SSINet2Setup = ( (0 << 24) | 212 ), + /// \brief The EmulatedQuadratureDivider parameter + PARAMETERID_EmulatedQuadratureDivider = ( (0 << 24) | 213 ), + /// \brief The HarmonicCancellation3Type parameter + PARAMETERID_HarmonicCancellation3Type = ( (0 << 24) | 214 ), + /// \brief The HarmonicCancellation3Period parameter + PARAMETERID_HarmonicCancellation3Period = ( (0 << 24) | 215 ), + /// \brief The HarmonicCancellation3Gain parameter + PARAMETERID_HarmonicCancellation3Gain = ( (0 << 24) | 217 ), + /// \brief The HarmonicCancellation3Phase parameter + PARAMETERID_HarmonicCancellation3Phase = ( (0 << 24) | 218 ), + /// \brief The HarmonicCancellation4Type parameter + PARAMETERID_HarmonicCancellation4Type = ( (0 << 24) | 219 ), + /// \brief The HarmonicCancellation4Period parameter + PARAMETERID_HarmonicCancellation4Period = ( (0 << 24) | 220 ), + /// \brief The HarmonicCancellation4Gain parameter + PARAMETERID_HarmonicCancellation4Gain = ( (0 << 24) | 222 ), + /// \brief The HarmonicCancellation4Phase parameter + PARAMETERID_HarmonicCancellation4Phase = ( (0 << 24) | 223 ), + /// \brief The EnhancedThroughputChannel parameter + PARAMETERID_EnhancedThroughputChannel = ( (0 << 24) | 224 ), + /// \brief The EnhancedThroughputGain parameter + PARAMETERID_EnhancedThroughputGain = ( (0 << 24) | 225 ), + /// \brief The HarmonicCancellationSetup parameter + PARAMETERID_HarmonicCancellationSetup = ( (0 << 24) | 226 ), + /// \brief The EnhancedThroughputCurrentClamp parameter + PARAMETERID_EnhancedThroughputCurrentClamp = ( (0 << 24) | 227 ), + /// \brief The Analog0Filter0CoeffN0 parameter + PARAMETERID_Analog0Filter0CoeffN0 = ( (0 << 24) | 228 ), + /// \brief The Analog0Filter0CoeffN1 parameter + PARAMETERID_Analog0Filter0CoeffN1 = ( (0 << 24) | 229 ), + /// \brief The Analog0Filter0CoeffN2 parameter + PARAMETERID_Analog0Filter0CoeffN2 = ( (0 << 24) | 230 ), + /// \brief The Analog0Filter0CoeffD1 parameter + PARAMETERID_Analog0Filter0CoeffD1 = ( (0 << 24) | 231 ), + /// \brief The Analog0Filter0CoeffD2 parameter + PARAMETERID_Analog0Filter0CoeffD2 = ( (0 << 24) | 232 ), + /// \brief The Analog0Filter1CoeffN0 parameter + PARAMETERID_Analog0Filter1CoeffN0 = ( (0 << 24) | 233 ), + /// \brief The Analog0Filter1CoeffN1 parameter + PARAMETERID_Analog0Filter1CoeffN1 = ( (0 << 24) | 234 ), + /// \brief The Analog0Filter1CoeffN2 parameter + PARAMETERID_Analog0Filter1CoeffN2 = ( (0 << 24) | 235 ), + /// \brief The Analog0Filter1CoeffD1 parameter + PARAMETERID_Analog0Filter1CoeffD1 = ( (0 << 24) | 236 ), + /// \brief The Analog0Filter1CoeffD2 parameter + PARAMETERID_Analog0Filter1CoeffD2 = ( (0 << 24) | 237 ), + /// \brief The Analog1Filter0CoeffN0 parameter + PARAMETERID_Analog1Filter0CoeffN0 = ( (0 << 24) | 238 ), + /// \brief The Analog1Filter0CoeffN1 parameter + PARAMETERID_Analog1Filter0CoeffN1 = ( (0 << 24) | 239 ), + /// \brief The Analog1Filter0CoeffN2 parameter + PARAMETERID_Analog1Filter0CoeffN2 = ( (0 << 24) | 240 ), + /// \brief The Analog1Filter0CoeffD1 parameter + PARAMETERID_Analog1Filter0CoeffD1 = ( (0 << 24) | 241 ), + /// \brief The Analog1Filter0CoeffD2 parameter + PARAMETERID_Analog1Filter0CoeffD2 = ( (0 << 24) | 242 ), + /// \brief The Analog1Filter1CoeffN0 parameter + PARAMETERID_Analog1Filter1CoeffN0 = ( (0 << 24) | 243 ), + /// \brief The Analog1Filter1CoeffN1 parameter + PARAMETERID_Analog1Filter1CoeffN1 = ( (0 << 24) | 244 ), + /// \brief The Analog1Filter1CoeffN2 parameter + PARAMETERID_Analog1Filter1CoeffN2 = ( (0 << 24) | 245 ), + /// \brief The Analog1Filter1CoeffD1 parameter + PARAMETERID_Analog1Filter1CoeffD1 = ( (0 << 24) | 246 ), + /// \brief The Analog1Filter1CoeffD2 parameter + PARAMETERID_Analog1Filter1CoeffD2 = ( (0 << 24) | 247 ), + /// \brief The GlobalStrings parameter + PARAMETERID_GlobalStrings = ( (0 << 24) | 248 ), + /// \brief The DefaultCoordinatedRampMode parameter + PARAMETERID_DefaultCoordinatedRampMode = ( (0 << 24) | 249 ), + /// \brief The DefaultCoordinatedRampTime parameter + PARAMETERID_DefaultCoordinatedRampTime = ( (0 << 24) | 250 ), + /// \brief The DefaultCoordinatedRampDistance parameter + PARAMETERID_DefaultCoordinatedRampDistance = ( (0 << 24) | 251 ), + /// \brief The DefaultRampMode parameter + PARAMETERID_DefaultRampMode = ( (0 << 24) | 252 ), + /// \brief The DefaultRampTime parameter + PARAMETERID_DefaultRampTime = ( (0 << 24) | 253 ), + /// \brief The DefaultRampDistance parameter + PARAMETERID_DefaultRampDistance = ( (0 << 24) | 254 ), + /// \brief The ServoFilterSetup parameter + PARAMETERID_ServoFilterSetup = ( (0 << 24) | 255 ), + /// \brief The FeedbackSetup parameter + PARAMETERID_FeedbackSetup = ( (0 << 24) | 256 ), + /// \brief The EncoderMultiplierSetup parameter + PARAMETERID_EncoderMultiplierSetup = ( (0 << 24) | 257 ), + /// \brief The FaultSetup parameter + PARAMETERID_FaultSetup = ( (0 << 24) | 258 ), + /// \brief The ThresholdScheduleSetup parameter + PARAMETERID_ThresholdScheduleSetup = ( (0 << 24) | 259 ), + /// \brief The ThresholdRegion2High parameter + PARAMETERID_ThresholdRegion2High = ( (0 << 24) | 260 ), + /// \brief The ThresholdRegion2Low parameter + PARAMETERID_ThresholdRegion2Low = ( (0 << 24) | 261 ), + /// \brief The ThresholdRegion3GainKpos parameter + PARAMETERID_ThresholdRegion3GainKpos = ( (0 << 24) | 262 ), + /// \brief The ThresholdRegion3GainKp parameter + PARAMETERID_ThresholdRegion3GainKp = ( (0 << 24) | 263 ), + /// \brief The ThresholdRegion3GainKi parameter + PARAMETERID_ThresholdRegion3GainKi = ( (0 << 24) | 264 ), + /// \brief The ThresholdRegion3GainKpi parameter + PARAMETERID_ThresholdRegion3GainKpi = ( (0 << 24) | 265 ), + /// \brief The ThresholdRegion4High parameter + PARAMETERID_ThresholdRegion4High = ( (0 << 24) | 266 ), + /// \brief The ThresholdRegion4Low parameter + PARAMETERID_ThresholdRegion4Low = ( (0 << 24) | 267 ), + /// \brief The ThresholdRegion5GainKpos parameter + PARAMETERID_ThresholdRegion5GainKpos = ( (0 << 24) | 268 ), + /// \brief The ThresholdRegion5GainKp parameter + PARAMETERID_ThresholdRegion5GainKp = ( (0 << 24) | 269 ), + /// \brief The ThresholdRegion5GainKi parameter + PARAMETERID_ThresholdRegion5GainKi = ( (0 << 24) | 270 ), + /// \brief The ThresholdRegion5GainKpi parameter + PARAMETERID_ThresholdRegion5GainKpi = ( (0 << 24) | 271 ), + /// \brief The DynamicScheduleSetup parameter + PARAMETERID_DynamicScheduleSetup = ( (0 << 24) | 272 ), + /// \brief The DynamicGainKposScale parameter + PARAMETERID_DynamicGainKposScale = ( (0 << 24) | 273 ), + /// \brief The DynamicGainKpScale parameter + PARAMETERID_DynamicGainKpScale = ( (0 << 24) | 274 ), + /// \brief The DynamicGainKiScale parameter + PARAMETERID_DynamicGainKiScale = ( (0 << 24) | 275 ), + /// \brief The ServoFilter4CoeffN0 parameter + PARAMETERID_ServoFilter4CoeffN0 = ( (0 << 24) | 276 ), + /// \brief The ServoFilter4CoeffN1 parameter + PARAMETERID_ServoFilter4CoeffN1 = ( (0 << 24) | 277 ), + /// \brief The ServoFilter4CoeffN2 parameter + PARAMETERID_ServoFilter4CoeffN2 = ( (0 << 24) | 278 ), + /// \brief The ServoFilter4CoeffD1 parameter + PARAMETERID_ServoFilter4CoeffD1 = ( (0 << 24) | 279 ), + /// \brief The ServoFilter4CoeffD2 parameter + PARAMETERID_ServoFilter4CoeffD2 = ( (0 << 24) | 280 ), + /// \brief The ServoFilter5CoeffN0 parameter + PARAMETERID_ServoFilter5CoeffN0 = ( (0 << 24) | 281 ), + /// \brief The ServoFilter5CoeffN1 parameter + PARAMETERID_ServoFilter5CoeffN1 = ( (0 << 24) | 282 ), + /// \brief The ServoFilter5CoeffN2 parameter + PARAMETERID_ServoFilter5CoeffN2 = ( (0 << 24) | 283 ), + /// \brief The ServoFilter5CoeffD1 parameter + PARAMETERID_ServoFilter5CoeffD1 = ( (0 << 24) | 284 ), + /// \brief The ServoFilter5CoeffD2 parameter + PARAMETERID_ServoFilter5CoeffD2 = ( (0 << 24) | 285 ), + /// \brief The ServoFilter6CoeffN0 parameter + PARAMETERID_ServoFilter6CoeffN0 = ( (0 << 24) | 286 ), + /// \brief The ServoFilter6CoeffN1 parameter + PARAMETERID_ServoFilter6CoeffN1 = ( (0 << 24) | 287 ), + /// \brief The ServoFilter6CoeffN2 parameter + PARAMETERID_ServoFilter6CoeffN2 = ( (0 << 24) | 288 ), + /// \brief The ServoFilter6CoeffD1 parameter + PARAMETERID_ServoFilter6CoeffD1 = ( (0 << 24) | 289 ), + /// \brief The ServoFilter6CoeffD2 parameter + PARAMETERID_ServoFilter6CoeffD2 = ( (0 << 24) | 290 ), + /// \brief The ServoFilter7CoeffN0 parameter + PARAMETERID_ServoFilter7CoeffN0 = ( (0 << 24) | 291 ), + /// \brief The ServoFilter7CoeffN1 parameter + PARAMETERID_ServoFilter7CoeffN1 = ( (0 << 24) | 292 ), + /// \brief The ServoFilter7CoeffN2 parameter + PARAMETERID_ServoFilter7CoeffN2 = ( (0 << 24) | 293 ), + /// \brief The ServoFilter7CoeffD1 parameter + PARAMETERID_ServoFilter7CoeffD1 = ( (0 << 24) | 294 ), + /// \brief The ServoFilter7CoeffD2 parameter + PARAMETERID_ServoFilter7CoeffD2 = ( (0 << 24) | 295 ), + /// \brief The LinearAmpMaxPower parameter + PARAMETERID_LinearAmpMaxPower = ( (0 << 24) | 296 ), + /// \brief The LinearAmpDeratingFactor parameter + PARAMETERID_LinearAmpDeratingFactor = ( (0 << 24) | 297 ), + /// \brief The LinearAmpBusVoltage parameter + PARAMETERID_LinearAmpBusVoltage = ( (0 << 24) | 298 ), + /// \brief The MotorResistance parameter + PARAMETERID_MotorResistance = ( (0 << 24) | 299 ), + /// \brief The MotorBackEMFConstant parameter + PARAMETERID_MotorBackEMFConstant = ( (0 << 24) | 300 ), + /// \brief The GantrySetup parameter + PARAMETERID_GantrySetup = ( (0 << 24) | 302 ), + /// \brief The RolloverMode parameter + PARAMETERID_RolloverMode = ( (0 << 24) | 303 ), + /// \brief The EmulatedQuadratureChannel parameter + PARAMETERID_EmulatedQuadratureChannel = ( (0 << 24) | 305 ), + /// \brief The ResolverCoarseChannel parameter + PARAMETERID_ResolverCoarseChannel = ( (0 << 24) | 306 ), + /// \brief The ResolverFeedbackRatio parameter + PARAMETERID_ResolverFeedbackRatio = ( (0 << 24) | 307 ), + /// \brief The ResolverFeedbackOffset parameter + PARAMETERID_ResolverFeedbackOffset = ( (0 << 24) | 308 ), + /// \brief The BrakeEnableDelay parameter + PARAMETERID_BrakeEnableDelay = ( (0 << 24) | 309 ), + /// \brief The InPositionTime parameter + PARAMETERID_InPositionTime = ( (0 << 24) | 319 ), + /// \brief The StaticFrictionCompensation parameter + PARAMETERID_StaticFrictionCompensation = ( (0 << 24) | 324 ), + /// \brief The ExternalFaultAnalogInput parameter + PARAMETERID_ExternalFaultAnalogInput = ( (0 << 24) | 424 ), + /// \brief The ExternalFaultThreshold parameter + PARAMETERID_ExternalFaultThreshold = ( (0 << 24) | 425 ), + /// \brief The DisplayAxes parameter + PARAMETERID_DisplayAxes = ( (0 << 24) | 426 ), + /// \brief The DefaultDependentCoordinatedSpeed parameter + PARAMETERID_DefaultDependentCoordinatedSpeed = ( (0 << 24) | 427 ), + /// \brief The AnalogFilterSetup parameter + PARAMETERID_AnalogFilterSetup = ( (0 << 24) | 482 ), + /// \brief The DefaultRampType parameter + PARAMETERID_DefaultRampType = ( (0 << 24) | 485 ), + /// \brief The ModbusMasterSlaveIPAddress parameter + PARAMETERID_ModbusMasterSlaveIPAddress = ( (0 << 24) | 489 ), + /// \brief The ModbusMasterSlavePort parameter + PARAMETERID_ModbusMasterSlavePort = ( (0 << 24) | 490 ), + /// \brief The ModbusMasterSlaveID parameter + PARAMETERID_ModbusMasterSlaveID = ( (0 << 24) | 491 ), + /// \brief The ModbusMasterInputWords parameter + PARAMETERID_ModbusMasterInputWords = ( (0 << 24) | 492 ), + /// \brief The ModbusMasterOutputWords parameter + PARAMETERID_ModbusMasterOutputWords = ( (0 << 24) | 493 ), + /// \brief The ModbusMasterInputBits parameter + PARAMETERID_ModbusMasterInputBits = ( (0 << 24) | 494 ), + /// \brief The ModbusMasterOutputBits parameter + PARAMETERID_ModbusMasterOutputBits = ( (0 << 24) | 495 ), + /// \brief The ModbusMasterSetup parameter + PARAMETERID_ModbusMasterSetup = ( (0 << 24) | 496 ), + /// \brief The ModbusMasterVirtualInputs parameter + PARAMETERID_ModbusMasterVirtualInputs = ( (0 << 24) | 499 ), + /// \brief The ModbusMasterVirtualOutputs parameter + PARAMETERID_ModbusMasterVirtualOutputs = ( (0 << 24) | 500 ), + /// \brief The ModbusMasterOutputWordsSections parameter + PARAMETERID_ModbusMasterOutputWordsSections = ( (0 << 24) | 501 ), + /// \brief The ModbusMasterOutputBitsSections parameter + PARAMETERID_ModbusMasterOutputBitsSections = ( (0 << 24) | 502 ), + /// \brief The ModbusMasterRWReadOffset parameter + PARAMETERID_ModbusMasterRWReadOffset = ( (0 << 24) | 503 ), + /// \brief The ModbusMasterInputWordsOffset parameter + PARAMETERID_ModbusMasterInputWordsOffset = ( (0 << 24) | 504 ), + /// \brief The ModbusMasterOutputWordsOffset parameter + PARAMETERID_ModbusMasterOutputWordsOffset = ( (0 << 24) | 505 ), + /// \brief The ModbusMasterInputBitsOffset parameter + PARAMETERID_ModbusMasterInputBitsOffset = ( (0 << 24) | 506 ), + /// \brief The ModbusMasterOutputBitsOffset parameter + PARAMETERID_ModbusMasterOutputBitsOffset = ( (0 << 24) | 507 ), + /// \brief The ModbusMasterStatusWordsOffset parameter + PARAMETERID_ModbusMasterStatusWordsOffset = ( (0 << 24) | 508 ), + /// \brief The ModbusMasterStatusBitsOffset parameter + PARAMETERID_ModbusMasterStatusBitsOffset = ( (0 << 24) | 509 ), + /// \brief The ModbusMasterVirtualInputsOffset parameter + PARAMETERID_ModbusMasterVirtualInputsOffset = ( (0 << 24) | 510 ), + /// \brief The ModbusMasterVirtualOutputsOffset parameter + PARAMETERID_ModbusMasterVirtualOutputsOffset = ( (0 << 24) | 511 ), + /// \brief The ModbusMasterRWWriteOffset parameter + PARAMETERID_ModbusMasterRWWriteOffset = ( (0 << 24) | 512 ), + /// \brief The ModbusMasterFunctions parameter + PARAMETERID_ModbusMasterFunctions = ( (0 << 24) | 513 ), + /// \brief The ModbusMasterSlaveType parameter + PARAMETERID_ModbusMasterSlaveType = ( (0 << 24) | 514 ), + /// \brief The ModbusSlaveUnitID parameter + PARAMETERID_ModbusSlaveUnitID = ( (0 << 24) | 516 ), + /// \brief The ModbusSlaveInputWords parameter + PARAMETERID_ModbusSlaveInputWords = ( (0 << 24) | 517 ), + /// \brief The ModbusSlaveOutputWords parameter + PARAMETERID_ModbusSlaveOutputWords = ( (0 << 24) | 518 ), + /// \brief The ModbusSlaveInputBits parameter + PARAMETERID_ModbusSlaveInputBits = ( (0 << 24) | 519 ), + /// \brief The ModbusSlaveOutputBits parameter + PARAMETERID_ModbusSlaveOutputBits = ( (0 << 24) | 520 ), + /// \brief The ModbusSlaveInputWordsOffset parameter + PARAMETERID_ModbusSlaveInputWordsOffset = ( (0 << 24) | 521 ), + /// \brief The ModbusSlaveOutputWordsOffset parameter + PARAMETERID_ModbusSlaveOutputWordsOffset = ( (0 << 24) | 522 ), + /// \brief The ModbusSlaveInputBitsOffset parameter + PARAMETERID_ModbusSlaveInputBitsOffset = ( (0 << 24) | 523 ), + /// \brief The ModbusSlaveOutputBitsOffset parameter + PARAMETERID_ModbusSlaveOutputBitsOffset = ( (0 << 24) | 524 ), + /// \brief The ModbusSlaveRWReadOffset parameter + PARAMETERID_ModbusSlaveRWReadOffset = ( (0 << 24) | 525 ), + /// \brief The ModbusSlaveRWWriteOffset parameter + PARAMETERID_ModbusSlaveRWWriteOffset = ( (0 << 24) | 526 ), + /// \brief The CurrentOffsetA parameter + PARAMETERID_CurrentOffsetA = ( (0 << 24) | 662 ), + /// \brief The CurrentOffsetB parameter + PARAMETERID_CurrentOffsetB = ( (0 << 24) | 663 ), + /// \brief The FaultAckMoveOutOfLimit parameter + PARAMETERID_FaultAckMoveOutOfLimit = ( (0 << 24) | 665 ), + /// \brief The CommandShaperSetup parameter + PARAMETERID_CommandShaperSetup = ( (0 << 24) | 666 ), + /// \brief The CommandShaperTime00 parameter + PARAMETERID_CommandShaperTime00 = ( (0 << 24) | 667 ), + /// \brief The CommandShaperTime01 parameter + PARAMETERID_CommandShaperTime01 = ( (0 << 24) | 668 ), + /// \brief The CommandShaperTime02 parameter + PARAMETERID_CommandShaperTime02 = ( (0 << 24) | 669 ), + /// \brief The CommandShaperTime03 parameter + PARAMETERID_CommandShaperTime03 = ( (0 << 24) | 670 ), + /// \brief The CommandShaperTime04 parameter + PARAMETERID_CommandShaperTime04 = ( (0 << 24) | 671 ), + /// \brief The CommandShaperTime05 parameter + PARAMETERID_CommandShaperTime05 = ( (0 << 24) | 672 ), + /// \brief The CommandShaperTime06 parameter + PARAMETERID_CommandShaperTime06 = ( (0 << 24) | 673 ), + /// \brief The CommandShaperTime07 parameter + PARAMETERID_CommandShaperTime07 = ( (0 << 24) | 674 ), + /// \brief The CommandShaperTime08 parameter + PARAMETERID_CommandShaperTime08 = ( (0 << 24) | 675 ), + /// \brief The CommandShaperTime09 parameter + PARAMETERID_CommandShaperTime09 = ( (0 << 24) | 676 ), + /// \brief The CommandShaperTime10 parameter + PARAMETERID_CommandShaperTime10 = ( (0 << 24) | 677 ), + /// \brief The CommandShaperTime11 parameter + PARAMETERID_CommandShaperTime11 = ( (0 << 24) | 678 ), + /// \brief The CommandShaperTime12 parameter + PARAMETERID_CommandShaperTime12 = ( (0 << 24) | 679 ), + /// \brief The CommandShaperTime13 parameter + PARAMETERID_CommandShaperTime13 = ( (0 << 24) | 680 ), + /// \brief The CommandShaperTime14 parameter + PARAMETERID_CommandShaperTime14 = ( (0 << 24) | 681 ), + /// \brief The CommandShaperTime15 parameter + PARAMETERID_CommandShaperTime15 = ( (0 << 24) | 682 ), + /// \brief The CommandShaperCoeff00 parameter + PARAMETERID_CommandShaperCoeff00 = ( (0 << 24) | 683 ), + /// \brief The CommandShaperCoeff01 parameter + PARAMETERID_CommandShaperCoeff01 = ( (0 << 24) | 684 ), + /// \brief The CommandShaperCoeff02 parameter + PARAMETERID_CommandShaperCoeff02 = ( (0 << 24) | 685 ), + /// \brief The CommandShaperCoeff03 parameter + PARAMETERID_CommandShaperCoeff03 = ( (0 << 24) | 686 ), + /// \brief The CommandShaperCoeff04 parameter + PARAMETERID_CommandShaperCoeff04 = ( (0 << 24) | 687 ), + /// \brief The CommandShaperCoeff05 parameter + PARAMETERID_CommandShaperCoeff05 = ( (0 << 24) | 688 ), + /// \brief The CommandShaperCoeff06 parameter + PARAMETERID_CommandShaperCoeff06 = ( (0 << 24) | 689 ), + /// \brief The CommandShaperCoeff07 parameter + PARAMETERID_CommandShaperCoeff07 = ( (0 << 24) | 690 ), + /// \brief The CommandShaperCoeff08 parameter + PARAMETERID_CommandShaperCoeff08 = ( (0 << 24) | 691 ), + /// \brief The CommandShaperCoeff09 parameter + PARAMETERID_CommandShaperCoeff09 = ( (0 << 24) | 692 ), + /// \brief The CommandShaperCoeff10 parameter + PARAMETERID_CommandShaperCoeff10 = ( (0 << 24) | 693 ), + /// \brief The CommandShaperCoeff11 parameter + PARAMETERID_CommandShaperCoeff11 = ( (0 << 24) | 694 ), + /// \brief The CommandShaperCoeff12 parameter + PARAMETERID_CommandShaperCoeff12 = ( (0 << 24) | 695 ), + /// \brief The CommandShaperCoeff13 parameter + PARAMETERID_CommandShaperCoeff13 = ( (0 << 24) | 696 ), + /// \brief The CommandShaperCoeff14 parameter + PARAMETERID_CommandShaperCoeff14 = ( (0 << 24) | 697 ), + /// \brief The CommandShaperCoeff15 parameter + PARAMETERID_CommandShaperCoeff15 = ( (0 << 24) | 698 ), + /// \brief The CommandShaper0Type parameter + PARAMETERID_CommandShaper0Type = ( (0 << 24) | 703 ), + /// \brief The CommandShaper0Frequency parameter + PARAMETERID_CommandShaper0Frequency = ( (0 << 24) | 704 ), + /// \brief The CommandShaper0Damping parameter + PARAMETERID_CommandShaper0Damping = ( (0 << 24) | 705 ), + /// \brief The CommandShaper1Type parameter + PARAMETERID_CommandShaper1Type = ( (0 << 24) | 706 ), + /// \brief The CommandShaper1Frequency parameter + PARAMETERID_CommandShaper1Frequency = ( (0 << 24) | 707 ), + /// \brief The CommandShaper1Damping parameter + PARAMETERID_CommandShaper1Damping = ( (0 << 24) | 708 ), + /// \brief The ResoluteEncoderSetup parameter + PARAMETERID_ResoluteEncoderSetup = ( (0 << 24) | 715 ), + /// \brief The ResoluteEncoderResolution parameter + PARAMETERID_ResoluteEncoderResolution = ( (0 << 24) | 716 ), + /// \brief The ResoluteEncoderUserResolution parameter + PARAMETERID_ResoluteEncoderUserResolution = ( (0 << 24) | 717 ), + /// \brief The AutofocusInput parameter + PARAMETERID_AutofocusInput = ( (0 << 24) | 721 ), + /// \brief The AutofocusTarget parameter + PARAMETERID_AutofocusTarget = ( (0 << 24) | 722 ), + /// \brief The AutofocusDeadband parameter + PARAMETERID_AutofocusDeadband = ( (0 << 24) | 723 ), + /// \brief The AutofocusGainKi parameter + PARAMETERID_AutofocusGainKi = ( (0 << 24) | 724 ), + /// \brief The AutofocusGainKp parameter + PARAMETERID_AutofocusGainKp = ( (0 << 24) | 725 ), + /// \brief The AutofocusLimitLow parameter + PARAMETERID_AutofocusLimitLow = ( (0 << 24) | 726 ), + /// \brief The AutofocusLimitHigh parameter + PARAMETERID_AutofocusLimitHigh = ( (0 << 24) | 727 ), + /// \brief The AutofocusSpeedClamp parameter + PARAMETERID_AutofocusSpeedClamp = ( (0 << 24) | 728 ), + /// \brief The AutofocusHoldInput parameter + PARAMETERID_AutofocusHoldInput = ( (0 << 24) | 729 ), + /// \brief The AutofocusSetup parameter + PARAMETERID_AutofocusSetup = ( (0 << 24) | 730 ), + /// \brief The ExternalSyncFrequency parameter + PARAMETERID_ExternalSyncFrequency = ( (0 << 24) | 731 ), + /// \brief The GainPff parameter + PARAMETERID_GainPff = ( (0 << 24) | 762 ), + /// \brief The AutofocusInitialRampTime parameter + PARAMETERID_AutofocusInitialRampTime = ( (0 << 24) | 763 ), + /// \brief The SoftwareExternalFaultInput parameter + PARAMETERID_SoftwareExternalFaultInput = ( (0 << 24) | 765 ), + /// \brief The AutofocusGainKi2 parameter + PARAMETERID_AutofocusGainKi2 = ( (0 << 24) | 769 ), + /// \brief The EnDatEncoderIncrementalResolution parameter + PARAMETERID_EnDatEncoderIncrementalResolution = ( (0 << 24) | 770 ), + /// \brief The MarkerSearchThreshold parameter + PARAMETERID_MarkerSearchThreshold = ( (0 << 24) | 771 ), + /// \brief The GainKd1 parameter + PARAMETERID_GainKd1 = ( (0 << 24) | 779 ), + /// \brief The GainKp1 parameter + PARAMETERID_GainKp1 = ( (0 << 24) | 780 ), + /// \brief The VelocityCommandThresholdBeforeHome parameter + PARAMETERID_VelocityCommandThresholdBeforeHome = ( (0 << 24) | 781 ), + /// \brief The InPosition2Distance parameter + PARAMETERID_InPosition2Distance = ( (0 << 24) | 789 ), + /// \brief The InPosition2Time parameter + PARAMETERID_InPosition2Time = ( (0 << 24) | 790 ), + /// \brief The StepperRunningCurrentDelay parameter + PARAMETERID_StepperRunningCurrentDelay = ( (0 << 24) | 791 ), + /// \brief The ExternalVelocityAverageTime parameter + PARAMETERID_ExternalVelocityAverageTime = ( (0 << 24) | 792 ), + /// \brief The Class1InputIntegers parameter + PARAMETERID_Class1InputIntegers = ( (0 << 24) | 794 ), + /// \brief The Class1InputIntegersOffset parameter + PARAMETERID_Class1InputIntegersOffset = ( (0 << 24) | 795 ), + /// \brief The Class1OutputIntegers parameter + PARAMETERID_Class1OutputIntegers = ( (0 << 24) | 796 ), + /// \brief The Class1OutputIntegersOffset parameter + PARAMETERID_Class1OutputIntegersOffset = ( (0 << 24) | 797 ), + /// \brief The Class1InputDoubles parameter + PARAMETERID_Class1InputDoubles = ( (0 << 24) | 798 ), + /// \brief The Class1InputDoublesOffset parameter + PARAMETERID_Class1InputDoublesOffset = ( (0 << 24) | 799 ), + /// \brief The Class1OutputDoubles parameter + PARAMETERID_Class1OutputDoubles = ( (0 << 24) | 800 ), + /// \brief The Class1OutputDoublesOffset parameter + PARAMETERID_Class1OutputDoublesOffset = ( (0 << 24) | 801 ), + /// \brief The AbsoluteFeedbackOffset parameter + PARAMETERID_AbsoluteFeedbackOffset = ( (0 << 24) | 802 ), + /// \brief The PiezoSetup parameter + PARAMETERID_PiezoSetup = ( (0 << 24) | 803 ), + /// \brief The CapSensorFilterLength parameter + PARAMETERID_CapSensorFilterLength = ( (0 << 24) | 804 ), + /// \brief The EnhancedTrackingScale parameter + PARAMETERID_EnhancedTrackingScale = ( (0 << 24) | 805 ), + /// \brief The EnhancedTrackingBandwidth parameter + PARAMETERID_EnhancedTrackingBandwidth = ( (0 << 24) | 806 ), + /// \brief The Analog0InputOffset parameter + PARAMETERID_Analog0InputOffset = ( (0 << 24) | 807 ), + /// \brief The Analog1InputOffset parameter + PARAMETERID_Analog1InputOffset = ( (0 << 24) | 808 ), + /// \brief The Analog2InputOffset parameter + PARAMETERID_Analog2InputOffset = ( (0 << 24) | 809 ), + /// \brief The Analog3InputOffset parameter + PARAMETERID_Analog3InputOffset = ( (0 << 24) | 810 ), + /// \brief The EnhancedTrackingSetup parameter + PARAMETERID_EnhancedTrackingSetup = ( (0 << 24) | 811 ), + /// \brief The WebServerSetup parameter + PARAMETERID_WebServerSetup = ( (0 << 24) | 812 ), + /// \brief The WebServerPort parameter + PARAMETERID_WebServerPort = ( (0 << 24) | 813 ), + /// \brief The EncoderMarkerAlignment parameter + PARAMETERID_EncoderMarkerAlignment = ( (0 << 24) | 814 ), + /// \brief The EncoderRadiusThresholdLow parameter + PARAMETERID_EncoderRadiusThresholdLow = ( (0 << 24) | 815 ), + /// \brief The EncoderRadiusThresholdHigh parameter + PARAMETERID_EncoderRadiusThresholdHigh = ( (0 << 24) | 816 ), + /// \brief The GainKsi1 parameter + PARAMETERID_GainKsi1 = ( (0 << 24) | 817 ), + /// \brief The GainKsi2 parameter + PARAMETERID_GainKsi2 = ( (0 << 24) | 818 ), + /// \brief The PiezoVoltsPerUnit parameter + PARAMETERID_PiezoVoltsPerUnit = ( (0 << 24) | 819 ), + /// \brief The PiezoVoltageClampLow parameter + PARAMETERID_PiezoVoltageClampLow = ( (0 << 24) | 820 ), + /// \brief The PiezoVoltageClampHigh parameter + PARAMETERID_PiezoVoltageClampHigh = ( (0 << 24) | 821 ), + /// \brief The PiezoSlewRateClamp parameter + PARAMETERID_PiezoSlewRateClamp = ( (0 << 24) | 822 ), + /// \brief The PiezoDefaultServoState parameter + PARAMETERID_PiezoDefaultServoState = ( (0 << 24) | 823 ), + /// \brief The FeedforwardAdvance parameter + PARAMETERID_FeedforwardAdvance = ( (0 << 24) | 824 ), + /// \brief The CapSensorSetup parameter + PARAMETERID_CapSensorSetup = ( (0 << 24) | 826 ), + /// \brief The CapSensorThresholdLow parameter + PARAMETERID_CapSensorThresholdLow = ( (0 << 24) | 828 ), + /// \brief The CapSensorThresholdHigh parameter + PARAMETERID_CapSensorThresholdHigh = ( (0 << 24) | 829 ), + /// \brief The RequiredStageSerialNumber parameter + PARAMETERID_RequiredStageSerialNumber = ( (0 << 24) | 832 ), + /// \brief The StepperDampingGain parameter + PARAMETERID_StepperDampingGain = ( (0 << 24) | 848 ), + /// \brief The StepperDampingCutoffFrequency parameter + PARAMETERID_StepperDampingCutoffFrequency = ( (0 << 24) | 849 ), +} PARAMETERID; + +#endif // __Ensemble_PARAMETER_ID_H__ diff --git a/motorApp/AerotechSrc/Makefile b/motorApp/AerotechSrc/Makefile index e9ed009..646bf8a 100644 --- a/motorApp/AerotechSrc/Makefile +++ b/motorApp/AerotechSrc/Makefile @@ -6,6 +6,9 @@ include $(TOP)/configure/CONFIG #!USR_CXXFLAGS += -DDEBUG DBD += devAerotech.dbd +ifdef SNCSEQ +DBD += devAerotechSeq.dbd +endif LIBRARY_IOC = Aerotech @@ -18,11 +21,15 @@ SRCS += drvA3200Asyn.cc # EnsemblePSOFly.db support SRCS += concatString.c +ifdef SNCSEQ # Ensemble trajectory support SRCS += EnsembleTrajectoryScan.st +endif Aerotech_LIBS += motor asyn +ifdef SNCSEQ Aerotech_LIBS += seq pv +endif Aerotech_LIBS += $(EPICS_BASE_IOC_LIBS) include $(TOP)/configure/RULES diff --git a/motorApp/AerotechSrc/ParameterId.h b/motorApp/AerotechSrc/ParameterId.h index a2da635..e527f8a 100644 --- a/motorApp/AerotechSrc/ParameterId.h +++ b/motorApp/AerotechSrc/ParameterId.h @@ -1,768 +1,768 @@ -/// \file ParameterId.h -/// \brief File contains parameter identifiers -/// -/// This file is version dependant and needs to match the rest of the software - -#ifndef __PARAMETER_ID_H__ -#define __PARAMETER_ID_H__ - - -/// \brief Represents a parameter identifier -typedef enum { - /// \brief The AxisType parameter - PARAMETERID_AxisType = ( (0 << 24) | 0 ), - /// \brief The ReverseMotionDirection parameter - PARAMETERID_ReverseMotionDirection = ( (0 << 24) | 1 ), - /// \brief The CountsPerUnit parameter - PARAMETERID_CountsPerUnit = ( (0 << 24) | 2 ), - /// \brief The ServoRate parameter - PARAMETERID_ServoRate = ( (0 << 24) | 3 ), - /// \brief The ServoSetup parameter - PARAMETERID_ServoSetup = ( (0 << 24) | 4 ), - /// \brief The GainKpos parameter - PARAMETERID_GainKpos = ( (0 << 24) | 5 ), - /// \brief The GainKi parameter - PARAMETERID_GainKi = ( (0 << 24) | 6 ), - /// \brief The GainKp parameter - PARAMETERID_GainKp = ( (0 << 24) | 7 ), - /// \brief The GainVff parameter - PARAMETERID_GainVff = ( (0 << 24) | 8 ), - /// \brief The GainAff parameter - PARAMETERID_GainAff = ( (0 << 24) | 9 ), - /// \brief The GainKv parameter - PARAMETERID_GainKv = ( (0 << 24) | 10 ), - /// \brief The GainKpi parameter - PARAMETERID_GainKpi = ( (0 << 24) | 11 ), - /// \brief The ServoFilter0CoeffN0 parameter - PARAMETERID_ServoFilter0CoeffN0 = ( (0 << 24) | 12 ), - /// \brief The ServoFilter0CoeffN1 parameter - PARAMETERID_ServoFilter0CoeffN1 = ( (0 << 24) | 13 ), - /// \brief The ServoFilter0CoeffN2 parameter - PARAMETERID_ServoFilter0CoeffN2 = ( (0 << 24) | 14 ), - /// \brief The ServoFilter0CoeffD1 parameter - PARAMETERID_ServoFilter0CoeffD1 = ( (0 << 24) | 15 ), - /// \brief The ServoFilter0CoeffD2 parameter - PARAMETERID_ServoFilter0CoeffD2 = ( (0 << 24) | 16 ), - /// \brief The ServoFilter1CoeffN0 parameter - PARAMETERID_ServoFilter1CoeffN0 = ( (0 << 24) | 17 ), - /// \brief The ServoFilter1CoeffN1 parameter - PARAMETERID_ServoFilter1CoeffN1 = ( (0 << 24) | 18 ), - /// \brief The ServoFilter1CoeffN2 parameter - PARAMETERID_ServoFilter1CoeffN2 = ( (0 << 24) | 19 ), - /// \brief The ServoFilter1CoeffD1 parameter - PARAMETERID_ServoFilter1CoeffD1 = ( (0 << 24) | 20 ), - /// \brief The ServoFilter1CoeffD2 parameter - PARAMETERID_ServoFilter1CoeffD2 = ( (0 << 24) | 21 ), - /// \brief The AmplifierDeadtime parameter - PARAMETERID_AmplifierDeadtime = ( (0 << 24) | 22 ), - /// \brief The RolloverCounts parameter - PARAMETERID_RolloverCounts = ( (0 << 24) | 23 ), - /// \brief The CurrentGainKi parameter - PARAMETERID_CurrentGainKi = ( (0 << 24) | 24 ), - /// \brief The CurrentGainKp parameter - PARAMETERID_CurrentGainKp = ( (0 << 24) | 25 ), - /// \brief The FaultMask parameter - PARAMETERID_FaultMask = ( (0 << 24) | 26 ), - /// \brief The FaultMaskDisable parameter - PARAMETERID_FaultMaskDisable = ( (0 << 24) | 27 ), - /// \brief The FaultMaskDecel parameter - PARAMETERID_FaultMaskDecel = ( (0 << 24) | 28 ), - /// \brief The EnableBrakeControl parameter - PARAMETERID_EnableBrakeControl = ( (0 << 24) | 29 ), - /// \brief The FaultMaskOutput parameter - PARAMETERID_FaultMaskOutput = ( (0 << 24) | 30 ), - /// \brief The ESTOPFaultInput parameter - PARAMETERID_ESTOPFaultInput = ( (0 << 24) | 31 ), - /// \brief The PositionErrorThreshold parameter - PARAMETERID_PositionErrorThreshold = ( (0 << 24) | 32 ), - /// \brief The AverageCurrentThreshold parameter - PARAMETERID_AverageCurrentThreshold = ( (0 << 24) | 33 ), - /// \brief The AverageCurrentTime parameter - PARAMETERID_AverageCurrentTime = ( (0 << 24) | 34 ), - /// \brief The VelocityCommandThreshold parameter - PARAMETERID_VelocityCommandThreshold = ( (0 << 24) | 35 ), - /// \brief The VelocityErrorThreshold parameter - PARAMETERID_VelocityErrorThreshold = ( (0 << 24) | 36 ), - /// \brief The SoftwareLimitLow parameter - PARAMETERID_SoftwareLimitLow = ( (0 << 24) | 37 ), - /// \brief The SoftwareLimitHigh parameter - PARAMETERID_SoftwareLimitHigh = ( (0 << 24) | 38 ), - /// \brief The MaxCurrentClamp parameter - PARAMETERID_MaxCurrentClamp = ( (0 << 24) | 39 ), - /// \brief The InPositionDistance parameter - PARAMETERID_InPositionDistance = ( (0 << 24) | 40 ), - /// \brief The MotorType parameter - PARAMETERID_MotorType = ( (0 << 24) | 41 ), - /// \brief The CyclesPerRev parameter - PARAMETERID_CyclesPerRev = ( (0 << 24) | 42 ), - /// \brief The CountsPerRev parameter - PARAMETERID_CountsPerRev = ( (0 << 24) | 43 ), - /// \brief The CommutationOffset parameter - PARAMETERID_CommutationOffset = ( (0 << 24) | 44 ), - /// \brief The AutoMsetTime parameter - PARAMETERID_AutoMsetTime = ( (0 << 24) | 45 ), - /// \brief The AutoMsetCurrent parameter - PARAMETERID_AutoMsetCurrent = ( (0 << 24) | 46 ), - /// \brief The PositionFeedbackType parameter - PARAMETERID_PositionFeedbackType = ( (0 << 24) | 47 ), - /// \brief The PositionFeedbackChannel parameter - PARAMETERID_PositionFeedbackChannel = ( (0 << 24) | 48 ), - /// \brief The VelocityFeedbackType parameter - PARAMETERID_VelocityFeedbackType = ( (0 << 24) | 49 ), - /// \brief The VelocityFeedbackChannel parameter - PARAMETERID_VelocityFeedbackChannel = ( (0 << 24) | 50 ), - /// \brief The EncoderMultiplicationFactor parameter - PARAMETERID_EncoderMultiplicationFactor = ( (0 << 24) | 51 ), - /// \brief The EncoderSineGain parameter - PARAMETERID_EncoderSineGain = ( (0 << 24) | 52 ), - /// \brief The EncoderSineOffset parameter - PARAMETERID_EncoderSineOffset = ( (0 << 24) | 53 ), - /// \brief The EncoderCosineGain parameter - PARAMETERID_EncoderCosineGain = ( (0 << 24) | 54 ), - /// \brief The EncoderCosineOffset parameter - PARAMETERID_EncoderCosineOffset = ( (0 << 24) | 55 ), - /// \brief The EncoderPhase parameter - PARAMETERID_EncoderPhase = ( (0 << 24) | 56 ), - /// \brief The GantryMasterAxis parameter - PARAMETERID_GantryMasterAxis = ( (0 << 24) | 57 ), - /// \brief The LimitDecelDistance parameter - PARAMETERID_LimitDecelDistance = ( (0 << 24) | 59 ), - /// \brief The LimitDebounceTime parameter - PARAMETERID_LimitDebounceTime = ( (0 << 24) | 60 ), - /// \brief The EndOfTravelLimitSetup parameter - PARAMETERID_EndOfTravelLimitSetup = ( (0 << 24) | 61 ), - /// \brief The BacklashDistance parameter - PARAMETERID_BacklashDistance = ( (0 << 24) | 62 ), - /// \brief The FaultOutputSetup parameter - PARAMETERID_FaultOutputSetup = ( (0 << 24) | 63 ), - /// \brief The FaultOutputState parameter - PARAMETERID_FaultOutputState = ( (0 << 24) | 64 ), - /// \brief The IOSetup parameter - PARAMETERID_IOSetup = ( (0 << 24) | 65 ), - /// \brief The BrakeOutput parameter - PARAMETERID_BrakeOutput = ( (0 << 24) | 66 ), - /// \brief The EncoderDivider parameter - PARAMETERID_EncoderDivider = ( (0 << 24) | 67 ), - /// \brief The ExternalFaultDigitalInput parameter - PARAMETERID_ExternalFaultDigitalInput = ( (0 << 24) | 68 ), - /// \brief The BrakeDisableDelay parameter - PARAMETERID_BrakeDisableDelay = ( (0 << 24) | 69 ), - /// \brief The MaxJogDistance parameter - PARAMETERID_MaxJogDistance = ( (0 << 24) | 70 ), - /// \brief The DefaultSpeed parameter - PARAMETERID_DefaultSpeed = ( (0 << 24) | 71 ), - /// \brief The DefaultRampRate parameter - PARAMETERID_DefaultRampRate = ( (0 << 24) | 72 ), - /// \brief The AbortDecelRate parameter - PARAMETERID_AbortDecelRate = ( (0 << 24) | 73 ), - /// \brief The HomeType parameter - PARAMETERID_HomeType = ( (0 << 24) | 74 ), - /// \brief The HomeSetup parameter - PARAMETERID_HomeSetup = ( (0 << 24) | 75 ), - /// \brief The HomeSpeed parameter - PARAMETERID_HomeSpeed = ( (0 << 24) | 76 ), - /// \brief The HomeOffset parameter - PARAMETERID_HomeOffset = ( (0 << 24) | 77 ), - /// \brief The HomeRampRate parameter - PARAMETERID_HomeRampRate = ( (0 << 24) | 78 ), - /// \brief The DefaultWaitMode parameter - PARAMETERID_DefaultWaitMode = ( (0 << 24) | 79 ), - /// \brief The DefaultSCurve parameter - PARAMETERID_DefaultSCurve = ( (0 << 24) | 80 ), - /// \brief The DataCollectionPoints parameter - PARAMETERID_DataCollectionPoints = ( (0 << 24) | 81 ), - /// \brief The StepperResolution parameter - PARAMETERID_StepperResolution = ( (0 << 24) | 83 ), - /// \brief The StepperRunningCurrent parameter - PARAMETERID_StepperRunningCurrent = ( (0 << 24) | 84 ), - /// \brief The StepperHoldingCurrent parameter - PARAMETERID_StepperHoldingCurrent = ( (0 << 24) | 85 ), - /// \brief The StepperVerificationSpeed parameter - PARAMETERID_StepperVerificationSpeed = ( (0 << 24) | 86 ), - /// \brief The LimitDebounceDistance parameter - PARAMETERID_LimitDebounceDistance = ( (0 << 24) | 87 ), - /// \brief The ServoFilter2CoeffN0 parameter - PARAMETERID_ServoFilter2CoeffN0 = ( (0 << 24) | 88 ), - /// \brief The ServoFilter2CoeffN1 parameter - PARAMETERID_ServoFilter2CoeffN1 = ( (0 << 24) | 89 ), - /// \brief The ServoFilter2CoeffN2 parameter - PARAMETERID_ServoFilter2CoeffN2 = ( (0 << 24) | 90 ), - /// \brief The ServoFilter2CoeffD1 parameter - PARAMETERID_ServoFilter2CoeffD1 = ( (0 << 24) | 91 ), - /// \brief The ServoFilter2CoeffD2 parameter - PARAMETERID_ServoFilter2CoeffD2 = ( (0 << 24) | 92 ), - /// \brief The ServoFilter3CoeffN0 parameter - PARAMETERID_ServoFilter3CoeffN0 = ( (0 << 24) | 93 ), - /// \brief The ServoFilter3CoeffN1 parameter - PARAMETERID_ServoFilter3CoeffN1 = ( (0 << 24) | 94 ), - /// \brief The ServoFilter3CoeffN2 parameter - PARAMETERID_ServoFilter3CoeffN2 = ( (0 << 24) | 95 ), - /// \brief The ServoFilter3CoeffD1 parameter - PARAMETERID_ServoFilter3CoeffD1 = ( (0 << 24) | 96 ), - /// \brief The ServoFilter3CoeffD2 parameter - PARAMETERID_ServoFilter3CoeffD2 = ( (0 << 24) | 97 ), - /// \brief The GearCamSource parameter - PARAMETERID_GearCamSource = ( (0 << 24) | 98 ), - /// \brief The GearCamIndex parameter - PARAMETERID_GearCamIndex = ( (0 << 24) | 99 ), - /// \brief The GearCamScaleFactor parameter - PARAMETERID_GearCamScaleFactor = ( (0 << 24) | 100 ), - /// \brief The GearCamAnalogDeadband parameter - PARAMETERID_GearCamAnalogDeadband = ( (0 << 24) | 105 ), - /// \brief The PrintBufferSize parameter - PARAMETERID_PrintBufferSize = ( (0 << 24) | 106 ), - /// \brief The SerialPort0XonCharacter parameter - PARAMETERID_SerialPort0XonCharacter = ( (0 << 24) | 109 ), - /// \brief The SerialPort0XoffCharacter parameter - PARAMETERID_SerialPort0XoffCharacter = ( (0 << 24) | 110 ), - /// \brief The SerialPort0BaudRate parameter - PARAMETERID_SerialPort0BaudRate = ( (0 << 24) | 111 ), - /// \brief The SerialPort0Setup parameter - PARAMETERID_SerialPort0Setup = ( (0 << 24) | 112 ), - /// \brief The TaskExecutionSetup parameter - PARAMETERID_TaskExecutionSetup = ( (0 << 24) | 113 ), - /// \brief The CodeSize parameter - PARAMETERID_CodeSize = ( (0 << 24) | 114 ), - /// \brief The DataSize parameter - PARAMETERID_DataSize = ( (0 << 24) | 115 ), - /// \brief The StackSize parameter - PARAMETERID_StackSize = ( (0 << 24) | 116 ), - /// \brief The AutoRunProgram parameter - PARAMETERID_AutoRunProgram = ( (0 << 24) | 118 ), - /// \brief The MaxJogSpeed parameter - PARAMETERID_MaxJogSpeed = ( (0 << 24) | 123 ), - /// \brief The GlobalIntegers parameter - PARAMETERID_GlobalIntegers = ( (0 << 24) | 124 ), - /// \brief The GlobalDoubles parameter - PARAMETERID_GlobalDoubles = ( (0 << 24) | 125 ), - /// \brief The DecimalPlaces parameter - PARAMETERID_DecimalPlaces = ( (0 << 24) | 126 ), - /// \brief The TaskErrorAbortAxes parameter - PARAMETERID_TaskErrorAbortAxes = ( (0 << 24) | 127 ), - /// \brief The CalibrationFile1D parameter - PARAMETERID_CalibrationFile1D = ( (0 << 24) | 128 ), - /// \brief The UnitsName parameter - PARAMETERID_UnitsName = ( (0 << 24) | 129 ), - /// \brief The Socket2RemoteIPAddress parameter - PARAMETERID_Socket2RemoteIPAddress = ( (0 << 24) | 130 ), - /// \brief The Socket2Port parameter - PARAMETERID_Socket2Port = ( (0 << 24) | 131 ), - /// \brief The Socket2Setup parameter - PARAMETERID_Socket2Setup = ( (0 << 24) | 132 ), - /// \brief The Socket2TransmissionSize parameter - PARAMETERID_Socket2TransmissionSize = ( (0 << 24) | 133 ), - /// \brief The Socket3RemoteIPAddress parameter - PARAMETERID_Socket3RemoteIPAddress = ( (0 << 24) | 134 ), - /// \brief The Socket3Port parameter - PARAMETERID_Socket3Port = ( (0 << 24) | 135 ), - /// \brief The Socket3Setup parameter - PARAMETERID_Socket3Setup = ( (0 << 24) | 136 ), - /// \brief The Socket3TransmissionSize parameter - PARAMETERID_Socket3TransmissionSize = ( (0 << 24) | 137 ), - /// \brief The Socket2Timeout parameter - PARAMETERID_Socket2Timeout = ( (0 << 24) | 138 ), - /// \brief The Socket3Timeout parameter - PARAMETERID_Socket3Timeout = ( (0 << 24) | 139 ), - /// \brief The AxisName parameter - PARAMETERID_AxisName = ( (0 << 24) | 140 ), - /// \brief The UserInteger0 parameter - PARAMETERID_UserInteger0 = ( (0 << 24) | 141 ), - /// \brief The UserInteger1 parameter - PARAMETERID_UserInteger1 = ( (0 << 24) | 142 ), - /// \brief The UserDouble0 parameter - PARAMETERID_UserDouble0 = ( (0 << 24) | 143 ), - /// \brief The UserDouble1 parameter - PARAMETERID_UserDouble1 = ( (0 << 24) | 144 ), - /// \brief The UserString0 parameter - PARAMETERID_UserString0 = ( (0 << 24) | 145 ), - /// \brief The UserString1 parameter - PARAMETERID_UserString1 = ( (0 << 24) | 146 ), - /// \brief The EnDatEncoderSetup parameter - PARAMETERID_EnDatEncoderSetup = ( (0 << 24) | 147 ), - /// \brief The EnDatEncoderResolution parameter - PARAMETERID_EnDatEncoderResolution = ( (0 << 24) | 148 ), - /// \brief The EnDatEncoderTurns parameter - PARAMETERID_EnDatEncoderTurns = ( (0 << 24) | 149 ), - /// \brief The CommandSetup parameter - PARAMETERID_CommandSetup = ( (0 << 24) | 150 ), - /// \brief The SerialPort1XonCharacter parameter - PARAMETERID_SerialPort1XonCharacter = ( (0 << 24) | 152 ), - /// \brief The SerialPort1XoffCharacter parameter - PARAMETERID_SerialPort1XoffCharacter = ( (0 << 24) | 153 ), - /// \brief The SerialPort1BaudRate parameter - PARAMETERID_SerialPort1BaudRate = ( (0 << 24) | 154 ), - /// \brief The SerialPort1Setup parameter - PARAMETERID_SerialPort1Setup = ( (0 << 24) | 155 ), - /// \brief The RequiredAxes parameter - PARAMETERID_RequiredAxes = ( (0 << 24) | 156 ), - /// \brief The JoystickInput1MinVoltage parameter - PARAMETERID_JoystickInput1MinVoltage = ( (0 << 24) | 157 ), - /// \brief The JoystickInput1MaxVoltage parameter - PARAMETERID_JoystickInput1MaxVoltage = ( (0 << 24) | 158 ), - /// \brief The JoystickInput1Deadband parameter - PARAMETERID_JoystickInput1Deadband = ( (0 << 24) | 159 ), - /// \brief The JoystickInput0MinVoltage parameter - PARAMETERID_JoystickInput0MinVoltage = ( (0 << 24) | 160 ), - /// \brief The JoystickInput0MaxVoltage parameter - PARAMETERID_JoystickInput0MaxVoltage = ( (0 << 24) | 161 ), - /// \brief The JoystickInput0Deadband parameter - PARAMETERID_JoystickInput0Deadband = ( (0 << 24) | 162 ), - /// \brief The JoystickLowSpeed parameter - PARAMETERID_JoystickLowSpeed = ( (0 << 24) | 163 ), - /// \brief The JoystickHighSpeed parameter - PARAMETERID_JoystickHighSpeed = ( (0 << 24) | 164 ), - /// \brief The JoystickSetup parameter - PARAMETERID_JoystickSetup = ( (0 << 24) | 165 ), - /// \brief The HomePositionSet parameter - PARAMETERID_HomePositionSet = ( (0 << 24) | 166 ), - /// \brief The TaskTerminationAxes parameter - PARAMETERID_TaskTerminationAxes = ( (0 << 24) | 167 ), - /// \brief The TaskStopAbortAxes parameter - PARAMETERID_TaskStopAbortAxes = ( (0 << 24) | 168 ), - /// \brief The CalibrationFile2D parameter - PARAMETERID_CalibrationFile2D = ( (0 << 24) | 169 ), - /// \brief The FaultMaskDisableDelay parameter - PARAMETERID_FaultMaskDisableDelay = ( (0 << 24) | 170 ), - /// \brief The DefaultCoordinatedSpeed parameter - PARAMETERID_DefaultCoordinatedSpeed = ( (0 << 24) | 171 ), - /// \brief The DefaultCoordinatedRampRate parameter - PARAMETERID_DefaultCoordinatedRampRate = ( (0 << 24) | 172 ), - /// \brief The DefaultDependentCoordinatedRampRate parameter - PARAMETERID_DefaultDependentCoordinatedRampRate = ( (0 << 24) | 173 ), - /// \brief The GpibTerminatingCharacter parameter - PARAMETERID_GpibTerminatingCharacter = ( (0 << 24) | 174 ), - /// \brief The GpibPrimaryAddress parameter - PARAMETERID_GpibPrimaryAddress = ( (0 << 24) | 175 ), - /// \brief The GpibParallelResponse parameter - PARAMETERID_GpibParallelResponse = ( (0 << 24) | 176 ), - /// \brief The CommandTerminatingCharacter parameter - PARAMETERID_CommandTerminatingCharacter = ( (0 << 24) | 177 ), - /// \brief The CommandSuccessCharacter parameter - PARAMETERID_CommandSuccessCharacter = ( (0 << 24) | 178 ), - /// \brief The CommandInvalidCharacter parameter - PARAMETERID_CommandInvalidCharacter = ( (0 << 24) | 179 ), - /// \brief The CommandFaultCharacter parameter - PARAMETERID_CommandFaultCharacter = ( (0 << 24) | 180 ), - /// \brief The FaultAbortAxes parameter - PARAMETERID_FaultAbortAxes = ( (0 << 24) | 182 ), - /// \brief The HarmonicCancellation0Type parameter - PARAMETERID_HarmonicCancellation0Type = ( (0 << 24) | 185 ), - /// \brief The HarmonicCancellation0Period parameter - PARAMETERID_HarmonicCancellation0Period = ( (0 << 24) | 186 ), - /// \brief The HarmonicCancellation0Gain parameter - PARAMETERID_HarmonicCancellation0Gain = ( (0 << 24) | 188 ), - /// \brief The HarmonicCancellation0Phase parameter - PARAMETERID_HarmonicCancellation0Phase = ( (0 << 24) | 189 ), - /// \brief The HarmonicCancellation1Type parameter - PARAMETERID_HarmonicCancellation1Type = ( (0 << 24) | 190 ), - /// \brief The HarmonicCancellation1Period parameter - PARAMETERID_HarmonicCancellation1Period = ( (0 << 24) | 191 ), - /// \brief The HarmonicCancellation1Gain parameter - PARAMETERID_HarmonicCancellation1Gain = ( (0 << 24) | 193 ), - /// \brief The HarmonicCancellation1Phase parameter - PARAMETERID_HarmonicCancellation1Phase = ( (0 << 24) | 194 ), - /// \brief The HarmonicCancellation2Type parameter - PARAMETERID_HarmonicCancellation2Type = ( (0 << 24) | 195 ), - /// \brief The HarmonicCancellation2Period parameter - PARAMETERID_HarmonicCancellation2Period = ( (0 << 24) | 196 ), - /// \brief The HarmonicCancellation2Gain parameter - PARAMETERID_HarmonicCancellation2Gain = ( (0 << 24) | 198 ), - /// \brief The HarmonicCancellation2Phase parameter - PARAMETERID_HarmonicCancellation2Phase = ( (0 << 24) | 199 ), - /// \brief The CommandTimeout parameter - PARAMETERID_CommandTimeout = ( (0 << 24) | 202 ), - /// \brief The CommandTimeoutCharacter parameter - PARAMETERID_CommandTimeoutCharacter = ( (0 << 24) | 203 ), - /// \brief The ResolverReferenceGain parameter - PARAMETERID_ResolverReferenceGain = ( (0 << 24) | 204 ), - /// \brief The ResolverSetup parameter - PARAMETERID_ResolverSetup = ( (0 << 24) | 205 ), - /// \brief The ResolverReferencePhase parameter - PARAMETERID_ResolverReferencePhase = ( (0 << 24) | 206 ), - /// \brief The SoftwareLimitSetup parameter - PARAMETERID_SoftwareLimitSetup = ( (0 << 24) | 210 ), - /// \brief The SSINet1Setup parameter - PARAMETERID_SSINet1Setup = ( (0 << 24) | 211 ), - /// \brief The SSINet2Setup parameter - PARAMETERID_SSINet2Setup = ( (0 << 24) | 212 ), - /// \brief The EmulatedQuadratureDivider parameter - PARAMETERID_EmulatedQuadratureDivider = ( (0 << 24) | 213 ), - /// \brief The HarmonicCancellation3Type parameter - PARAMETERID_HarmonicCancellation3Type = ( (0 << 24) | 214 ), - /// \brief The HarmonicCancellation3Period parameter - PARAMETERID_HarmonicCancellation3Period = ( (0 << 24) | 215 ), - /// \brief The HarmonicCancellation3Gain parameter - PARAMETERID_HarmonicCancellation3Gain = ( (0 << 24) | 217 ), - /// \brief The HarmonicCancellation3Phase parameter - PARAMETERID_HarmonicCancellation3Phase = ( (0 << 24) | 218 ), - /// \brief The HarmonicCancellation4Type parameter - PARAMETERID_HarmonicCancellation4Type = ( (0 << 24) | 219 ), - /// \brief The HarmonicCancellation4Period parameter - PARAMETERID_HarmonicCancellation4Period = ( (0 << 24) | 220 ), - /// \brief The HarmonicCancellation4Gain parameter - PARAMETERID_HarmonicCancellation4Gain = ( (0 << 24) | 222 ), - /// \brief The HarmonicCancellation4Phase parameter - PARAMETERID_HarmonicCancellation4Phase = ( (0 << 24) | 223 ), - /// \brief The EnhancedThroughputChannel parameter - PARAMETERID_EnhancedThroughputChannel = ( (0 << 24) | 224 ), - /// \brief The EnhancedThroughputGain parameter - PARAMETERID_EnhancedThroughputGain = ( (0 << 24) | 225 ), - /// \brief The HarmonicCancellationSetup parameter - PARAMETERID_HarmonicCancellationSetup = ( (0 << 24) | 226 ), - /// \brief The EnhancedThroughputCurrentClamp parameter - PARAMETERID_EnhancedThroughputCurrentClamp = ( (0 << 24) | 227 ), - /// \brief The Analog0Filter0CoeffN0 parameter - PARAMETERID_Analog0Filter0CoeffN0 = ( (0 << 24) | 228 ), - /// \brief The Analog0Filter0CoeffN1 parameter - PARAMETERID_Analog0Filter0CoeffN1 = ( (0 << 24) | 229 ), - /// \brief The Analog0Filter0CoeffN2 parameter - PARAMETERID_Analog0Filter0CoeffN2 = ( (0 << 24) | 230 ), - /// \brief The Analog0Filter0CoeffD1 parameter - PARAMETERID_Analog0Filter0CoeffD1 = ( (0 << 24) | 231 ), - /// \brief The Analog0Filter0CoeffD2 parameter - PARAMETERID_Analog0Filter0CoeffD2 = ( (0 << 24) | 232 ), - /// \brief The Analog0Filter1CoeffN0 parameter - PARAMETERID_Analog0Filter1CoeffN0 = ( (0 << 24) | 233 ), - /// \brief The Analog0Filter1CoeffN1 parameter - PARAMETERID_Analog0Filter1CoeffN1 = ( (0 << 24) | 234 ), - /// \brief The Analog0Filter1CoeffN2 parameter - PARAMETERID_Analog0Filter1CoeffN2 = ( (0 << 24) | 235 ), - /// \brief The Analog0Filter1CoeffD1 parameter - PARAMETERID_Analog0Filter1CoeffD1 = ( (0 << 24) | 236 ), - /// \brief The Analog0Filter1CoeffD2 parameter - PARAMETERID_Analog0Filter1CoeffD2 = ( (0 << 24) | 237 ), - /// \brief The Analog1Filter0CoeffN0 parameter - PARAMETERID_Analog1Filter0CoeffN0 = ( (0 << 24) | 238 ), - /// \brief The Analog1Filter0CoeffN1 parameter - PARAMETERID_Analog1Filter0CoeffN1 = ( (0 << 24) | 239 ), - /// \brief The Analog1Filter0CoeffN2 parameter - PARAMETERID_Analog1Filter0CoeffN2 = ( (0 << 24) | 240 ), - /// \brief The Analog1Filter0CoeffD1 parameter - PARAMETERID_Analog1Filter0CoeffD1 = ( (0 << 24) | 241 ), - /// \brief The Analog1Filter0CoeffD2 parameter - PARAMETERID_Analog1Filter0CoeffD2 = ( (0 << 24) | 242 ), - /// \brief The Analog1Filter1CoeffN0 parameter - PARAMETERID_Analog1Filter1CoeffN0 = ( (0 << 24) | 243 ), - /// \brief The Analog1Filter1CoeffN1 parameter - PARAMETERID_Analog1Filter1CoeffN1 = ( (0 << 24) | 244 ), - /// \brief The Analog1Filter1CoeffN2 parameter - PARAMETERID_Analog1Filter1CoeffN2 = ( (0 << 24) | 245 ), - /// \brief The Analog1Filter1CoeffD1 parameter - PARAMETERID_Analog1Filter1CoeffD1 = ( (0 << 24) | 246 ), - /// \brief The Analog1Filter1CoeffD2 parameter - PARAMETERID_Analog1Filter1CoeffD2 = ( (0 << 24) | 247 ), - /// \brief The GlobalStrings parameter - PARAMETERID_GlobalStrings = ( (0 << 24) | 248 ), - /// \brief The DefaultCoordinatedRampMode parameter - PARAMETERID_DefaultCoordinatedRampMode = ( (0 << 24) | 249 ), - /// \brief The DefaultCoordinatedRampTime parameter - PARAMETERID_DefaultCoordinatedRampTime = ( (0 << 24) | 250 ), - /// \brief The DefaultCoordinatedRampDistance parameter - PARAMETERID_DefaultCoordinatedRampDistance = ( (0 << 24) | 251 ), - /// \brief The DefaultRampMode parameter - PARAMETERID_DefaultRampMode = ( (0 << 24) | 252 ), - /// \brief The DefaultRampTime parameter - PARAMETERID_DefaultRampTime = ( (0 << 24) | 253 ), - /// \brief The DefaultRampDistance parameter - PARAMETERID_DefaultRampDistance = ( (0 << 24) | 254 ), - /// \brief The ServoFilterSetup parameter - PARAMETERID_ServoFilterSetup = ( (0 << 24) | 255 ), - /// \brief The FeedbackSetup parameter - PARAMETERID_FeedbackSetup = ( (0 << 24) | 256 ), - /// \brief The EncoderMultiplierSetup parameter - PARAMETERID_EncoderMultiplierSetup = ( (0 << 24) | 257 ), - /// \brief The FaultSetup parameter - PARAMETERID_FaultSetup = ( (0 << 24) | 258 ), - /// \brief The ThresholdScheduleSetup parameter - PARAMETERID_ThresholdScheduleSetup = ( (0 << 24) | 259 ), - /// \brief The ThresholdRegion2High parameter - PARAMETERID_ThresholdRegion2High = ( (0 << 24) | 260 ), - /// \brief The ThresholdRegion2Low parameter - PARAMETERID_ThresholdRegion2Low = ( (0 << 24) | 261 ), - /// \brief The ThresholdRegion3GainKpos parameter - PARAMETERID_ThresholdRegion3GainKpos = ( (0 << 24) | 262 ), - /// \brief The ThresholdRegion3GainKp parameter - PARAMETERID_ThresholdRegion3GainKp = ( (0 << 24) | 263 ), - /// \brief The ThresholdRegion3GainKi parameter - PARAMETERID_ThresholdRegion3GainKi = ( (0 << 24) | 264 ), - /// \brief The ThresholdRegion3GainKpi parameter - PARAMETERID_ThresholdRegion3GainKpi = ( (0 << 24) | 265 ), - /// \brief The ThresholdRegion4High parameter - PARAMETERID_ThresholdRegion4High = ( (0 << 24) | 266 ), - /// \brief The ThresholdRegion4Low parameter - PARAMETERID_ThresholdRegion4Low = ( (0 << 24) | 267 ), - /// \brief The ThresholdRegion5GainKpos parameter - PARAMETERID_ThresholdRegion5GainKpos = ( (0 << 24) | 268 ), - /// \brief The ThresholdRegion5GainKp parameter - PARAMETERID_ThresholdRegion5GainKp = ( (0 << 24) | 269 ), - /// \brief The ThresholdRegion5GainKi parameter - PARAMETERID_ThresholdRegion5GainKi = ( (0 << 24) | 270 ), - /// \brief The ThresholdRegion5GainKpi parameter - PARAMETERID_ThresholdRegion5GainKpi = ( (0 << 24) | 271 ), - /// \brief The DynamicScheduleSetup parameter - PARAMETERID_DynamicScheduleSetup = ( (0 << 24) | 272 ), - /// \brief The DynamicGainKposScale parameter - PARAMETERID_DynamicGainKposScale = ( (0 << 24) | 273 ), - /// \brief The DynamicGainKpScale parameter - PARAMETERID_DynamicGainKpScale = ( (0 << 24) | 274 ), - /// \brief The DynamicGainKiScale parameter - PARAMETERID_DynamicGainKiScale = ( (0 << 24) | 275 ), - /// \brief The ServoFilter4CoeffN0 parameter - PARAMETERID_ServoFilter4CoeffN0 = ( (0 << 24) | 276 ), - /// \brief The ServoFilter4CoeffN1 parameter - PARAMETERID_ServoFilter4CoeffN1 = ( (0 << 24) | 277 ), - /// \brief The ServoFilter4CoeffN2 parameter - PARAMETERID_ServoFilter4CoeffN2 = ( (0 << 24) | 278 ), - /// \brief The ServoFilter4CoeffD1 parameter - PARAMETERID_ServoFilter4CoeffD1 = ( (0 << 24) | 279 ), - /// \brief The ServoFilter4CoeffD2 parameter - PARAMETERID_ServoFilter4CoeffD2 = ( (0 << 24) | 280 ), - /// \brief The ServoFilter5CoeffN0 parameter - PARAMETERID_ServoFilter5CoeffN0 = ( (0 << 24) | 281 ), - /// \brief The ServoFilter5CoeffN1 parameter - PARAMETERID_ServoFilter5CoeffN1 = ( (0 << 24) | 282 ), - /// \brief The ServoFilter5CoeffN2 parameter - PARAMETERID_ServoFilter5CoeffN2 = ( (0 << 24) | 283 ), - /// \brief The ServoFilter5CoeffD1 parameter - PARAMETERID_ServoFilter5CoeffD1 = ( (0 << 24) | 284 ), - /// \brief The ServoFilter5CoeffD2 parameter - PARAMETERID_ServoFilter5CoeffD2 = ( (0 << 24) | 285 ), - /// \brief The ServoFilter6CoeffN0 parameter - PARAMETERID_ServoFilter6CoeffN0 = ( (0 << 24) | 286 ), - /// \brief The ServoFilter6CoeffN1 parameter - PARAMETERID_ServoFilter6CoeffN1 = ( (0 << 24) | 287 ), - /// \brief The ServoFilter6CoeffN2 parameter - PARAMETERID_ServoFilter6CoeffN2 = ( (0 << 24) | 288 ), - /// \brief The ServoFilter6CoeffD1 parameter - PARAMETERID_ServoFilter6CoeffD1 = ( (0 << 24) | 289 ), - /// \brief The ServoFilter6CoeffD2 parameter - PARAMETERID_ServoFilter6CoeffD2 = ( (0 << 24) | 290 ), - /// \brief The ServoFilter7CoeffN0 parameter - PARAMETERID_ServoFilter7CoeffN0 = ( (0 << 24) | 291 ), - /// \brief The ServoFilter7CoeffN1 parameter - PARAMETERID_ServoFilter7CoeffN1 = ( (0 << 24) | 292 ), - /// \brief The ServoFilter7CoeffN2 parameter - PARAMETERID_ServoFilter7CoeffN2 = ( (0 << 24) | 293 ), - /// \brief The ServoFilter7CoeffD1 parameter - PARAMETERID_ServoFilter7CoeffD1 = ( (0 << 24) | 294 ), - /// \brief The ServoFilter7CoeffD2 parameter - PARAMETERID_ServoFilter7CoeffD2 = ( (0 << 24) | 295 ), - /// \brief The LinearAmpMaxPower parameter - PARAMETERID_LinearAmpMaxPower = ( (0 << 24) | 296 ), - /// \brief The LinearAmpDeratingFactor parameter - PARAMETERID_LinearAmpDeratingFactor = ( (0 << 24) | 297 ), - /// \brief The LinearAmpBusVoltage parameter - PARAMETERID_LinearAmpBusVoltage = ( (0 << 24) | 298 ), - /// \brief The MotorResistance parameter - PARAMETERID_MotorResistance = ( (0 << 24) | 299 ), - /// \brief The MotorBackEMFConstant parameter - PARAMETERID_MotorBackEMFConstant = ( (0 << 24) | 300 ), - /// \brief The GantrySetup parameter - PARAMETERID_GantrySetup = ( (0 << 24) | 302 ), - /// \brief The RolloverMode parameter - PARAMETERID_RolloverMode = ( (0 << 24) | 303 ), - /// \brief The ResolverCoarseChannel parameter - PARAMETERID_ResolverCoarseChannel = ( (0 << 24) | 306 ), - /// \brief The ResolverFeedbackRatio parameter - PARAMETERID_ResolverFeedbackRatio = ( (0 << 24) | 307 ), - /// \brief The ResolverFeedbackOffset parameter - PARAMETERID_ResolverFeedbackOffset = ( (0 << 24) | 308 ), - /// \brief The InPositionTime parameter - PARAMETERID_InPositionTime = ( (0 << 24) | 319 ), - /// \brief The ExternalFaultAnalogInput parameter - PARAMETERID_ExternalFaultAnalogInput = ( (0 << 24) | 424 ), - /// \brief The ExternalFaultThreshold parameter - PARAMETERID_ExternalFaultThreshold = ( (0 << 24) | 425 ), - /// \brief The DisplayAxes parameter - PARAMETERID_DisplayAxes = ( (0 << 24) | 426 ), - /// \brief The DefaultDependentCoordinatedSpeed parameter - PARAMETERID_DefaultDependentCoordinatedSpeed = ( (0 << 24) | 427 ), - /// \brief The AnalogFilterSetup parameter - PARAMETERID_AnalogFilterSetup = ( (0 << 24) | 482 ), - /// \brief The ModbusMasterSlaveIPAddress parameter - PARAMETERID_ModbusMasterSlaveIPAddress = ( (0 << 24) | 489 ), - /// \brief The ModbusMasterSlavePort parameter - PARAMETERID_ModbusMasterSlavePort = ( (0 << 24) | 490 ), - /// \brief The ModbusMasterSlaveID parameter - PARAMETERID_ModbusMasterSlaveID = ( (0 << 24) | 491 ), - /// \brief The ModbusMasterInputWords parameter - PARAMETERID_ModbusMasterInputWords = ( (0 << 24) | 492 ), - /// \brief The ModbusMasterOutputWords parameter - PARAMETERID_ModbusMasterOutputWords = ( (0 << 24) | 493 ), - /// \brief The ModbusMasterInputBits parameter - PARAMETERID_ModbusMasterInputBits = ( (0 << 24) | 494 ), - /// \brief The ModbusMasterOutputBits parameter - PARAMETERID_ModbusMasterOutputBits = ( (0 << 24) | 495 ), - /// \brief The ModbusMasterSetup parameter - PARAMETERID_ModbusMasterSetup = ( (0 << 24) | 496 ), - /// \brief The ModbusMasterVirtualInputs parameter - PARAMETERID_ModbusMasterVirtualInputs = ( (0 << 24) | 499 ), - /// \brief The ModbusMasterVirtualOutputs parameter - PARAMETERID_ModbusMasterVirtualOutputs = ( (0 << 24) | 500 ), - /// \brief The ModbusMasterOutputWordsSections parameter - PARAMETERID_ModbusMasterOutputWordsSections = ( (0 << 24) | 501 ), - /// \brief The ModbusMasterOutputBitsSections parameter - PARAMETERID_ModbusMasterOutputBitsSections = ( (0 << 24) | 502 ), - /// \brief The ModbusMasterRWReadOffset parameter - PARAMETERID_ModbusMasterRWReadOffset = ( (0 << 24) | 503 ), - /// \brief The ModbusMasterInputWordsOffset parameter - PARAMETERID_ModbusMasterInputWordsOffset = ( (0 << 24) | 504 ), - /// \brief The ModbusMasterOutputWordsOffset parameter - PARAMETERID_ModbusMasterOutputWordsOffset = ( (0 << 24) | 505 ), - /// \brief The ModbusMasterInputBitsOffset parameter - PARAMETERID_ModbusMasterInputBitsOffset = ( (0 << 24) | 506 ), - /// \brief The ModbusMasterOutputBitsOffset parameter - PARAMETERID_ModbusMasterOutputBitsOffset = ( (0 << 24) | 507 ), - /// \brief The ModbusMasterStatusWordsOffset parameter - PARAMETERID_ModbusMasterStatusWordsOffset = ( (0 << 24) | 508 ), - /// \brief The ModbusMasterStatusBitsOffset parameter - PARAMETERID_ModbusMasterStatusBitsOffset = ( (0 << 24) | 509 ), - /// \brief The ModbusMasterVirtualInputsOffset parameter - PARAMETERID_ModbusMasterVirtualInputsOffset = ( (0 << 24) | 510 ), - /// \brief The ModbusMasterVirtualOutputsOffset parameter - PARAMETERID_ModbusMasterVirtualOutputsOffset = ( (0 << 24) | 511 ), - /// \brief The ModbusMasterRWWriteOffset parameter - PARAMETERID_ModbusMasterRWWriteOffset = ( (0 << 24) | 512 ), - /// \brief The ModbusMasterFunctions parameter - PARAMETERID_ModbusMasterFunctions = ( (0 << 24) | 513 ), - /// \brief The ModbusMasterSlaveType parameter - PARAMETERID_ModbusMasterSlaveType = ( (0 << 24) | 514 ), - /// \brief The ModbusSlaveUnitID parameter - PARAMETERID_ModbusSlaveUnitID = ( (0 << 24) | 516 ), - /// \brief The ModbusSlaveInputWords parameter - PARAMETERID_ModbusSlaveInputWords = ( (0 << 24) | 517 ), - /// \brief The ModbusSlaveOutputWords parameter - PARAMETERID_ModbusSlaveOutputWords = ( (0 << 24) | 518 ), - /// \brief The ModbusSlaveInputBits parameter - PARAMETERID_ModbusSlaveInputBits = ( (0 << 24) | 519 ), - /// \brief The ModbusSlaveOutputBits parameter - PARAMETERID_ModbusSlaveOutputBits = ( (0 << 24) | 520 ), - /// \brief The ModbusSlaveInputWordsOffset parameter - PARAMETERID_ModbusSlaveInputWordsOffset = ( (0 << 24) | 521 ), - /// \brief The ModbusSlaveOutputWordsOffset parameter - PARAMETERID_ModbusSlaveOutputWordsOffset = ( (0 << 24) | 522 ), - /// \brief The ModbusSlaveInputBitsOffset parameter - PARAMETERID_ModbusSlaveInputBitsOffset = ( (0 << 24) | 523 ), - /// \brief The ModbusSlaveOutputBitsOffset parameter - PARAMETERID_ModbusSlaveOutputBitsOffset = ( (0 << 24) | 524 ), - /// \brief The ModbusSlaveRWReadOffset parameter - PARAMETERID_ModbusSlaveRWReadOffset = ( (0 << 24) | 525 ), - /// \brief The ModbusSlaveRWWriteOffset parameter - PARAMETERID_ModbusSlaveRWWriteOffset = ( (0 << 24) | 526 ), - /// \brief The CurrentOffsetA parameter - PARAMETERID_CurrentOffsetA = ( (0 << 24) | 662 ), - /// \brief The CurrentOffsetB parameter - PARAMETERID_CurrentOffsetB = ( (0 << 24) | 663 ), - /// \brief The CommandShaperSetup parameter - PARAMETERID_CommandShaperSetup = ( (0 << 24) | 666 ), - /// \brief The CommandShaperTime00 parameter - PARAMETERID_CommandShaperTime00 = ( (0 << 24) | 667 ), - /// \brief The CommandShaperTime01 parameter - PARAMETERID_CommandShaperTime01 = ( (0 << 24) | 668 ), - /// \brief The CommandShaperTime02 parameter - PARAMETERID_CommandShaperTime02 = ( (0 << 24) | 669 ), - /// \brief The CommandShaperTime03 parameter - PARAMETERID_CommandShaperTime03 = ( (0 << 24) | 670 ), - /// \brief The CommandShaperTime04 parameter - PARAMETERID_CommandShaperTime04 = ( (0 << 24) | 671 ), - /// \brief The CommandShaperTime05 parameter - PARAMETERID_CommandShaperTime05 = ( (0 << 24) | 672 ), - /// \brief The CommandShaperTime06 parameter - PARAMETERID_CommandShaperTime06 = ( (0 << 24) | 673 ), - /// \brief The CommandShaperTime07 parameter - PARAMETERID_CommandShaperTime07 = ( (0 << 24) | 674 ), - /// \brief The CommandShaperTime08 parameter - PARAMETERID_CommandShaperTime08 = ( (0 << 24) | 675 ), - /// \brief The CommandShaperTime09 parameter - PARAMETERID_CommandShaperTime09 = ( (0 << 24) | 676 ), - /// \brief The CommandShaperTime10 parameter - PARAMETERID_CommandShaperTime10 = ( (0 << 24) | 677 ), - /// \brief The CommandShaperTime11 parameter - PARAMETERID_CommandShaperTime11 = ( (0 << 24) | 678 ), - /// \brief The CommandShaperTime12 parameter - PARAMETERID_CommandShaperTime12 = ( (0 << 24) | 679 ), - /// \brief The CommandShaperTime13 parameter - PARAMETERID_CommandShaperTime13 = ( (0 << 24) | 680 ), - /// \brief The CommandShaperTime14 parameter - PARAMETERID_CommandShaperTime14 = ( (0 << 24) | 681 ), - /// \brief The CommandShaperTime15 parameter - PARAMETERID_CommandShaperTime15 = ( (0 << 24) | 682 ), - /// \brief The CommandShaperCoeff00 parameter - PARAMETERID_CommandShaperCoeff00 = ( (0 << 24) | 683 ), - /// \brief The CommandShaperCoeff01 parameter - PARAMETERID_CommandShaperCoeff01 = ( (0 << 24) | 684 ), - /// \brief The CommandShaperCoeff02 parameter - PARAMETERID_CommandShaperCoeff02 = ( (0 << 24) | 685 ), - /// \brief The CommandShaperCoeff03 parameter - PARAMETERID_CommandShaperCoeff03 = ( (0 << 24) | 686 ), - /// \brief The CommandShaperCoeff04 parameter - PARAMETERID_CommandShaperCoeff04 = ( (0 << 24) | 687 ), - /// \brief The CommandShaperCoeff05 parameter - PARAMETERID_CommandShaperCoeff05 = ( (0 << 24) | 688 ), - /// \brief The CommandShaperCoeff06 parameter - PARAMETERID_CommandShaperCoeff06 = ( (0 << 24) | 689 ), - /// \brief The CommandShaperCoeff07 parameter - PARAMETERID_CommandShaperCoeff07 = ( (0 << 24) | 690 ), - /// \brief The CommandShaperCoeff08 parameter - PARAMETERID_CommandShaperCoeff08 = ( (0 << 24) | 691 ), - /// \brief The CommandShaperCoeff09 parameter - PARAMETERID_CommandShaperCoeff09 = ( (0 << 24) | 692 ), - /// \brief The CommandShaperCoeff10 parameter - PARAMETERID_CommandShaperCoeff10 = ( (0 << 24) | 693 ), - /// \brief The CommandShaperCoeff11 parameter - PARAMETERID_CommandShaperCoeff11 = ( (0 << 24) | 694 ), - /// \brief The CommandShaperCoeff12 parameter - PARAMETERID_CommandShaperCoeff12 = ( (0 << 24) | 695 ), - /// \brief The CommandShaperCoeff13 parameter - PARAMETERID_CommandShaperCoeff13 = ( (0 << 24) | 696 ), - /// \brief The CommandShaperCoeff14 parameter - PARAMETERID_CommandShaperCoeff14 = ( (0 << 24) | 697 ), - /// \brief The CommandShaperCoeff15 parameter - PARAMETERID_CommandShaperCoeff15 = ( (0 << 24) | 698 ), - /// \brief The CommandShaper0Type parameter - PARAMETERID_CommandShaper0Type = ( (0 << 24) | 703 ), - /// \brief The CommandShaper0Frequency parameter - PARAMETERID_CommandShaper0Frequency = ( (0 << 24) | 704 ), - /// \brief The CommandShaper0Damping parameter - PARAMETERID_CommandShaper0Damping = ( (0 << 24) | 705 ), - /// \brief The CommandShaper1Type parameter - PARAMETERID_CommandShaper1Type = ( (0 << 24) | 706 ), - /// \brief The CommandShaper1Frequency parameter - PARAMETERID_CommandShaper1Frequency = ( (0 << 24) | 707 ), - /// \brief The CommandShaper1Damping parameter - PARAMETERID_CommandShaper1Damping = ( (0 << 24) | 708 ), - /// \brief The ResoluteEncoderSetup parameter - PARAMETERID_ResoluteEncoderSetup = ( (0 << 24) | 715 ), - /// \brief The ResoluteEncoderResolution parameter - PARAMETERID_ResoluteEncoderResolution = ( (0 << 24) | 716 ), - /// \brief The ResoluteEncoderUserResolution parameter - PARAMETERID_ResoluteEncoderUserResolution = ( (0 << 24) | 717 ), - /// \brief The AutofocusInput parameter - PARAMETERID_AutofocusInput = ( (0 << 24) | 721 ), - /// \brief The AutofocusTarget parameter - PARAMETERID_AutofocusTarget = ( (0 << 24) | 722 ), - /// \brief The AutofocusDeadband parameter - PARAMETERID_AutofocusDeadband = ( (0 << 24) | 723 ), - /// \brief The AutofocusGainKi parameter - PARAMETERID_AutofocusGainKi = ( (0 << 24) | 724 ), - /// \brief The AutofocusGainKp parameter - PARAMETERID_AutofocusGainKp = ( (0 << 24) | 725 ), - /// \brief The AutofocusLimitLow parameter - PARAMETERID_AutofocusLimitLow = ( (0 << 24) | 726 ), - /// \brief The AutofocusLimitHigh parameter - PARAMETERID_AutofocusLimitHigh = ( (0 << 24) | 727 ), - /// \brief The AutofocusSpeedClamp parameter - PARAMETERID_AutofocusSpeedClamp = ( (0 << 24) | 728 ), - /// \brief The AutofocusHoldInput parameter - PARAMETERID_AutofocusHoldInput = ( (0 << 24) | 729 ), - /// \brief The AutofocusSetup parameter - PARAMETERID_AutofocusSetup = ( (0 << 24) | 730 ), - /// \brief The ExternalSyncFrequency parameter - PARAMETERID_ExternalSyncFrequency = ( (0 << 24) | 731 ), - /// \brief The GainPff parameter - PARAMETERID_GainPff = ( (0 << 24) | 762 ), - /// \brief The AutofocusInitialRampTime parameter - PARAMETERID_AutofocusInitialRampTime = ( (0 << 24) | 763 ), -} PARAMETERID; - -#endif // __PARAMETER_ID_H__ +/// \file ParameterId.h +/// \brief File contains parameter identifiers +/// +/// This file is version dependant and needs to match the rest of the software + +#ifndef __PARAMETER_ID_H__ +#define __PARAMETER_ID_H__ + + +/// \brief Represents a parameter identifier +typedef enum { + /// \brief The AxisType parameter + PARAMETERID_AxisType = ( (0 << 24) | 0 ), + /// \brief The ReverseMotionDirection parameter + PARAMETERID_ReverseMotionDirection = ( (0 << 24) | 1 ), + /// \brief The CountsPerUnit parameter + PARAMETERID_CountsPerUnit = ( (0 << 24) | 2 ), + /// \brief The ServoRate parameter + PARAMETERID_ServoRate = ( (0 << 24) | 3 ), + /// \brief The ServoSetup parameter + PARAMETERID_ServoSetup = ( (0 << 24) | 4 ), + /// \brief The GainKpos parameter + PARAMETERID_GainKpos = ( (0 << 24) | 5 ), + /// \brief The GainKi parameter + PARAMETERID_GainKi = ( (0 << 24) | 6 ), + /// \brief The GainKp parameter + PARAMETERID_GainKp = ( (0 << 24) | 7 ), + /// \brief The GainVff parameter + PARAMETERID_GainVff = ( (0 << 24) | 8 ), + /// \brief The GainAff parameter + PARAMETERID_GainAff = ( (0 << 24) | 9 ), + /// \brief The GainKv parameter + PARAMETERID_GainKv = ( (0 << 24) | 10 ), + /// \brief The GainKpi parameter + PARAMETERID_GainKpi = ( (0 << 24) | 11 ), + /// \brief The ServoFilter0CoeffN0 parameter + PARAMETERID_ServoFilter0CoeffN0 = ( (0 << 24) | 12 ), + /// \brief The ServoFilter0CoeffN1 parameter + PARAMETERID_ServoFilter0CoeffN1 = ( (0 << 24) | 13 ), + /// \brief The ServoFilter0CoeffN2 parameter + PARAMETERID_ServoFilter0CoeffN2 = ( (0 << 24) | 14 ), + /// \brief The ServoFilter0CoeffD1 parameter + PARAMETERID_ServoFilter0CoeffD1 = ( (0 << 24) | 15 ), + /// \brief The ServoFilter0CoeffD2 parameter + PARAMETERID_ServoFilter0CoeffD2 = ( (0 << 24) | 16 ), + /// \brief The ServoFilter1CoeffN0 parameter + PARAMETERID_ServoFilter1CoeffN0 = ( (0 << 24) | 17 ), + /// \brief The ServoFilter1CoeffN1 parameter + PARAMETERID_ServoFilter1CoeffN1 = ( (0 << 24) | 18 ), + /// \brief The ServoFilter1CoeffN2 parameter + PARAMETERID_ServoFilter1CoeffN2 = ( (0 << 24) | 19 ), + /// \brief The ServoFilter1CoeffD1 parameter + PARAMETERID_ServoFilter1CoeffD1 = ( (0 << 24) | 20 ), + /// \brief The ServoFilter1CoeffD2 parameter + PARAMETERID_ServoFilter1CoeffD2 = ( (0 << 24) | 21 ), + /// \brief The AmplifierDeadtime parameter + PARAMETERID_AmplifierDeadtime = ( (0 << 24) | 22 ), + /// \brief The RolloverCounts parameter + PARAMETERID_RolloverCounts = ( (0 << 24) | 23 ), + /// \brief The CurrentGainKi parameter + PARAMETERID_CurrentGainKi = ( (0 << 24) | 24 ), + /// \brief The CurrentGainKp parameter + PARAMETERID_CurrentGainKp = ( (0 << 24) | 25 ), + /// \brief The FaultMask parameter + PARAMETERID_FaultMask = ( (0 << 24) | 26 ), + /// \brief The FaultMaskDisable parameter + PARAMETERID_FaultMaskDisable = ( (0 << 24) | 27 ), + /// \brief The FaultMaskDecel parameter + PARAMETERID_FaultMaskDecel = ( (0 << 24) | 28 ), + /// \brief The EnableBrakeControl parameter + PARAMETERID_EnableBrakeControl = ( (0 << 24) | 29 ), + /// \brief The FaultMaskOutput parameter + PARAMETERID_FaultMaskOutput = ( (0 << 24) | 30 ), + /// \brief The ESTOPFaultInput parameter + PARAMETERID_ESTOPFaultInput = ( (0 << 24) | 31 ), + /// \brief The PositionErrorThreshold parameter + PARAMETERID_PositionErrorThreshold = ( (0 << 24) | 32 ), + /// \brief The AverageCurrentThreshold parameter + PARAMETERID_AverageCurrentThreshold = ( (0 << 24) | 33 ), + /// \brief The AverageCurrentTime parameter + PARAMETERID_AverageCurrentTime = ( (0 << 24) | 34 ), + /// \brief The VelocityCommandThreshold parameter + PARAMETERID_VelocityCommandThreshold = ( (0 << 24) | 35 ), + /// \brief The VelocityErrorThreshold parameter + PARAMETERID_VelocityErrorThreshold = ( (0 << 24) | 36 ), + /// \brief The SoftwareLimitLow parameter + PARAMETERID_SoftwareLimitLow = ( (0 << 24) | 37 ), + /// \brief The SoftwareLimitHigh parameter + PARAMETERID_SoftwareLimitHigh = ( (0 << 24) | 38 ), + /// \brief The MaxCurrentClamp parameter + PARAMETERID_MaxCurrentClamp = ( (0 << 24) | 39 ), + /// \brief The InPositionDistance parameter + PARAMETERID_InPositionDistance = ( (0 << 24) | 40 ), + /// \brief The MotorType parameter + PARAMETERID_MotorType = ( (0 << 24) | 41 ), + /// \brief The CyclesPerRev parameter + PARAMETERID_CyclesPerRev = ( (0 << 24) | 42 ), + /// \brief The CountsPerRev parameter + PARAMETERID_CountsPerRev = ( (0 << 24) | 43 ), + /// \brief The CommutationOffset parameter + PARAMETERID_CommutationOffset = ( (0 << 24) | 44 ), + /// \brief The AutoMsetTime parameter + PARAMETERID_AutoMsetTime = ( (0 << 24) | 45 ), + /// \brief The AutoMsetCurrent parameter + PARAMETERID_AutoMsetCurrent = ( (0 << 24) | 46 ), + /// \brief The PositionFeedbackType parameter + PARAMETERID_PositionFeedbackType = ( (0 << 24) | 47 ), + /// \brief The PositionFeedbackChannel parameter + PARAMETERID_PositionFeedbackChannel = ( (0 << 24) | 48 ), + /// \brief The VelocityFeedbackType parameter + PARAMETERID_VelocityFeedbackType = ( (0 << 24) | 49 ), + /// \brief The VelocityFeedbackChannel parameter + PARAMETERID_VelocityFeedbackChannel = ( (0 << 24) | 50 ), + /// \brief The EncoderMultiplicationFactor parameter + PARAMETERID_EncoderMultiplicationFactor = ( (0 << 24) | 51 ), + /// \brief The EncoderSineGain parameter + PARAMETERID_EncoderSineGain = ( (0 << 24) | 52 ), + /// \brief The EncoderSineOffset parameter + PARAMETERID_EncoderSineOffset = ( (0 << 24) | 53 ), + /// \brief The EncoderCosineGain parameter + PARAMETERID_EncoderCosineGain = ( (0 << 24) | 54 ), + /// \brief The EncoderCosineOffset parameter + PARAMETERID_EncoderCosineOffset = ( (0 << 24) | 55 ), + /// \brief The EncoderPhase parameter + PARAMETERID_EncoderPhase = ( (0 << 24) | 56 ), + /// \brief The GantryMasterAxis parameter + PARAMETERID_GantryMasterAxis = ( (0 << 24) | 57 ), + /// \brief The LimitDecelDistance parameter + PARAMETERID_LimitDecelDistance = ( (0 << 24) | 59 ), + /// \brief The LimitDebounceTime parameter + PARAMETERID_LimitDebounceTime = ( (0 << 24) | 60 ), + /// \brief The EndOfTravelLimitSetup parameter + PARAMETERID_EndOfTravelLimitSetup = ( (0 << 24) | 61 ), + /// \brief The BacklashDistance parameter + PARAMETERID_BacklashDistance = ( (0 << 24) | 62 ), + /// \brief The FaultOutputSetup parameter + PARAMETERID_FaultOutputSetup = ( (0 << 24) | 63 ), + /// \brief The FaultOutputState parameter + PARAMETERID_FaultOutputState = ( (0 << 24) | 64 ), + /// \brief The IOSetup parameter + PARAMETERID_IOSetup = ( (0 << 24) | 65 ), + /// \brief The BrakeOutput parameter + PARAMETERID_BrakeOutput = ( (0 << 24) | 66 ), + /// \brief The EncoderDivider parameter + PARAMETERID_EncoderDivider = ( (0 << 24) | 67 ), + /// \brief The ExternalFaultDigitalInput parameter + PARAMETERID_ExternalFaultDigitalInput = ( (0 << 24) | 68 ), + /// \brief The BrakeDisableDelay parameter + PARAMETERID_BrakeDisableDelay = ( (0 << 24) | 69 ), + /// \brief The MaxJogDistance parameter + PARAMETERID_MaxJogDistance = ( (0 << 24) | 70 ), + /// \brief The DefaultSpeed parameter + PARAMETERID_DefaultSpeed = ( (0 << 24) | 71 ), + /// \brief The DefaultRampRate parameter + PARAMETERID_DefaultRampRate = ( (0 << 24) | 72 ), + /// \brief The AbortDecelRate parameter + PARAMETERID_AbortDecelRate = ( (0 << 24) | 73 ), + /// \brief The HomeType parameter + PARAMETERID_HomeType = ( (0 << 24) | 74 ), + /// \brief The HomeSetup parameter + PARAMETERID_HomeSetup = ( (0 << 24) | 75 ), + /// \brief The HomeSpeed parameter + PARAMETERID_HomeSpeed = ( (0 << 24) | 76 ), + /// \brief The HomeOffset parameter + PARAMETERID_HomeOffset = ( (0 << 24) | 77 ), + /// \brief The HomeRampRate parameter + PARAMETERID_HomeRampRate = ( (0 << 24) | 78 ), + /// \brief The DefaultWaitMode parameter + PARAMETERID_DefaultWaitMode = ( (0 << 24) | 79 ), + /// \brief The DefaultSCurve parameter + PARAMETERID_DefaultSCurve = ( (0 << 24) | 80 ), + /// \brief The DataCollectionPoints parameter + PARAMETERID_DataCollectionPoints = ( (0 << 24) | 81 ), + /// \brief The StepperResolution parameter + PARAMETERID_StepperResolution = ( (0 << 24) | 83 ), + /// \brief The StepperRunningCurrent parameter + PARAMETERID_StepperRunningCurrent = ( (0 << 24) | 84 ), + /// \brief The StepperHoldingCurrent parameter + PARAMETERID_StepperHoldingCurrent = ( (0 << 24) | 85 ), + /// \brief The StepperVerificationSpeed parameter + PARAMETERID_StepperVerificationSpeed = ( (0 << 24) | 86 ), + /// \brief The LimitDebounceDistance parameter + PARAMETERID_LimitDebounceDistance = ( (0 << 24) | 87 ), + /// \brief The ServoFilter2CoeffN0 parameter + PARAMETERID_ServoFilter2CoeffN0 = ( (0 << 24) | 88 ), + /// \brief The ServoFilter2CoeffN1 parameter + PARAMETERID_ServoFilter2CoeffN1 = ( (0 << 24) | 89 ), + /// \brief The ServoFilter2CoeffN2 parameter + PARAMETERID_ServoFilter2CoeffN2 = ( (0 << 24) | 90 ), + /// \brief The ServoFilter2CoeffD1 parameter + PARAMETERID_ServoFilter2CoeffD1 = ( (0 << 24) | 91 ), + /// \brief The ServoFilter2CoeffD2 parameter + PARAMETERID_ServoFilter2CoeffD2 = ( (0 << 24) | 92 ), + /// \brief The ServoFilter3CoeffN0 parameter + PARAMETERID_ServoFilter3CoeffN0 = ( (0 << 24) | 93 ), + /// \brief The ServoFilter3CoeffN1 parameter + PARAMETERID_ServoFilter3CoeffN1 = ( (0 << 24) | 94 ), + /// \brief The ServoFilter3CoeffN2 parameter + PARAMETERID_ServoFilter3CoeffN2 = ( (0 << 24) | 95 ), + /// \brief The ServoFilter3CoeffD1 parameter + PARAMETERID_ServoFilter3CoeffD1 = ( (0 << 24) | 96 ), + /// \brief The ServoFilter3CoeffD2 parameter + PARAMETERID_ServoFilter3CoeffD2 = ( (0 << 24) | 97 ), + /// \brief The GearCamSource parameter + PARAMETERID_GearCamSource = ( (0 << 24) | 98 ), + /// \brief The GearCamIndex parameter + PARAMETERID_GearCamIndex = ( (0 << 24) | 99 ), + /// \brief The GearCamScaleFactor parameter + PARAMETERID_GearCamScaleFactor = ( (0 << 24) | 100 ), + /// \brief The GearCamAnalogDeadband parameter + PARAMETERID_GearCamAnalogDeadband = ( (0 << 24) | 105 ), + /// \brief The PrintBufferSize parameter + PARAMETERID_PrintBufferSize = ( (0 << 24) | 106 ), + /// \brief The SerialPort0XonCharacter parameter + PARAMETERID_SerialPort0XonCharacter = ( (0 << 24) | 109 ), + /// \brief The SerialPort0XoffCharacter parameter + PARAMETERID_SerialPort0XoffCharacter = ( (0 << 24) | 110 ), + /// \brief The SerialPort0BaudRate parameter + PARAMETERID_SerialPort0BaudRate = ( (0 << 24) | 111 ), + /// \brief The SerialPort0Setup parameter + PARAMETERID_SerialPort0Setup = ( (0 << 24) | 112 ), + /// \brief The TaskExecutionSetup parameter + PARAMETERID_TaskExecutionSetup = ( (0 << 24) | 113 ), + /// \brief The CodeSize parameter + PARAMETERID_CodeSize = ( (0 << 24) | 114 ), + /// \brief The DataSize parameter + PARAMETERID_DataSize = ( (0 << 24) | 115 ), + /// \brief The StackSize parameter + PARAMETERID_StackSize = ( (0 << 24) | 116 ), + /// \brief The AutoRunProgram parameter + PARAMETERID_AutoRunProgram = ( (0 << 24) | 118 ), + /// \brief The MaxJogSpeed parameter + PARAMETERID_MaxJogSpeed = ( (0 << 24) | 123 ), + /// \brief The GlobalIntegers parameter + PARAMETERID_GlobalIntegers = ( (0 << 24) | 124 ), + /// \brief The GlobalDoubles parameter + PARAMETERID_GlobalDoubles = ( (0 << 24) | 125 ), + /// \brief The DecimalPlaces parameter + PARAMETERID_DecimalPlaces = ( (0 << 24) | 126 ), + /// \brief The TaskErrorAbortAxes parameter + PARAMETERID_TaskErrorAbortAxes = ( (0 << 24) | 127 ), + /// \brief The CalibrationFile1D parameter + PARAMETERID_CalibrationFile1D = ( (0 << 24) | 128 ), + /// \brief The UnitsName parameter + PARAMETERID_UnitsName = ( (0 << 24) | 129 ), + /// \brief The Socket2RemoteIPAddress parameter + PARAMETERID_Socket2RemoteIPAddress = ( (0 << 24) | 130 ), + /// \brief The Socket2Port parameter + PARAMETERID_Socket2Port = ( (0 << 24) | 131 ), + /// \brief The Socket2Setup parameter + PARAMETERID_Socket2Setup = ( (0 << 24) | 132 ), + /// \brief The Socket2TransmissionSize parameter + PARAMETERID_Socket2TransmissionSize = ( (0 << 24) | 133 ), + /// \brief The Socket3RemoteIPAddress parameter + PARAMETERID_Socket3RemoteIPAddress = ( (0 << 24) | 134 ), + /// \brief The Socket3Port parameter + PARAMETERID_Socket3Port = ( (0 << 24) | 135 ), + /// \brief The Socket3Setup parameter + PARAMETERID_Socket3Setup = ( (0 << 24) | 136 ), + /// \brief The Socket3TransmissionSize parameter + PARAMETERID_Socket3TransmissionSize = ( (0 << 24) | 137 ), + /// \brief The Socket2Timeout parameter + PARAMETERID_Socket2Timeout = ( (0 << 24) | 138 ), + /// \brief The Socket3Timeout parameter + PARAMETERID_Socket3Timeout = ( (0 << 24) | 139 ), + /// \brief The AxisName parameter + PARAMETERID_AxisName = ( (0 << 24) | 140 ), + /// \brief The UserInteger0 parameter + PARAMETERID_UserInteger0 = ( (0 << 24) | 141 ), + /// \brief The UserInteger1 parameter + PARAMETERID_UserInteger1 = ( (0 << 24) | 142 ), + /// \brief The UserDouble0 parameter + PARAMETERID_UserDouble0 = ( (0 << 24) | 143 ), + /// \brief The UserDouble1 parameter + PARAMETERID_UserDouble1 = ( (0 << 24) | 144 ), + /// \brief The UserString0 parameter + PARAMETERID_UserString0 = ( (0 << 24) | 145 ), + /// \brief The UserString1 parameter + PARAMETERID_UserString1 = ( (0 << 24) | 146 ), + /// \brief The EnDatEncoderSetup parameter + PARAMETERID_EnDatEncoderSetup = ( (0 << 24) | 147 ), + /// \brief The EnDatEncoderResolution parameter + PARAMETERID_EnDatEncoderResolution = ( (0 << 24) | 148 ), + /// \brief The EnDatEncoderTurns parameter + PARAMETERID_EnDatEncoderTurns = ( (0 << 24) | 149 ), + /// \brief The CommandSetup parameter + PARAMETERID_CommandSetup = ( (0 << 24) | 150 ), + /// \brief The SerialPort1XonCharacter parameter + PARAMETERID_SerialPort1XonCharacter = ( (0 << 24) | 152 ), + /// \brief The SerialPort1XoffCharacter parameter + PARAMETERID_SerialPort1XoffCharacter = ( (0 << 24) | 153 ), + /// \brief The SerialPort1BaudRate parameter + PARAMETERID_SerialPort1BaudRate = ( (0 << 24) | 154 ), + /// \brief The SerialPort1Setup parameter + PARAMETERID_SerialPort1Setup = ( (0 << 24) | 155 ), + /// \brief The RequiredAxes parameter + PARAMETERID_RequiredAxes = ( (0 << 24) | 156 ), + /// \brief The JoystickInput1MinVoltage parameter + PARAMETERID_JoystickInput1MinVoltage = ( (0 << 24) | 157 ), + /// \brief The JoystickInput1MaxVoltage parameter + PARAMETERID_JoystickInput1MaxVoltage = ( (0 << 24) | 158 ), + /// \brief The JoystickInput1Deadband parameter + PARAMETERID_JoystickInput1Deadband = ( (0 << 24) | 159 ), + /// \brief The JoystickInput0MinVoltage parameter + PARAMETERID_JoystickInput0MinVoltage = ( (0 << 24) | 160 ), + /// \brief The JoystickInput0MaxVoltage parameter + PARAMETERID_JoystickInput0MaxVoltage = ( (0 << 24) | 161 ), + /// \brief The JoystickInput0Deadband parameter + PARAMETERID_JoystickInput0Deadband = ( (0 << 24) | 162 ), + /// \brief The JoystickLowSpeed parameter + PARAMETERID_JoystickLowSpeed = ( (0 << 24) | 163 ), + /// \brief The JoystickHighSpeed parameter + PARAMETERID_JoystickHighSpeed = ( (0 << 24) | 164 ), + /// \brief The JoystickSetup parameter + PARAMETERID_JoystickSetup = ( (0 << 24) | 165 ), + /// \brief The HomePositionSet parameter + PARAMETERID_HomePositionSet = ( (0 << 24) | 166 ), + /// \brief The TaskTerminationAxes parameter + PARAMETERID_TaskTerminationAxes = ( (0 << 24) | 167 ), + /// \brief The TaskStopAbortAxes parameter + PARAMETERID_TaskStopAbortAxes = ( (0 << 24) | 168 ), + /// \brief The CalibrationFile2D parameter + PARAMETERID_CalibrationFile2D = ( (0 << 24) | 169 ), + /// \brief The FaultMaskDisableDelay parameter + PARAMETERID_FaultMaskDisableDelay = ( (0 << 24) | 170 ), + /// \brief The DefaultCoordinatedSpeed parameter + PARAMETERID_DefaultCoordinatedSpeed = ( (0 << 24) | 171 ), + /// \brief The DefaultCoordinatedRampRate parameter + PARAMETERID_DefaultCoordinatedRampRate = ( (0 << 24) | 172 ), + /// \brief The DefaultDependentCoordinatedRampRate parameter + PARAMETERID_DefaultDependentCoordinatedRampRate = ( (0 << 24) | 173 ), + /// \brief The GpibTerminatingCharacter parameter + PARAMETERID_GpibTerminatingCharacter = ( (0 << 24) | 174 ), + /// \brief The GpibPrimaryAddress parameter + PARAMETERID_GpibPrimaryAddress = ( (0 << 24) | 175 ), + /// \brief The GpibParallelResponse parameter + PARAMETERID_GpibParallelResponse = ( (0 << 24) | 176 ), + /// \brief The CommandTerminatingCharacter parameter + PARAMETERID_CommandTerminatingCharacter = ( (0 << 24) | 177 ), + /// \brief The CommandSuccessCharacter parameter + PARAMETERID_CommandSuccessCharacter = ( (0 << 24) | 178 ), + /// \brief The CommandInvalidCharacter parameter + PARAMETERID_CommandInvalidCharacter = ( (0 << 24) | 179 ), + /// \brief The CommandFaultCharacter parameter + PARAMETERID_CommandFaultCharacter = ( (0 << 24) | 180 ), + /// \brief The FaultAbortAxes parameter + PARAMETERID_FaultAbortAxes = ( (0 << 24) | 182 ), + /// \brief The HarmonicCancellation0Type parameter + PARAMETERID_HarmonicCancellation0Type = ( (0 << 24) | 185 ), + /// \brief The HarmonicCancellation0Period parameter + PARAMETERID_HarmonicCancellation0Period = ( (0 << 24) | 186 ), + /// \brief The HarmonicCancellation0Gain parameter + PARAMETERID_HarmonicCancellation0Gain = ( (0 << 24) | 188 ), + /// \brief The HarmonicCancellation0Phase parameter + PARAMETERID_HarmonicCancellation0Phase = ( (0 << 24) | 189 ), + /// \brief The HarmonicCancellation1Type parameter + PARAMETERID_HarmonicCancellation1Type = ( (0 << 24) | 190 ), + /// \brief The HarmonicCancellation1Period parameter + PARAMETERID_HarmonicCancellation1Period = ( (0 << 24) | 191 ), + /// \brief The HarmonicCancellation1Gain parameter + PARAMETERID_HarmonicCancellation1Gain = ( (0 << 24) | 193 ), + /// \brief The HarmonicCancellation1Phase parameter + PARAMETERID_HarmonicCancellation1Phase = ( (0 << 24) | 194 ), + /// \brief The HarmonicCancellation2Type parameter + PARAMETERID_HarmonicCancellation2Type = ( (0 << 24) | 195 ), + /// \brief The HarmonicCancellation2Period parameter + PARAMETERID_HarmonicCancellation2Period = ( (0 << 24) | 196 ), + /// \brief The HarmonicCancellation2Gain parameter + PARAMETERID_HarmonicCancellation2Gain = ( (0 << 24) | 198 ), + /// \brief The HarmonicCancellation2Phase parameter + PARAMETERID_HarmonicCancellation2Phase = ( (0 << 24) | 199 ), + /// \brief The CommandTimeout parameter + PARAMETERID_CommandTimeout = ( (0 << 24) | 202 ), + /// \brief The CommandTimeoutCharacter parameter + PARAMETERID_CommandTimeoutCharacter = ( (0 << 24) | 203 ), + /// \brief The ResolverReferenceGain parameter + PARAMETERID_ResolverReferenceGain = ( (0 << 24) | 204 ), + /// \brief The ResolverSetup parameter + PARAMETERID_ResolverSetup = ( (0 << 24) | 205 ), + /// \brief The ResolverReferencePhase parameter + PARAMETERID_ResolverReferencePhase = ( (0 << 24) | 206 ), + /// \brief The SoftwareLimitSetup parameter + PARAMETERID_SoftwareLimitSetup = ( (0 << 24) | 210 ), + /// \brief The SSINet1Setup parameter + PARAMETERID_SSINet1Setup = ( (0 << 24) | 211 ), + /// \brief The SSINet2Setup parameter + PARAMETERID_SSINet2Setup = ( (0 << 24) | 212 ), + /// \brief The EmulatedQuadratureDivider parameter + PARAMETERID_EmulatedQuadratureDivider = ( (0 << 24) | 213 ), + /// \brief The HarmonicCancellation3Type parameter + PARAMETERID_HarmonicCancellation3Type = ( (0 << 24) | 214 ), + /// \brief The HarmonicCancellation3Period parameter + PARAMETERID_HarmonicCancellation3Period = ( (0 << 24) | 215 ), + /// \brief The HarmonicCancellation3Gain parameter + PARAMETERID_HarmonicCancellation3Gain = ( (0 << 24) | 217 ), + /// \brief The HarmonicCancellation3Phase parameter + PARAMETERID_HarmonicCancellation3Phase = ( (0 << 24) | 218 ), + /// \brief The HarmonicCancellation4Type parameter + PARAMETERID_HarmonicCancellation4Type = ( (0 << 24) | 219 ), + /// \brief The HarmonicCancellation4Period parameter + PARAMETERID_HarmonicCancellation4Period = ( (0 << 24) | 220 ), + /// \brief The HarmonicCancellation4Gain parameter + PARAMETERID_HarmonicCancellation4Gain = ( (0 << 24) | 222 ), + /// \brief The HarmonicCancellation4Phase parameter + PARAMETERID_HarmonicCancellation4Phase = ( (0 << 24) | 223 ), + /// \brief The EnhancedThroughputChannel parameter + PARAMETERID_EnhancedThroughputChannel = ( (0 << 24) | 224 ), + /// \brief The EnhancedThroughputGain parameter + PARAMETERID_EnhancedThroughputGain = ( (0 << 24) | 225 ), + /// \brief The HarmonicCancellationSetup parameter + PARAMETERID_HarmonicCancellationSetup = ( (0 << 24) | 226 ), + /// \brief The EnhancedThroughputCurrentClamp parameter + PARAMETERID_EnhancedThroughputCurrentClamp = ( (0 << 24) | 227 ), + /// \brief The Analog0Filter0CoeffN0 parameter + PARAMETERID_Analog0Filter0CoeffN0 = ( (0 << 24) | 228 ), + /// \brief The Analog0Filter0CoeffN1 parameter + PARAMETERID_Analog0Filter0CoeffN1 = ( (0 << 24) | 229 ), + /// \brief The Analog0Filter0CoeffN2 parameter + PARAMETERID_Analog0Filter0CoeffN2 = ( (0 << 24) | 230 ), + /// \brief The Analog0Filter0CoeffD1 parameter + PARAMETERID_Analog0Filter0CoeffD1 = ( (0 << 24) | 231 ), + /// \brief The Analog0Filter0CoeffD2 parameter + PARAMETERID_Analog0Filter0CoeffD2 = ( (0 << 24) | 232 ), + /// \brief The Analog0Filter1CoeffN0 parameter + PARAMETERID_Analog0Filter1CoeffN0 = ( (0 << 24) | 233 ), + /// \brief The Analog0Filter1CoeffN1 parameter + PARAMETERID_Analog0Filter1CoeffN1 = ( (0 << 24) | 234 ), + /// \brief The Analog0Filter1CoeffN2 parameter + PARAMETERID_Analog0Filter1CoeffN2 = ( (0 << 24) | 235 ), + /// \brief The Analog0Filter1CoeffD1 parameter + PARAMETERID_Analog0Filter1CoeffD1 = ( (0 << 24) | 236 ), + /// \brief The Analog0Filter1CoeffD2 parameter + PARAMETERID_Analog0Filter1CoeffD2 = ( (0 << 24) | 237 ), + /// \brief The Analog1Filter0CoeffN0 parameter + PARAMETERID_Analog1Filter0CoeffN0 = ( (0 << 24) | 238 ), + /// \brief The Analog1Filter0CoeffN1 parameter + PARAMETERID_Analog1Filter0CoeffN1 = ( (0 << 24) | 239 ), + /// \brief The Analog1Filter0CoeffN2 parameter + PARAMETERID_Analog1Filter0CoeffN2 = ( (0 << 24) | 240 ), + /// \brief The Analog1Filter0CoeffD1 parameter + PARAMETERID_Analog1Filter0CoeffD1 = ( (0 << 24) | 241 ), + /// \brief The Analog1Filter0CoeffD2 parameter + PARAMETERID_Analog1Filter0CoeffD2 = ( (0 << 24) | 242 ), + /// \brief The Analog1Filter1CoeffN0 parameter + PARAMETERID_Analog1Filter1CoeffN0 = ( (0 << 24) | 243 ), + /// \brief The Analog1Filter1CoeffN1 parameter + PARAMETERID_Analog1Filter1CoeffN1 = ( (0 << 24) | 244 ), + /// \brief The Analog1Filter1CoeffN2 parameter + PARAMETERID_Analog1Filter1CoeffN2 = ( (0 << 24) | 245 ), + /// \brief The Analog1Filter1CoeffD1 parameter + PARAMETERID_Analog1Filter1CoeffD1 = ( (0 << 24) | 246 ), + /// \brief The Analog1Filter1CoeffD2 parameter + PARAMETERID_Analog1Filter1CoeffD2 = ( (0 << 24) | 247 ), + /// \brief The GlobalStrings parameter + PARAMETERID_GlobalStrings = ( (0 << 24) | 248 ), + /// \brief The DefaultCoordinatedRampMode parameter + PARAMETERID_DefaultCoordinatedRampMode = ( (0 << 24) | 249 ), + /// \brief The DefaultCoordinatedRampTime parameter + PARAMETERID_DefaultCoordinatedRampTime = ( (0 << 24) | 250 ), + /// \brief The DefaultCoordinatedRampDistance parameter + PARAMETERID_DefaultCoordinatedRampDistance = ( (0 << 24) | 251 ), + /// \brief The DefaultRampMode parameter + PARAMETERID_DefaultRampMode = ( (0 << 24) | 252 ), + /// \brief The DefaultRampTime parameter + PARAMETERID_DefaultRampTime = ( (0 << 24) | 253 ), + /// \brief The DefaultRampDistance parameter + PARAMETERID_DefaultRampDistance = ( (0 << 24) | 254 ), + /// \brief The ServoFilterSetup parameter + PARAMETERID_ServoFilterSetup = ( (0 << 24) | 255 ), + /// \brief The FeedbackSetup parameter + PARAMETERID_FeedbackSetup = ( (0 << 24) | 256 ), + /// \brief The EncoderMultiplierSetup parameter + PARAMETERID_EncoderMultiplierSetup = ( (0 << 24) | 257 ), + /// \brief The FaultSetup parameter + PARAMETERID_FaultSetup = ( (0 << 24) | 258 ), + /// \brief The ThresholdScheduleSetup parameter + PARAMETERID_ThresholdScheduleSetup = ( (0 << 24) | 259 ), + /// \brief The ThresholdRegion2High parameter + PARAMETERID_ThresholdRegion2High = ( (0 << 24) | 260 ), + /// \brief The ThresholdRegion2Low parameter + PARAMETERID_ThresholdRegion2Low = ( (0 << 24) | 261 ), + /// \brief The ThresholdRegion3GainKpos parameter + PARAMETERID_ThresholdRegion3GainKpos = ( (0 << 24) | 262 ), + /// \brief The ThresholdRegion3GainKp parameter + PARAMETERID_ThresholdRegion3GainKp = ( (0 << 24) | 263 ), + /// \brief The ThresholdRegion3GainKi parameter + PARAMETERID_ThresholdRegion3GainKi = ( (0 << 24) | 264 ), + /// \brief The ThresholdRegion3GainKpi parameter + PARAMETERID_ThresholdRegion3GainKpi = ( (0 << 24) | 265 ), + /// \brief The ThresholdRegion4High parameter + PARAMETERID_ThresholdRegion4High = ( (0 << 24) | 266 ), + /// \brief The ThresholdRegion4Low parameter + PARAMETERID_ThresholdRegion4Low = ( (0 << 24) | 267 ), + /// \brief The ThresholdRegion5GainKpos parameter + PARAMETERID_ThresholdRegion5GainKpos = ( (0 << 24) | 268 ), + /// \brief The ThresholdRegion5GainKp parameter + PARAMETERID_ThresholdRegion5GainKp = ( (0 << 24) | 269 ), + /// \brief The ThresholdRegion5GainKi parameter + PARAMETERID_ThresholdRegion5GainKi = ( (0 << 24) | 270 ), + /// \brief The ThresholdRegion5GainKpi parameter + PARAMETERID_ThresholdRegion5GainKpi = ( (0 << 24) | 271 ), + /// \brief The DynamicScheduleSetup parameter + PARAMETERID_DynamicScheduleSetup = ( (0 << 24) | 272 ), + /// \brief The DynamicGainKposScale parameter + PARAMETERID_DynamicGainKposScale = ( (0 << 24) | 273 ), + /// \brief The DynamicGainKpScale parameter + PARAMETERID_DynamicGainKpScale = ( (0 << 24) | 274 ), + /// \brief The DynamicGainKiScale parameter + PARAMETERID_DynamicGainKiScale = ( (0 << 24) | 275 ), + /// \brief The ServoFilter4CoeffN0 parameter + PARAMETERID_ServoFilter4CoeffN0 = ( (0 << 24) | 276 ), + /// \brief The ServoFilter4CoeffN1 parameter + PARAMETERID_ServoFilter4CoeffN1 = ( (0 << 24) | 277 ), + /// \brief The ServoFilter4CoeffN2 parameter + PARAMETERID_ServoFilter4CoeffN2 = ( (0 << 24) | 278 ), + /// \brief The ServoFilter4CoeffD1 parameter + PARAMETERID_ServoFilter4CoeffD1 = ( (0 << 24) | 279 ), + /// \brief The ServoFilter4CoeffD2 parameter + PARAMETERID_ServoFilter4CoeffD2 = ( (0 << 24) | 280 ), + /// \brief The ServoFilter5CoeffN0 parameter + PARAMETERID_ServoFilter5CoeffN0 = ( (0 << 24) | 281 ), + /// \brief The ServoFilter5CoeffN1 parameter + PARAMETERID_ServoFilter5CoeffN1 = ( (0 << 24) | 282 ), + /// \brief The ServoFilter5CoeffN2 parameter + PARAMETERID_ServoFilter5CoeffN2 = ( (0 << 24) | 283 ), + /// \brief The ServoFilter5CoeffD1 parameter + PARAMETERID_ServoFilter5CoeffD1 = ( (0 << 24) | 284 ), + /// \brief The ServoFilter5CoeffD2 parameter + PARAMETERID_ServoFilter5CoeffD2 = ( (0 << 24) | 285 ), + /// \brief The ServoFilter6CoeffN0 parameter + PARAMETERID_ServoFilter6CoeffN0 = ( (0 << 24) | 286 ), + /// \brief The ServoFilter6CoeffN1 parameter + PARAMETERID_ServoFilter6CoeffN1 = ( (0 << 24) | 287 ), + /// \brief The ServoFilter6CoeffN2 parameter + PARAMETERID_ServoFilter6CoeffN2 = ( (0 << 24) | 288 ), + /// \brief The ServoFilter6CoeffD1 parameter + PARAMETERID_ServoFilter6CoeffD1 = ( (0 << 24) | 289 ), + /// \brief The ServoFilter6CoeffD2 parameter + PARAMETERID_ServoFilter6CoeffD2 = ( (0 << 24) | 290 ), + /// \brief The ServoFilter7CoeffN0 parameter + PARAMETERID_ServoFilter7CoeffN0 = ( (0 << 24) | 291 ), + /// \brief The ServoFilter7CoeffN1 parameter + PARAMETERID_ServoFilter7CoeffN1 = ( (0 << 24) | 292 ), + /// \brief The ServoFilter7CoeffN2 parameter + PARAMETERID_ServoFilter7CoeffN2 = ( (0 << 24) | 293 ), + /// \brief The ServoFilter7CoeffD1 parameter + PARAMETERID_ServoFilter7CoeffD1 = ( (0 << 24) | 294 ), + /// \brief The ServoFilter7CoeffD2 parameter + PARAMETERID_ServoFilter7CoeffD2 = ( (0 << 24) | 295 ), + /// \brief The LinearAmpMaxPower parameter + PARAMETERID_LinearAmpMaxPower = ( (0 << 24) | 296 ), + /// \brief The LinearAmpDeratingFactor parameter + PARAMETERID_LinearAmpDeratingFactor = ( (0 << 24) | 297 ), + /// \brief The LinearAmpBusVoltage parameter + PARAMETERID_LinearAmpBusVoltage = ( (0 << 24) | 298 ), + /// \brief The MotorResistance parameter + PARAMETERID_MotorResistance = ( (0 << 24) | 299 ), + /// \brief The MotorBackEMFConstant parameter + PARAMETERID_MotorBackEMFConstant = ( (0 << 24) | 300 ), + /// \brief The GantrySetup parameter + PARAMETERID_GantrySetup = ( (0 << 24) | 302 ), + /// \brief The RolloverMode parameter + PARAMETERID_RolloverMode = ( (0 << 24) | 303 ), + /// \brief The ResolverCoarseChannel parameter + PARAMETERID_ResolverCoarseChannel = ( (0 << 24) | 306 ), + /// \brief The ResolverFeedbackRatio parameter + PARAMETERID_ResolverFeedbackRatio = ( (0 << 24) | 307 ), + /// \brief The ResolverFeedbackOffset parameter + PARAMETERID_ResolverFeedbackOffset = ( (0 << 24) | 308 ), + /// \brief The InPositionTime parameter + PARAMETERID_InPositionTime = ( (0 << 24) | 319 ), + /// \brief The ExternalFaultAnalogInput parameter + PARAMETERID_ExternalFaultAnalogInput = ( (0 << 24) | 424 ), + /// \brief The ExternalFaultThreshold parameter + PARAMETERID_ExternalFaultThreshold = ( (0 << 24) | 425 ), + /// \brief The DisplayAxes parameter + PARAMETERID_DisplayAxes = ( (0 << 24) | 426 ), + /// \brief The DefaultDependentCoordinatedSpeed parameter + PARAMETERID_DefaultDependentCoordinatedSpeed = ( (0 << 24) | 427 ), + /// \brief The AnalogFilterSetup parameter + PARAMETERID_AnalogFilterSetup = ( (0 << 24) | 482 ), + /// \brief The ModbusMasterSlaveIPAddress parameter + PARAMETERID_ModbusMasterSlaveIPAddress = ( (0 << 24) | 489 ), + /// \brief The ModbusMasterSlavePort parameter + PARAMETERID_ModbusMasterSlavePort = ( (0 << 24) | 490 ), + /// \brief The ModbusMasterSlaveID parameter + PARAMETERID_ModbusMasterSlaveID = ( (0 << 24) | 491 ), + /// \brief The ModbusMasterInputWords parameter + PARAMETERID_ModbusMasterInputWords = ( (0 << 24) | 492 ), + /// \brief The ModbusMasterOutputWords parameter + PARAMETERID_ModbusMasterOutputWords = ( (0 << 24) | 493 ), + /// \brief The ModbusMasterInputBits parameter + PARAMETERID_ModbusMasterInputBits = ( (0 << 24) | 494 ), + /// \brief The ModbusMasterOutputBits parameter + PARAMETERID_ModbusMasterOutputBits = ( (0 << 24) | 495 ), + /// \brief The ModbusMasterSetup parameter + PARAMETERID_ModbusMasterSetup = ( (0 << 24) | 496 ), + /// \brief The ModbusMasterVirtualInputs parameter + PARAMETERID_ModbusMasterVirtualInputs = ( (0 << 24) | 499 ), + /// \brief The ModbusMasterVirtualOutputs parameter + PARAMETERID_ModbusMasterVirtualOutputs = ( (0 << 24) | 500 ), + /// \brief The ModbusMasterOutputWordsSections parameter + PARAMETERID_ModbusMasterOutputWordsSections = ( (0 << 24) | 501 ), + /// \brief The ModbusMasterOutputBitsSections parameter + PARAMETERID_ModbusMasterOutputBitsSections = ( (0 << 24) | 502 ), + /// \brief The ModbusMasterRWReadOffset parameter + PARAMETERID_ModbusMasterRWReadOffset = ( (0 << 24) | 503 ), + /// \brief The ModbusMasterInputWordsOffset parameter + PARAMETERID_ModbusMasterInputWordsOffset = ( (0 << 24) | 504 ), + /// \brief The ModbusMasterOutputWordsOffset parameter + PARAMETERID_ModbusMasterOutputWordsOffset = ( (0 << 24) | 505 ), + /// \brief The ModbusMasterInputBitsOffset parameter + PARAMETERID_ModbusMasterInputBitsOffset = ( (0 << 24) | 506 ), + /// \brief The ModbusMasterOutputBitsOffset parameter + PARAMETERID_ModbusMasterOutputBitsOffset = ( (0 << 24) | 507 ), + /// \brief The ModbusMasterStatusWordsOffset parameter + PARAMETERID_ModbusMasterStatusWordsOffset = ( (0 << 24) | 508 ), + /// \brief The ModbusMasterStatusBitsOffset parameter + PARAMETERID_ModbusMasterStatusBitsOffset = ( (0 << 24) | 509 ), + /// \brief The ModbusMasterVirtualInputsOffset parameter + PARAMETERID_ModbusMasterVirtualInputsOffset = ( (0 << 24) | 510 ), + /// \brief The ModbusMasterVirtualOutputsOffset parameter + PARAMETERID_ModbusMasterVirtualOutputsOffset = ( (0 << 24) | 511 ), + /// \brief The ModbusMasterRWWriteOffset parameter + PARAMETERID_ModbusMasterRWWriteOffset = ( (0 << 24) | 512 ), + /// \brief The ModbusMasterFunctions parameter + PARAMETERID_ModbusMasterFunctions = ( (0 << 24) | 513 ), + /// \brief The ModbusMasterSlaveType parameter + PARAMETERID_ModbusMasterSlaveType = ( (0 << 24) | 514 ), + /// \brief The ModbusSlaveUnitID parameter + PARAMETERID_ModbusSlaveUnitID = ( (0 << 24) | 516 ), + /// \brief The ModbusSlaveInputWords parameter + PARAMETERID_ModbusSlaveInputWords = ( (0 << 24) | 517 ), + /// \brief The ModbusSlaveOutputWords parameter + PARAMETERID_ModbusSlaveOutputWords = ( (0 << 24) | 518 ), + /// \brief The ModbusSlaveInputBits parameter + PARAMETERID_ModbusSlaveInputBits = ( (0 << 24) | 519 ), + /// \brief The ModbusSlaveOutputBits parameter + PARAMETERID_ModbusSlaveOutputBits = ( (0 << 24) | 520 ), + /// \brief The ModbusSlaveInputWordsOffset parameter + PARAMETERID_ModbusSlaveInputWordsOffset = ( (0 << 24) | 521 ), + /// \brief The ModbusSlaveOutputWordsOffset parameter + PARAMETERID_ModbusSlaveOutputWordsOffset = ( (0 << 24) | 522 ), + /// \brief The ModbusSlaveInputBitsOffset parameter + PARAMETERID_ModbusSlaveInputBitsOffset = ( (0 << 24) | 523 ), + /// \brief The ModbusSlaveOutputBitsOffset parameter + PARAMETERID_ModbusSlaveOutputBitsOffset = ( (0 << 24) | 524 ), + /// \brief The ModbusSlaveRWReadOffset parameter + PARAMETERID_ModbusSlaveRWReadOffset = ( (0 << 24) | 525 ), + /// \brief The ModbusSlaveRWWriteOffset parameter + PARAMETERID_ModbusSlaveRWWriteOffset = ( (0 << 24) | 526 ), + /// \brief The CurrentOffsetA parameter + PARAMETERID_CurrentOffsetA = ( (0 << 24) | 662 ), + /// \brief The CurrentOffsetB parameter + PARAMETERID_CurrentOffsetB = ( (0 << 24) | 663 ), + /// \brief The CommandShaperSetup parameter + PARAMETERID_CommandShaperSetup = ( (0 << 24) | 666 ), + /// \brief The CommandShaperTime00 parameter + PARAMETERID_CommandShaperTime00 = ( (0 << 24) | 667 ), + /// \brief The CommandShaperTime01 parameter + PARAMETERID_CommandShaperTime01 = ( (0 << 24) | 668 ), + /// \brief The CommandShaperTime02 parameter + PARAMETERID_CommandShaperTime02 = ( (0 << 24) | 669 ), + /// \brief The CommandShaperTime03 parameter + PARAMETERID_CommandShaperTime03 = ( (0 << 24) | 670 ), + /// \brief The CommandShaperTime04 parameter + PARAMETERID_CommandShaperTime04 = ( (0 << 24) | 671 ), + /// \brief The CommandShaperTime05 parameter + PARAMETERID_CommandShaperTime05 = ( (0 << 24) | 672 ), + /// \brief The CommandShaperTime06 parameter + PARAMETERID_CommandShaperTime06 = ( (0 << 24) | 673 ), + /// \brief The CommandShaperTime07 parameter + PARAMETERID_CommandShaperTime07 = ( (0 << 24) | 674 ), + /// \brief The CommandShaperTime08 parameter + PARAMETERID_CommandShaperTime08 = ( (0 << 24) | 675 ), + /// \brief The CommandShaperTime09 parameter + PARAMETERID_CommandShaperTime09 = ( (0 << 24) | 676 ), + /// \brief The CommandShaperTime10 parameter + PARAMETERID_CommandShaperTime10 = ( (0 << 24) | 677 ), + /// \brief The CommandShaperTime11 parameter + PARAMETERID_CommandShaperTime11 = ( (0 << 24) | 678 ), + /// \brief The CommandShaperTime12 parameter + PARAMETERID_CommandShaperTime12 = ( (0 << 24) | 679 ), + /// \brief The CommandShaperTime13 parameter + PARAMETERID_CommandShaperTime13 = ( (0 << 24) | 680 ), + /// \brief The CommandShaperTime14 parameter + PARAMETERID_CommandShaperTime14 = ( (0 << 24) | 681 ), + /// \brief The CommandShaperTime15 parameter + PARAMETERID_CommandShaperTime15 = ( (0 << 24) | 682 ), + /// \brief The CommandShaperCoeff00 parameter + PARAMETERID_CommandShaperCoeff00 = ( (0 << 24) | 683 ), + /// \brief The CommandShaperCoeff01 parameter + PARAMETERID_CommandShaperCoeff01 = ( (0 << 24) | 684 ), + /// \brief The CommandShaperCoeff02 parameter + PARAMETERID_CommandShaperCoeff02 = ( (0 << 24) | 685 ), + /// \brief The CommandShaperCoeff03 parameter + PARAMETERID_CommandShaperCoeff03 = ( (0 << 24) | 686 ), + /// \brief The CommandShaperCoeff04 parameter + PARAMETERID_CommandShaperCoeff04 = ( (0 << 24) | 687 ), + /// \brief The CommandShaperCoeff05 parameter + PARAMETERID_CommandShaperCoeff05 = ( (0 << 24) | 688 ), + /// \brief The CommandShaperCoeff06 parameter + PARAMETERID_CommandShaperCoeff06 = ( (0 << 24) | 689 ), + /// \brief The CommandShaperCoeff07 parameter + PARAMETERID_CommandShaperCoeff07 = ( (0 << 24) | 690 ), + /// \brief The CommandShaperCoeff08 parameter + PARAMETERID_CommandShaperCoeff08 = ( (0 << 24) | 691 ), + /// \brief The CommandShaperCoeff09 parameter + PARAMETERID_CommandShaperCoeff09 = ( (0 << 24) | 692 ), + /// \brief The CommandShaperCoeff10 parameter + PARAMETERID_CommandShaperCoeff10 = ( (0 << 24) | 693 ), + /// \brief The CommandShaperCoeff11 parameter + PARAMETERID_CommandShaperCoeff11 = ( (0 << 24) | 694 ), + /// \brief The CommandShaperCoeff12 parameter + PARAMETERID_CommandShaperCoeff12 = ( (0 << 24) | 695 ), + /// \brief The CommandShaperCoeff13 parameter + PARAMETERID_CommandShaperCoeff13 = ( (0 << 24) | 696 ), + /// \brief The CommandShaperCoeff14 parameter + PARAMETERID_CommandShaperCoeff14 = ( (0 << 24) | 697 ), + /// \brief The CommandShaperCoeff15 parameter + PARAMETERID_CommandShaperCoeff15 = ( (0 << 24) | 698 ), + /// \brief The CommandShaper0Type parameter + PARAMETERID_CommandShaper0Type = ( (0 << 24) | 703 ), + /// \brief The CommandShaper0Frequency parameter + PARAMETERID_CommandShaper0Frequency = ( (0 << 24) | 704 ), + /// \brief The CommandShaper0Damping parameter + PARAMETERID_CommandShaper0Damping = ( (0 << 24) | 705 ), + /// \brief The CommandShaper1Type parameter + PARAMETERID_CommandShaper1Type = ( (0 << 24) | 706 ), + /// \brief The CommandShaper1Frequency parameter + PARAMETERID_CommandShaper1Frequency = ( (0 << 24) | 707 ), + /// \brief The CommandShaper1Damping parameter + PARAMETERID_CommandShaper1Damping = ( (0 << 24) | 708 ), + /// \brief The ResoluteEncoderSetup parameter + PARAMETERID_ResoluteEncoderSetup = ( (0 << 24) | 715 ), + /// \brief The ResoluteEncoderResolution parameter + PARAMETERID_ResoluteEncoderResolution = ( (0 << 24) | 716 ), + /// \brief The ResoluteEncoderUserResolution parameter + PARAMETERID_ResoluteEncoderUserResolution = ( (0 << 24) | 717 ), + /// \brief The AutofocusInput parameter + PARAMETERID_AutofocusInput = ( (0 << 24) | 721 ), + /// \brief The AutofocusTarget parameter + PARAMETERID_AutofocusTarget = ( (0 << 24) | 722 ), + /// \brief The AutofocusDeadband parameter + PARAMETERID_AutofocusDeadband = ( (0 << 24) | 723 ), + /// \brief The AutofocusGainKi parameter + PARAMETERID_AutofocusGainKi = ( (0 << 24) | 724 ), + /// \brief The AutofocusGainKp parameter + PARAMETERID_AutofocusGainKp = ( (0 << 24) | 725 ), + /// \brief The AutofocusLimitLow parameter + PARAMETERID_AutofocusLimitLow = ( (0 << 24) | 726 ), + /// \brief The AutofocusLimitHigh parameter + PARAMETERID_AutofocusLimitHigh = ( (0 << 24) | 727 ), + /// \brief The AutofocusSpeedClamp parameter + PARAMETERID_AutofocusSpeedClamp = ( (0 << 24) | 728 ), + /// \brief The AutofocusHoldInput parameter + PARAMETERID_AutofocusHoldInput = ( (0 << 24) | 729 ), + /// \brief The AutofocusSetup parameter + PARAMETERID_AutofocusSetup = ( (0 << 24) | 730 ), + /// \brief The ExternalSyncFrequency parameter + PARAMETERID_ExternalSyncFrequency = ( (0 << 24) | 731 ), + /// \brief The GainPff parameter + PARAMETERID_GainPff = ( (0 << 24) | 762 ), + /// \brief The AutofocusInitialRampTime parameter + PARAMETERID_AutofocusInitialRampTime = ( (0 << 24) | 763 ), +} PARAMETERID; + +#endif // __PARAMETER_ID_H__ diff --git a/motorApp/AerotechSrc/README b/motorApp/AerotechSrc/README index bd76290..a906c6e 100644 --- a/motorApp/AerotechSrc/README +++ b/motorApp/AerotechSrc/README @@ -91,6 +91,15 @@ between the call to drvAsynIPPortConfigure() and the call to EnsembleAsynConfig() in the st.cmd file must be less than the ->Socket2Timeout Parameter. If this is not done a socket timeout will occur during IOC initialization and prevent EPICS from making a communication connection.) +- In order to execute a home search from EPICS, configure the following. + - Set the System > TaskExecutionSetup parameter so that the Auxiliary task is enabled + - Copy the HomeAsync.ab from + C:\Program Files (x86)\Aerotech\Ensemble\Samples\AeroBasic + to convenient local directory, such as + C:\Users\Public\Documents\Aerotech\Ensemble\User Files\AeroBasicPrgms + - From Ensemble Motion Composer, select the Auxililary task, then build and load the HomeAsync program. + - Finally, from Ensemble Configuration Manager, drag and drop the HomeAsync.bcx file to the Ensemble congtroller's file system. + DRIVER LIMITATIONS diff --git a/motorApp/AerotechSrc/devAerotech.dbd b/motorApp/AerotechSrc/devAerotech.dbd index 1a742bf..3619889 100644 --- a/motorApp/AerotechSrc/devAerotech.dbd +++ b/motorApp/AerotechSrc/devAerotech.dbd @@ -10,4 +10,3 @@ driver(motorA3200) registrar(AerotechRegister) registrar(concatStringRegister) -registrar(EnsembleTrajectoryScanRegistrar) diff --git a/motorApp/AerotechSrc/devAerotechSeq.dbd b/motorApp/AerotechSrc/devAerotechSeq.dbd new file mode 100644 index 0000000..b3872d3 --- /dev/null +++ b/motorApp/AerotechSrc/devAerotechSeq.dbd @@ -0,0 +1 @@ +registrar(EnsembleTrajectoryScanRegistrar) diff --git a/motorApp/AerotechSrc/devSoloist.cc b/motorApp/AerotechSrc/devSoloist.cc index dcd913c..41762da 100644 --- a/motorApp/AerotechSrc/devSoloist.cc +++ b/motorApp/AerotechSrc/devSoloist.cc @@ -2,10 +2,6 @@ * FILENAME... devSoloist.cc * USAGE... Motor record device level support for Aerotech Soloist. * -* Version: $Revision: 10834 $ -* Modified By: $Author: sluiter $ -* Last Modified: $Date: 2010-04-29 12:04:39 -0500 (Thu, 29 Apr 2010) $ -* HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/AerotechSrc/devSoloist.cc $ * */ @@ -44,6 +40,7 @@ #include #include #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -54,7 +51,7 @@ extern struct driver_table Soloist_access; /* ----------------Create the dsets for devSoloist----------------- */ static struct driver_table *drvtabptr; -static long Soloist_init (void *); +static long Soloist_init (int); static long Soloist_init_record (void *); static long Soloist_start_trans (struct motorRecord *); static RTN_STATUS Soloist_build_trans (motor_cmnd, double *, @@ -111,12 +108,11 @@ static struct board_stat **Soloist_cards; // initialize device support for Soloist -static long Soloist_init (void *arg) +static long Soloist_init (int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &Soloist_access; (drvtabptr->init)(); diff --git a/motorApp/AerotechSrc/doCommand.ab b/motorApp/AerotechSrc/doCommand.ab index 8879969..e459bc5 100755 --- a/motorApp/AerotechSrc/doCommand.ab +++ b/motorApp/AerotechSrc/doCommand.ab @@ -1,235 +1,235 @@ -HEADER - DEFINE cmdDONE 0 - DEFINE cmdVELOCITY_ON 1 - DEFINE cmdVELOCITY_OFF 2 - DEFINE cmdHALT 3 - DEFINE cmdSTART 4 - DEFINE cmdPVT_INIT_TIME_ABS 5 - DEFINE cmdPVT_INIT_TIME_INC 6 - DEFINE cmdPVT1 7 - DEFINE cmdPVT2 8 - DEFINE cmdPVT3 9 - DEFINE cmdPVT 10 - DEFINE cmdABORT 11 - DEFINE cmdSTARTABORT 12 - - DEFINE cmdSCOPEBUFFER 13 - DEFINE cmdSCOPEDATA 14 - DEFINE cmdSCOPESTATUS 15 - DEFINE cmdSCOPETRIG 16 - DEFINE cmdSCOPETRIGPERIOD 17 - DEFINE cmdDRIVEINFO 18 - DEFINE cmdLINEAR 19 - DEFINE cmdDATAACQ_TRIG 20 - DEFINE cmdDATAACQ_INP 21 - DEFINE cmdDATAACQ_ON 22 - DEFINE cmdDATAACQ_OFF 23 - DEFINE cmdDATAACQ_READ 24 - DEFINE cmdDOTRAJECTORY 25 - - DEFINE cmdVar 45 - DEFINE iarg1Var 46 - DEFINE iarg2Var 47 - DEFINE iarg3Var 48 - DEFINE iarg4Var 49 - DEFINE darg1Var 1 - DEFINE darg2Var 2 - DEFINE darg3Var 3 - DEFINE darg4Var 4 - DEFINE darg5Var 5 - DEFINE darg6Var 6 - DEFINE darg7Var 7 - DEFINE darg8Var 8 - DEFINE darg9Var 9 - DEFINE numIArg 44 - DEFINE numDArg 43 - DEFINE pvtWaitMSVar 42 - - ' Numerical values for first arg to scopedata() - DEFINE sd_PositionCommand 0 - DEFINE sd_PositionFeedback 1 - DEFINE sd_ExternalPosition 2 - DEFINE sd_AxisFault 3 - DEFINE sd_AxisStatus 4 - DEFINE sd_AnalogInput0 5 - DEFINE sd_AnalogInput1 6 - DEFINE sd_AnalogOutput0 7 - DEFINE sd_AnalogOutput1 8 - DEFINE sd_DigitalInput0 9 - DEFINE sd_DigitalInput1 10 - DEFINE sd_DigitalOutput0 11 - DEFINE sd_DigitalOutput1 12 - DEFINE sd_CurrentCommand 13 - DEFINE sd_CurrentFeedback 14 - DEFINE sd_OptionalData1 15 - DEFINE sd_OptionalData2 16 - DEFINE sd_ProgramCounter 17 - -END HEADER - -PROGRAM - - DIM axis1Number AS Integer - DIM axis2Number AS Integer - DIM axis3Number AS Integer - DIM axis4Number AS Integer - DIM keepon as Integer - DIM iarg as integer - DIM pvtWaitMS as integer - dim pos as double - dim vel as double - dim timeval as double - dim timeIsAbs as integer - dim timeInitialized as integer - dim numpoints as integer - dim i as integer - - wait mode nowait - ABS - keepon = 1 - pvtWaitMS = IGLOBAL(pvtWaitMSVar) - IF pvtWaitMS < 1 THEN - pvtWaitMS = 50 - END IF - WHILE keepon - IF IGLOBAL(cmdVar) = cmdPVT1 THEN - axis1Number = IGLOBAL(iarg1Var) - pos = DGLOBAL(darg1Var) - vel = DGLOBAL(darg2Var) - timeval = DGLOBAL(darg3Var) - if timeIsAbs and not timeInitialized then - PVT INIT TIME ABS - timeInitialized = 1 - end if - PVT @axis1Number pos, vel TIME timeval - ELSEIF IGLOBAL(cmdVar) = cmdVELOCITY_ON THEN - VELOCITY ON - ELSEIF IGLOBAL(cmdVar) = cmdVELOCITY_OFF THEN - VELOCITY OFF - ELSEIF IGLOBAL(cmdVar) = cmdHALT THEN - HALT - ELSEIF IGLOBAL(cmdVar) = cmdSTARTABORT THEN - START - ABORT @0 - acknowledgeall - enable @0 - keepon = 0 - ELSEIF IGLOBAL(cmdVar) = cmdSTART THEN - START - keepon = 0 - ELSEIF IGLOBAL(cmdVar) = cmdPVT THEN - axis1Number = IGLOBAL(iarg1Var) - axis2Number = IGLOBAL(iarg2Var) - axis3Number = IGLOBAL(iarg3Var) - axis4Number = IGLOBAL(iarg4Var) - if IGLOBAL(numIArg) = 1 then - PVT @axis1Number DGLOBAL(darg1Var), DGLOBAL(darg2Var) TIME DGLOBAL(darg3Var) - elseif IGLOBAL(numIArg) = 2 then - PVT @axis1Number DGLOBAL(darg1Var), DGLOBAL(darg2Var) @axis2Number DGLOBAL(darg3Var), DGLOBAL(darg4Var) TIME DGLOBAL(darg5Var) - elseif IGLOBAL(numIArg) = 3 then - PVT @axis1Number DGLOBAL(darg1Var), DGLOBAL(darg2Var) @axis2Number DGLOBAL(darg3Var), DGLOBAL(darg4Var) @axis3Number DGLOBAL(darg5Var), DGLOBAL(darg6Var) TIME DGLOBAL(darg7Var) - elseif IGLOBAL(numIArg) = 4 then - PVT @axis1Number DGLOBAL(darg1Var), DGLOBAL(darg2Var) @axis2Number DGLOBAL(darg3Var), DGLOBAL(darg4Var) @axis3Number DGLOBAL(darg5Var), DGLOBAL(darg6Var) @axis4Number DGLOBAL(darg7Var), DGLOBAL(darg8Var) TIME DGLOBAL(darg9Var) - end if - ELSEIF IGLOBAL(cmdVar) = cmdPVT_INIT_TIME_ABS THEN - 'PVT INIT TIME ABS - timeIsAbs = 1 - timeInitialized = 0 - ELSEIF IGLOBAL(cmdVar) = cmdPVT_INIT_TIME_INC THEN - timeIsAbs = 0 - PVT INIT TIME INC - ELSEIF IGLOBAL(cmdVar) = cmdABORT THEN - axis1Number = IGLOBAL(iarg1Var) - axis2Number = IGLOBAL(iarg2Var) - axis3Number = IGLOBAL(iarg3Var) - axis4Number = IGLOBAL(iarg4Var) - if IGLOBAL(numIArg) = 1 then - ABORT @axis1Number - elseif IGLOBAL(numIArg) = 2 then - ABORT @axis1Number @axis2Number - elseif IGLOBAL(numIArg) = 3 then - ABORT @axis1Number @axis2Number @axis3Number - elseif IGLOBAL(numIArg) = 4 then - ABORT @axis1Number @axis2Number @axis3Number @axis4Number - end if - keepon = 0 - ELSEIF IGLOBAL(cmdVar) = cmdSCOPEBUFFER THEN - iarg = IGLOBAL(iarg1Var) - SCOPEBUFFER iarg - ELSEIF IGLOBAL(cmdVar) = cmdSCOPEDATA THEN - iarg = IGLOBAL(iarg1Var) - if iarg = sd_PositionCommand then - DGLOBAL(darg1Var) = SCOPEDATA(PositionCommand, IGLOBAL(iarg2Var)) - elseif iarg = sd_PositionFeedback then - DGLOBAL(darg1Var) = SCOPEDATA(PositionFeedback, IGLOBAL(iarg2Var)) - elseif iarg = sd_CurrentFeedback then - DGLOBAL(darg1Var) = SCOPEDATA(CurrentFeedback, IGLOBAL(iarg2Var)) - else - DGLOBAL(darg1Var) = -1.2345654321 - end if - ELSEIF IGLOBAL(cmdVar) = cmdSCOPESTATUS THEN - IGLOBAL(iarg1Var) = SCOPESTATUS(IGLOBAL(iarg1Var)) - ELSEIF IGLOBAL(cmdVar) = cmdSCOPETRIG THEN - if IGLOBAL(iarg1Var) = 1 then - SCOPETRIG STOP - ELSE - SCOPETRIG - END IF - ELSEIF IGLOBAL(cmdVar) = cmdSCOPETRIGPERIOD THEN - iarg = IGLOBAL(iarg1Var) - 'SCOPETRIGPERIOD iarg - SCOPETRIGPERIOD iarg*1.0 - ' Not until version 4.03 - ' ELSEIF IGLOBAL(cmdVar) = cmdDRIVEINFO THEN - ' IGLOBAL(iarg1Var) = DRIVEINFO(X, 59) - ELSEIF IGLOBAL(cmdVar) = cmdLINEAR THEN - axis1Number = IGLOBAL(iarg1Var) - LINEAR @axis1Number DGLOBAL(darg1Var) F DGLOBAL(darg2Var) - ELSEIF IGLOBAL(cmdVar) = cmdDATAACQ_TRIG THEN - axis1Number = IGLOBAL(iarg1Var) - DATAACQ @axis1Number TRIGGER IGLOBAL(iarg2Var) - ELSEIF IGLOBAL(cmdVar) = cmdDATAACQ_INP THEN - axis1Number = IGLOBAL(iarg1Var) - DATAACQ @axis1Number INPUT IGLOBAL(iarg2Var) - ELSEIF IGLOBAL(cmdVar) = cmdDATAACQ_ON THEN - axis1Number = IGLOBAL(iarg1Var) - DATAACQ @axis1Number ON IGLOBAL(iarg2Var) - ELSEIF IGLOBAL(cmdVar) = cmdDATAACQ_OFF THEN - axis1Number = IGLOBAL(iarg1Var) - DATAACQ @axis1Number OFF - ELSEIF IGLOBAL(cmdVar) = cmdDATAACQ_READ THEN - axis1Number = IGLOBAL(iarg1Var) - DATAACQ @axis1Number READ IGLOBAL(iarg2Var), IGLOBAL(iarg3Var) - ELSEIF IGLOBAL(cmdVar) = cmdDOTRAJECTORY THEN - axis1Number = IGLOBAL(iarg1Var) - numpoints = IGLOBAL(iarg2Var) - VELOCITY ON - PVT INIT TIME ABS - for i = 0 to numpoints-1 step 1 - pos = dglobal(3*i) - vel = dglobal(3*i+1) - timeVal = dglobal(3*i+2) - if i = numpoints-2 then - VELOCITY OFF - end if - PVT @axis1Number pos, vel time timeVal - dwell pvtWaitMS/1000 - next i - elseif IGLOBAL(cmdVar) = cmdDONE then - ' do nothing - ' else - ' IGLOBAL(cmdVar) = 1000 - END IF - - IF IGLOBAL(cmdVar) = cmdPVT1 THEN - D = pvtWaitMS/1000 - ELSE - D = .001 - END IF - if IGLOBAL(cmdVar) > 0 then - IGLOBAL(cmdVar) = -(IGLOBAL(cmdVar)) - end if - DWELL D - WEND - -END PROGRAM +HEADER + DEFINE cmdDONE 0 + DEFINE cmdVELOCITY_ON 1 + DEFINE cmdVELOCITY_OFF 2 + DEFINE cmdHALT 3 + DEFINE cmdSTART 4 + DEFINE cmdPVT_INIT_TIME_ABS 5 + DEFINE cmdPVT_INIT_TIME_INC 6 + DEFINE cmdPVT1 7 + DEFINE cmdPVT2 8 + DEFINE cmdPVT3 9 + DEFINE cmdPVT 10 + DEFINE cmdABORT 11 + DEFINE cmdSTARTABORT 12 + + DEFINE cmdSCOPEBUFFER 13 + DEFINE cmdSCOPEDATA 14 + DEFINE cmdSCOPESTATUS 15 + DEFINE cmdSCOPETRIG 16 + DEFINE cmdSCOPETRIGPERIOD 17 + DEFINE cmdDRIVEINFO 18 + DEFINE cmdLINEAR 19 + DEFINE cmdDATAACQ_TRIG 20 + DEFINE cmdDATAACQ_INP 21 + DEFINE cmdDATAACQ_ON 22 + DEFINE cmdDATAACQ_OFF 23 + DEFINE cmdDATAACQ_READ 24 + DEFINE cmdDOTRAJECTORY 25 + + DEFINE cmdVar 45 + DEFINE iarg1Var 46 + DEFINE iarg2Var 47 + DEFINE iarg3Var 48 + DEFINE iarg4Var 49 + DEFINE darg1Var 1 + DEFINE darg2Var 2 + DEFINE darg3Var 3 + DEFINE darg4Var 4 + DEFINE darg5Var 5 + DEFINE darg6Var 6 + DEFINE darg7Var 7 + DEFINE darg8Var 8 + DEFINE darg9Var 9 + DEFINE numIArg 44 + DEFINE numDArg 43 + DEFINE pvtWaitMSVar 42 + + ' Numerical values for first arg to scopedata() + DEFINE sd_PositionCommand 0 + DEFINE sd_PositionFeedback 1 + DEFINE sd_ExternalPosition 2 + DEFINE sd_AxisFault 3 + DEFINE sd_AxisStatus 4 + DEFINE sd_AnalogInput0 5 + DEFINE sd_AnalogInput1 6 + DEFINE sd_AnalogOutput0 7 + DEFINE sd_AnalogOutput1 8 + DEFINE sd_DigitalInput0 9 + DEFINE sd_DigitalInput1 10 + DEFINE sd_DigitalOutput0 11 + DEFINE sd_DigitalOutput1 12 + DEFINE sd_CurrentCommand 13 + DEFINE sd_CurrentFeedback 14 + DEFINE sd_OptionalData1 15 + DEFINE sd_OptionalData2 16 + DEFINE sd_ProgramCounter 17 + +END HEADER + +PROGRAM + + DIM axis1Number AS Integer + DIM axis2Number AS Integer + DIM axis3Number AS Integer + DIM axis4Number AS Integer + DIM keepon as Integer + DIM iarg as integer + DIM pvtWaitMS as integer + dim pos as double + dim vel as double + dim timeval as double + dim timeIsAbs as integer + dim timeInitialized as integer + dim numpoints as integer + dim i as integer + + wait mode nowait + ABS + keepon = 1 + pvtWaitMS = IGLOBAL(pvtWaitMSVar) + IF pvtWaitMS < 1 THEN + pvtWaitMS = 50 + END IF + WHILE keepon + IF IGLOBAL(cmdVar) = cmdPVT1 THEN + axis1Number = IGLOBAL(iarg1Var) + pos = DGLOBAL(darg1Var) + vel = DGLOBAL(darg2Var) + timeval = DGLOBAL(darg3Var) + if timeIsAbs and not timeInitialized then + PVT INIT TIME ABS + timeInitialized = 1 + end if + PVT @axis1Number pos, vel TIME timeval + ELSEIF IGLOBAL(cmdVar) = cmdVELOCITY_ON THEN + VELOCITY ON + ELSEIF IGLOBAL(cmdVar) = cmdVELOCITY_OFF THEN + VELOCITY OFF + ELSEIF IGLOBAL(cmdVar) = cmdHALT THEN + HALT + ELSEIF IGLOBAL(cmdVar) = cmdSTARTABORT THEN + START + ABORT @0 + acknowledgeall + enable @0 + keepon = 0 + ELSEIF IGLOBAL(cmdVar) = cmdSTART THEN + START + keepon = 0 + ELSEIF IGLOBAL(cmdVar) = cmdPVT THEN + axis1Number = IGLOBAL(iarg1Var) + axis2Number = IGLOBAL(iarg2Var) + axis3Number = IGLOBAL(iarg3Var) + axis4Number = IGLOBAL(iarg4Var) + if IGLOBAL(numIArg) = 1 then + PVT @axis1Number DGLOBAL(darg1Var), DGLOBAL(darg2Var) TIME DGLOBAL(darg3Var) + elseif IGLOBAL(numIArg) = 2 then + PVT @axis1Number DGLOBAL(darg1Var), DGLOBAL(darg2Var) @axis2Number DGLOBAL(darg3Var), DGLOBAL(darg4Var) TIME DGLOBAL(darg5Var) + elseif IGLOBAL(numIArg) = 3 then + PVT @axis1Number DGLOBAL(darg1Var), DGLOBAL(darg2Var) @axis2Number DGLOBAL(darg3Var), DGLOBAL(darg4Var) @axis3Number DGLOBAL(darg5Var), DGLOBAL(darg6Var) TIME DGLOBAL(darg7Var) + elseif IGLOBAL(numIArg) = 4 then + PVT @axis1Number DGLOBAL(darg1Var), DGLOBAL(darg2Var) @axis2Number DGLOBAL(darg3Var), DGLOBAL(darg4Var) @axis3Number DGLOBAL(darg5Var), DGLOBAL(darg6Var) @axis4Number DGLOBAL(darg7Var), DGLOBAL(darg8Var) TIME DGLOBAL(darg9Var) + end if + ELSEIF IGLOBAL(cmdVar) = cmdPVT_INIT_TIME_ABS THEN + 'PVT INIT TIME ABS + timeIsAbs = 1 + timeInitialized = 0 + ELSEIF IGLOBAL(cmdVar) = cmdPVT_INIT_TIME_INC THEN + timeIsAbs = 0 + PVT INIT TIME INC + ELSEIF IGLOBAL(cmdVar) = cmdABORT THEN + axis1Number = IGLOBAL(iarg1Var) + axis2Number = IGLOBAL(iarg2Var) + axis3Number = IGLOBAL(iarg3Var) + axis4Number = IGLOBAL(iarg4Var) + if IGLOBAL(numIArg) = 1 then + ABORT @axis1Number + elseif IGLOBAL(numIArg) = 2 then + ABORT @axis1Number @axis2Number + elseif IGLOBAL(numIArg) = 3 then + ABORT @axis1Number @axis2Number @axis3Number + elseif IGLOBAL(numIArg) = 4 then + ABORT @axis1Number @axis2Number @axis3Number @axis4Number + end if + keepon = 0 + ELSEIF IGLOBAL(cmdVar) = cmdSCOPEBUFFER THEN + iarg = IGLOBAL(iarg1Var) + SCOPEBUFFER iarg + ELSEIF IGLOBAL(cmdVar) = cmdSCOPEDATA THEN + iarg = IGLOBAL(iarg1Var) + if iarg = sd_PositionCommand then + DGLOBAL(darg1Var) = SCOPEDATA(PositionCommand, IGLOBAL(iarg2Var)) + elseif iarg = sd_PositionFeedback then + DGLOBAL(darg1Var) = SCOPEDATA(PositionFeedback, IGLOBAL(iarg2Var)) + elseif iarg = sd_CurrentFeedback then + DGLOBAL(darg1Var) = SCOPEDATA(CurrentFeedback, IGLOBAL(iarg2Var)) + else + DGLOBAL(darg1Var) = -1.2345654321 + end if + ELSEIF IGLOBAL(cmdVar) = cmdSCOPESTATUS THEN + IGLOBAL(iarg1Var) = SCOPESTATUS(IGLOBAL(iarg1Var)) + ELSEIF IGLOBAL(cmdVar) = cmdSCOPETRIG THEN + if IGLOBAL(iarg1Var) = 1 then + SCOPETRIG STOP + ELSE + SCOPETRIG + END IF + ELSEIF IGLOBAL(cmdVar) = cmdSCOPETRIGPERIOD THEN + iarg = IGLOBAL(iarg1Var) + 'SCOPETRIGPERIOD iarg + SCOPETRIGPERIOD iarg*1.0 + ' Not until version 4.03 + ' ELSEIF IGLOBAL(cmdVar) = cmdDRIVEINFO THEN + ' IGLOBAL(iarg1Var) = DRIVEINFO(X, 59) + ELSEIF IGLOBAL(cmdVar) = cmdLINEAR THEN + axis1Number = IGLOBAL(iarg1Var) + LINEAR @axis1Number DGLOBAL(darg1Var) F DGLOBAL(darg2Var) + ELSEIF IGLOBAL(cmdVar) = cmdDATAACQ_TRIG THEN + axis1Number = IGLOBAL(iarg1Var) + DATAACQ @axis1Number TRIGGER IGLOBAL(iarg2Var) + ELSEIF IGLOBAL(cmdVar) = cmdDATAACQ_INP THEN + axis1Number = IGLOBAL(iarg1Var) + DATAACQ @axis1Number INPUT IGLOBAL(iarg2Var) + ELSEIF IGLOBAL(cmdVar) = cmdDATAACQ_ON THEN + axis1Number = IGLOBAL(iarg1Var) + DATAACQ @axis1Number ON IGLOBAL(iarg2Var) + ELSEIF IGLOBAL(cmdVar) = cmdDATAACQ_OFF THEN + axis1Number = IGLOBAL(iarg1Var) + DATAACQ @axis1Number OFF + ELSEIF IGLOBAL(cmdVar) = cmdDATAACQ_READ THEN + axis1Number = IGLOBAL(iarg1Var) + DATAACQ @axis1Number READ IGLOBAL(iarg2Var), IGLOBAL(iarg3Var) + ELSEIF IGLOBAL(cmdVar) = cmdDOTRAJECTORY THEN + axis1Number = IGLOBAL(iarg1Var) + numpoints = IGLOBAL(iarg2Var) + VELOCITY ON + PVT INIT TIME ABS + for i = 0 to numpoints-1 step 1 + pos = dglobal(3*i) + vel = dglobal(3*i+1) + timeVal = dglobal(3*i+2) + if i = numpoints-2 then + VELOCITY OFF + end if + PVT @axis1Number pos, vel time timeVal + dwell pvtWaitMS/1000 + next i + elseif IGLOBAL(cmdVar) = cmdDONE then + ' do nothing + ' else + ' IGLOBAL(cmdVar) = 1000 + END IF + + IF IGLOBAL(cmdVar) = cmdPVT1 THEN + D = pvtWaitMS/1000 + ELSE + D = .001 + END IF + if IGLOBAL(cmdVar) > 0 then + IGLOBAL(cmdVar) = -(IGLOBAL(cmdVar)) + end if + DWELL D + WEND + +END PROGRAM diff --git a/motorApp/AerotechSrc/drvA3200Asyn.cc b/motorApp/AerotechSrc/drvA3200Asyn.cc index d217ba6..19719ef 100644 --- a/motorApp/AerotechSrc/drvA3200Asyn.cc +++ b/motorApp/AerotechSrc/drvA3200Asyn.cc @@ -2,10 +2,6 @@ FILENAME... drvA3200Asyn.cc USAGE... Motor record asyn driver level support for Aerotech A3200. -Version: $Revision: 17434 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2014-05-21 11:43:51 -0500 (Wed, 21 May 2014) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/AerotechSrc/drvA3200Asyn.cc $ */ /* @@ -16,23 +12,35 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- ----------------------------------------------------------------------------- COPYRIGHT NOTICE ----------------------------------------------------------------------------- -Copyright (c) 2002 The University of Chicago, as Operator of Argonne -National Laboratory. +Copyright (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory. Copyright (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory. -Synapps Versions 4-5 -and higher are distributed subject to a Software License Agreement found +Synapps Versions 4-5 and higher are distributed subject to a Software License Agreement found in file LICENSE that is included with this distribution. ----------------------------------------------------------------------------- * NOTES * ----- * Verified with firmware: * - 4.07.000 -* +* +* A3200 Task Usage - This driver uses a user selectable Task #n for the ASCII Interface and +* Task #(n+1) to clear Task #n errors and ABORT axis moves issued by Task #n. +* * Modification Log: * ----------------- * * .01 11-15-13 cjb Initialized from drvEnsembleAsyn.c (Aerotech) +* .02 30-04-14 rls - Removed "Task number" argument from A3200AsynConfig and switched to using Task #2 for the ASCII +* Interface. Task #3 is used to clear Task #2 errors and ABORT axis moves issued by Task #2. +* - Deleted duplicate A3200 Setup and Config arguments from AerotechRegister.cc. +* - Switched from "LINEAR" TO "MOVE[ABS/INC]" commands. +* - Added delays to motorAxisMove() and motorAxisVelocityMove() so controller has time to set +* MoveDone false before the 1st status update. +* - Added axis name to "RAMP RATE" command. +* .03 10-14-15 rls - Use "ReverseDirec" parameter to set "HomeSetup" parameter. +* .04 03-15-18 rls - Restored "Task number" argument to A3200AsynConfig. +* .05 05-01-18 rls - Do not check the limit switches of virtual axes. +* - Added "single-axis" (MOVE{ABS/INC} or "multi-axis" (LINEAR) user selectable move option. */ #include @@ -110,73 +118,74 @@ typedef union motorAxisDrvSET_t motorA3200 = { - 14, - motorAxisReport, /**< Standard EPICS driver report function (optional) */ - motorAxisInit, /**< Standard EPICS driver initialization function (optional) */ - motorAxisSetLog, /**< Defines an external logging function (optional) */ - motorAxisOpen, /**< Driver open function */ - motorAxisClose, /**< Driver close function */ - motorAxisSetCallback, /**< Provides a callback function the driver can call when the status updates */ - motorAxisSetDouble, /**< Pointer to function to set a double value */ - motorAxisSetInteger, /**< Pointer to function to set an integer value */ - motorAxisGetDouble, /**< Pointer to function to get a double value */ - motorAxisGetInteger, /**< Pointer to function to get an integer value */ - motorAxisHome, /**< Pointer to function to execute a move to reference or home */ - motorAxisMove, /**< Pointer to function to execute a position move */ - motorAxisVelocityMove, /**< Pointer to function to execute a velocity mode move */ - motorAxisStop, /**< Pointer to function to stop motion */ - motorAxisforceCallback, /**< Pointer to function to request a poller status update */ - motorAxisProfileMove, /**< Pointer to function to execute a profile move */ - motorAxisTriggerProfile /**< Pointer to function to trigger a profile move */ + 14, + motorAxisReport, /**< Standard EPICS driver report function (optional) */ + motorAxisInit, /**< Standard EPICS driver initialization function (optional) */ + motorAxisSetLog, /**< Defines an external logging function (optional) */ + motorAxisOpen, /**< Driver open function */ + motorAxisClose, /**< Driver close function */ + motorAxisSetCallback, /**< Provides a callback function the driver can call when the status updates */ + motorAxisSetDouble, /**< Pointer to function to set a double value */ + motorAxisSetInteger, /**< Pointer to function to set an integer value */ + motorAxisGetDouble, /**< Pointer to function to get a double value */ + motorAxisGetInteger, /**< Pointer to function to get an integer value */ + motorAxisHome, /**< Pointer to function to execute a move to reference or home */ + motorAxisMove, /**< Pointer to function to execute a position move */ + motorAxisVelocityMove, /**< Pointer to function to execute a velocity mode move */ + motorAxisStop, /**< Pointer to function to stop motion */ + motorAxisforceCallback, /**< Pointer to function to request a poller status update */ + motorAxisProfileMove, /**< Pointer to function to execute a profile move */ + motorAxisTriggerProfile /**< Pointer to function to trigger a profile move */ }; extern "C" { - epicsExportAddress(drvet, motorA3200); + epicsExportAddress(drvet, motorA3200); } typedef struct { - epicsMutexId controllerLock; - asynUser *pasynUser; - int numAxes; - double movingPollPeriod; - double idlePollPeriod; - epicsEventId pollEventId; - epicsMutexId sendReceiveMutex; - AXIS_HDL pAxis; /* array of axes */ - epicsUInt32 taskNumber; /* the task number to use for motion commands */ + epicsMutexId controllerLock; + asynUser *pasynUser; + int numAxes; + double movingPollPeriod; + double idlePollPeriod; + epicsEventId pollEventId; + epicsMutexId sendReceiveMutex; + AXIS_HDL pAxis; /* array of axes */ + epicsUInt32 taskNumber; /* the task number to use for motion commands */ + epicsUInt32 linear; } A3200Controller; typedef struct motorAxisHandle { - A3200Controller *pController; - PARAMS params; - double currentCmdPos; - double stepSize; - double homePreset; - int homeDirection; - int closedLoop; - int axisStatus; - int card; - int axis; - char axisName[128]; - int maxDigits; - motorAxisLogFunc print; - void *logParam; - epicsMutexId mutexId; - Switch_Level swconfig; - int lastFault; - bool reverseDirec; + A3200Controller *pController; + PARAMS params; + double currentCmdPos; + double stepSize; + double homePreset; + int homeDirection; + int closedLoop; + int axisStatus; + int card; + int axis; + char axisName[128]; + int maxDigits; + motorAxisLogFunc print; + void *logParam; + epicsMutexId mutexId; + Switch_Level swconfig; + int lastFault; + bool reverseDirec; } motorAxis; typedef struct { - AXIS_HDL pFirst; - epicsThreadId motorThread; - motorAxisLogFunc print; - void *logParam; - epicsTimeStamp now; + AXIS_HDL pFirst; + epicsThreadId motorThread; + motorAxisLogFunc print; + void *logParam; + epicsTimeStamp now; } motorA3200_t; extern "C" { static int motorA3200LogMsg(void *, const motorAxisLogMask_t, const char *, ...); } @@ -187,777 +196,864 @@ static int numA3200Controllers; /* Pointer to array of controller structures */ static A3200Controller *pA3200Controller = NULL; -#define MAX(a, b) ((a)>(b) ? (a) : (b)) -#define MIN(a, b) ((a)<(b) ? (a) : (b)) - static void motorAxisReportAxis(AXIS_HDL pAxis, int level) { - if (level > 0) - { - printf("Axis %s\n", pAxis->axisName); - printf(" axisStatus: 0x%x\n", pAxis->axisStatus); - printf(" home preset: %f\n", pAxis->homePreset); - printf(" step size: %f\n", pAxis->stepSize); - printf(" max digits: %d\n", pAxis->maxDigits); - } + if (level > 0) + { + printf("Axis %s\n", pAxis->axisName); + printf(" axisStatus: 0x%x\n", pAxis->axisStatus); + printf(" home preset: %f\n", pAxis->homePreset); + printf(" step size: %f\n", pAxis->stepSize); + printf(" max digits: %d\n", pAxis->maxDigits); + } } static void motorAxisReport(int level) { - int i, j; - - for (i = 0; i < numA3200Controllers; i++) - { - if (level) - { - printf(" moving poll period: %f\n", pA3200Controller[i].movingPollPeriod); - printf(" idle poll period: %f\n", pA3200Controller[i].idlePollPeriod); - } - for (j = 0; j < pA3200Controller[i].numAxes; j++) - { - motorAxisReportAxis(&pA3200Controller[i].pAxis[j], level); - } - } + int i, j; + + for (i = 0; i < numA3200Controllers; i++) + { + if (level) + { + printf(" moving poll period: %f\n", pA3200Controller[i].movingPollPeriod); + printf(" idle poll period: %f\n", pA3200Controller[i].idlePollPeriod); + } + for (j = 0; j < pA3200Controller[i].numAxes; j++) + { + motorAxisReportAxis(&pA3200Controller[i].pAxis[j], level); + } + } } static int motorAxisInit(void) { - int controller, axis; - - for (controller = 0; controller < numA3200Controllers; controller++) - { - AXIS_HDL pAxis; - for (axis = 0; axis < pA3200Controller[controller].numAxes; axis++) - { - pAxis = &pA3200Controller[controller].pAxis[axis]; - if (!pAxis->mutexId) - break; - epicsMutexLock(pAxis->mutexId); - - /*Set GAIN_SUPPORT on so that at least, CNEN functions. */ - motorParam->setInteger(pAxis->params, motorAxisHasClosedLoop, 1); - - motorParam->callCallback(pAxis->params); - epicsMutexUnlock(pAxis->mutexId); - } - } - return MOTOR_AXIS_OK; + int controller, axis; + + for (controller = 0; controller < numA3200Controllers; controller++) + { + AXIS_HDL pAxis; + for (axis = 0; axis < pA3200Controller[controller].numAxes; axis++) + { + pAxis = &pA3200Controller[controller].pAxis[axis]; + if (!pAxis->mutexId) + break; + epicsMutexLock(pAxis->mutexId); + + /*Set GAIN_SUPPORT on so that at least, CNEN functions. */ + motorParam->setInteger(pAxis->params, motorAxisHasClosedLoop, 1); + + motorParam->callCallback(pAxis->params); + epicsMutexUnlock(pAxis->mutexId); + } + } + return MOTOR_AXIS_OK; } static int motorAxisSetLog(AXIS_HDL pAxis, motorAxisLogFunc logFunc, void * param) { - if (pAxis == NULL) - { - if (logFunc == NULL) - { - drv.print= motorA3200LogMsg; - drv.logParam = NULL; - } - else - { - drv.print = logFunc; - drv.logParam = param; - } - } - else - { - if (logFunc == NULL) - { - pAxis->print = motorA3200LogMsg; - pAxis->logParam = NULL; - } - else - { - pAxis->print = logFunc; - pAxis->logParam = param; - } - } - return MOTOR_AXIS_OK; + if (pAxis == NULL) + { + if (logFunc == NULL) + { + drv.print = motorA3200LogMsg; + drv.logParam = NULL; + } + else + { + drv.print = logFunc; + drv.logParam = param; + } + } + else + { + if (logFunc == NULL) + { + pAxis->print = motorA3200LogMsg; + pAxis->logParam = NULL; + } + else + { + pAxis->print = logFunc; + pAxis->logParam = param; + } + } + return MOTOR_AXIS_OK; } static AXIS_HDL motorAxisOpen(int card, int axis, char * param) { - AXIS_HDL pAxis; + AXIS_HDL pAxis; - if (card >= numA3200Controllers) - return NULL; - if (axis >= pA3200Controller[card].numAxes) - return NULL; + if (card >= numA3200Controllers) + return NULL; + if (axis >= pA3200Controller[card].numAxes) + return NULL; - pAxis = &pA3200Controller[card].pAxis[axis]; - return pAxis; + pAxis = &pA3200Controller[card].pAxis[axis]; + return pAxis; } static int motorAxisClose(AXIS_HDL pAxis) { - return MOTOR_AXIS_OK; + return MOTOR_AXIS_OK; } static int motorAxisGetInteger(AXIS_HDL pAxis, motorAxisParam_t function, int * value) { - if (pAxis == NULL || pAxis->params == NULL) - return MOTOR_AXIS_ERROR; - else - return motorParam->getInteger(pAxis->params, (paramIndex) function, value); + if (pAxis == NULL || pAxis->params == NULL) + return MOTOR_AXIS_ERROR; + else + return motorParam->getInteger(pAxis->params, (paramIndex) function, value); } static int motorAxisGetDouble(AXIS_HDL pAxis, motorAxisParam_t function, double * value) { - if (pAxis == NULL || pAxis->params == NULL) - return MOTOR_AXIS_ERROR; - else - return motorParam->getDouble(pAxis->params, (paramIndex) function, value); + if (pAxis == NULL || pAxis->params == NULL) + return MOTOR_AXIS_ERROR; + else + return motorParam->getDouble(pAxis->params, (paramIndex) function, value); } static int motorAxisSetCallback(AXIS_HDL pAxis, motorAxisCallbackFunc callback, void * param) { - if (pAxis == NULL || pAxis->params == NULL) - return MOTOR_AXIS_ERROR; - else - return motorParam->setCallback(pAxis->params, callback, param); + if (pAxis == NULL || pAxis->params == NULL) + return MOTOR_AXIS_ERROR; + else + return motorParam->setCallback(pAxis->params, callback, param); } static int motorAxisSetDouble(AXIS_HDL pAxis, motorAxisParam_t function, double value) { - asynStatus status = asynSuccess; - char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; - - if (pAxis == NULL || pAxis->pController == NULL) - return asynError; - - epicsMutexLock(pAxis->mutexId); - - switch (function) - { - case motorAxisPosition: - { - double offset = value * fabs(pAxis->stepSize); - sprintf(outputBuff, "POSOFFSET SET %s %.*f", pAxis->axisName, pAxis->maxDigits, offset); - status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); - if (inputBuff[0] != ASCII_ACK_CHAR) - status = asynError; - break; - } - case motorAxisEncoderRatio: - { - PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: A3200 does not support setting encoder ratio\n"); - break; - } - case motorAxisResolution: - { - /* we need to scale over a dozen other parameters if this changed in some cases, so the user should just use - * the Configuration Manager to change this setting to ensure that this is done correctly */ - PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: A3200 does not support setting motor resolution\n"); - break; - } - case motorAxisLowLimit: - { - PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: Driver does not set A3200's Low Limit\n"); - break; - } - case motorAxisHighLimit: - { - PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: Driver does not set A3200's High Limit\n"); - break; - } - case motorAxisPGain: - { - PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: A3200 does not support setting proportional gain\n"); - break; - } - case motorAxisIGain: - { - PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: A3200 does not support setting integral gain\n"); - break; - } - case motorAxisDGain: - { - PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: A3200 does not support setting derivative gain\n"); - break; - } - default: - PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: unknown function %d\n", function); - break; - } - if (status == asynSuccess) - { - motorParam->setDouble(pAxis->params, function, value); - motorParam->callCallback(pAxis->params); - } - epicsMutexUnlock(pAxis->mutexId); - - return status; + asynStatus status = asynSuccess; + char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; + + if (pAxis == NULL || pAxis->pController == NULL) + return asynError; + + epicsMutexLock(pAxis->mutexId); + + switch (function) + { + case motorAxisPosition: + { + double offset = value * fabs(pAxis->stepSize); + sprintf(outputBuff, "POSOFFSET SET %s %.*f", pAxis->axisName, pAxis->maxDigits, offset); + status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + if (inputBuff[0] != ASCII_ACK_CHAR) + status = asynError; + break; + } + case motorAxisEncoderRatio: + { + PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: A3200 does not support setting encoder ratio\n"); + break; + } + case motorAxisResolution: + { + /* we need to scale over a dozen other parameters if this changed in some cases, so the user should just use + * the Configuration Manager to change this setting to ensure that this is done correctly */ + PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: A3200 does not support setting motor resolution\n"); + break; + } + case motorAxisLowLimit: + { + PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: Driver does not set A3200's Low Limit\n"); + break; + } + case motorAxisHighLimit: + { + PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: Driver does not set A3200's High Limit\n"); + break; + } + case motorAxisPGain: + { + PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: A3200 does not support setting proportional gain\n"); + break; + } + case motorAxisIGain: + { + PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: A3200 does not support setting integral gain\n"); + break; + } + case motorAxisDGain: + { + PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: A3200 does not support setting derivative gain\n"); + break; + } + default: + PRINT(pAxis->logParam, TERROR, "motorAxisSetDouble: unknown function %d\n", function); + break; + } + if (status == asynSuccess) + { + motorParam->setDouble(pAxis->params, function, value); + motorParam->callCallback(pAxis->params); + } + epicsMutexUnlock(pAxis->mutexId); + + return status; } static int motorAxisSetInteger(AXIS_HDL pAxis, motorAxisParam_t function, int value) { - int ret_status = MOTOR_AXIS_ERROR; - char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; - - if (pAxis == NULL || pAxis->pController == NULL) - return MOTOR_AXIS_ERROR; - - epicsMutexLock(pAxis->mutexId); - - switch (function) - { - case motorAxisClosedLoop: - if (value == 0) - sprintf(outputBuff, "DISABLE %s", pAxis->axisName); - else - { - if(pAxis->lastFault) - { - sprintf(outputBuff, "FAULTACK %s", pAxis->axisName); - ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); - } - sprintf(outputBuff, "ENABLE %s", pAxis->axisName); - } - ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); - break; - default: - PRINT(pAxis->logParam, TERROR, "motorAxisSetInteger: unknown function %d\n", function); - break; - } - if (ret_status != MOTOR_AXIS_ERROR) - { - motorParam->setInteger(pAxis->params, function, value); - motorParam->callCallback(pAxis->params); - } - epicsMutexUnlock(pAxis->mutexId); - return ret_status; + int tasknum, taskNstate, taskN1state, ret_status = MOTOR_AXIS_ERROR; + char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; + + if (pAxis == NULL || pAxis->pController == NULL) + return MOTOR_AXIS_ERROR; + + tasknum = pAxis->pController->taskNumber; + + epicsMutexLock(pAxis->mutexId); + + switch (function) + { + case motorAxisClosedLoop: + sprintf(outputBuff, "~STATUS (%u, TaskState) (%u, TaskState)", tasknum, tasknum + 1); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + if (ret_status != asynSuccess || inputBuff[0] != ASCII_ACK_CHAR) + { + motorParam->setInteger(pAxis->params, motorAxisCommError, 1); + break; + } + + sscanf(&inputBuff[1], "%d %d", &taskNstate, &taskN1state); + if (taskNstate == TASKSTATE_Idle) + { + sprintf(outputBuff, "~INITQUEUE %u", tasknum); + sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + } + if (value == 0) + sprintf(outputBuff, "DISABLE %s", pAxis->axisName); + else + { + if (pAxis->lastFault) + { + if (pAxis->lastFault == 52 || pAxis->lastFault == 78) + { + sprintf(outputBuff, "~TASK %u", tasknum + 1); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + /* Prevent Task #3 from blocking during LINEAR commands. */ + ret_status = sendAndReceive(pAxis->pController, (char *) "WAIT MODE AUTO", inputBuff, sizeof(inputBuff)); + ret_status = sendAndReceive(pAxis->pController, (char *) "ACKNOWLEDGEALL", inputBuff, sizeof(inputBuff)); + sprintf(outputBuff, "~TASK %u", tasknum); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + sprintf(outputBuff, "~INITQUEUE"); + } + else + sprintf(outputBuff, "FAULTACK %s", pAxis->axisName); + + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + pAxis->lastFault = 0; /* Clear fault indicator. */ + motorParam->setInteger(pAxis->params, motorAxisProblem, 0); + } + sprintf(outputBuff, "ENABLE %s", pAxis->axisName); + } + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + /* Set indicator to force status update when Enable does not work. */ + motorParam->setInteger(pAxis->params, motorAxisPowerOn, value); + + /* Prevent Task #2 from blocking during LINEAR commands. */ + ret_status = sendAndReceive(pAxis->pController, (char *) "WAIT MODE AUTO", inputBuff, sizeof(inputBuff)); + + break; + + default: + PRINT(pAxis->logParam, TERROR, "motorAxisSetInteger: unknown function %d\n", function); + break; + } + if (ret_status != MOTOR_AXIS_ERROR) + { + motorParam->setInteger(pAxis->params, function, value); + motorParam->callCallback(pAxis->params); + } + epicsMutexUnlock(pAxis->mutexId); + return ret_status; } static int motorAxisMove(AXIS_HDL pAxis, double position, int relative, - double min_velocity, double max_velocity, double acceleration) + double min_velocity, double max_velocity, double acceleration) { - int ret_status; - char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; - const char *moveCommand; - bool posdir; - - if (pAxis == NULL || pAxis->pController == NULL) - return MOTOR_AXIS_ERROR; - - PRINT(pAxis->logParam, FLOW, "Set card %d, axis %s move to %f, min vel=%f, max_vel=%f, accel=%f\n", - pAxis->card, pAxis->axisName, position, min_velocity, max_velocity, acceleration); - - if (relative) - { - posdir = position >= 0.0; - moveCommand = "INCREMENTAL"; - } - else - { - posdir = position >= pAxis->currentCmdPos; - moveCommand = "ABSOLUTE"; - } - - ret_status = sendAndReceive(pAxis->pController, moveCommand, inputBuff, sizeof(inputBuff)); - if (ret_status) - return MOTOR_AXIS_ERROR; - - if (acceleration > 0) - { /* only use the acceleration if > 0 */ - sprintf(outputBuff, "RAMP RATE %.*f", pAxis->maxDigits, acceleration * fabs(pAxis->stepSize)); - ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); - } - - sprintf(outputBuff, "LINEAR %s %.*f F%.*f", pAxis->axisName, pAxis->maxDigits, position * fabs(pAxis->stepSize), - pAxis->maxDigits, max_velocity * fabs(pAxis->stepSize)); - - ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); - if (ret_status) - return MOTOR_AXIS_ERROR; - - if (epicsMutexLock(pAxis->mutexId) == epicsMutexLockOK) - { - motorParam->setInteger(pAxis->params, motorAxisDirection, (int) posdir); - /* Ensure that the motor record's next status update sees motorAxisDone = False. */ - motorParam->setInteger(pAxis->params, motorAxisDone, 0); - motorParam->callCallback(pAxis->params); - epicsMutexUnlock(pAxis->mutexId); - } - - /* Send a signal to the poller task which will make it do a poll, and switch to the moving poll rate */ - epicsEventSignal(pAxis->pController->pollEventId); - - return MOTOR_AXIS_OK; + int ret_status; + char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; + const char *moveCommand; + bool posdir; + + if (pAxis == NULL || pAxis->pController == NULL) + return MOTOR_AXIS_ERROR; + + PRINT(pAxis->logParam, FLOW, "Set card %d, axis %s move to %f, min vel=%f, max_vel=%f, accel=%f\n", + pAxis->card, pAxis->axisName, position, min_velocity, max_velocity, acceleration); + + if (relative) + posdir = position >= 0.0; + else + posdir = position >= pAxis->currentCmdPos; + + if (pAxis->pController->linear == 1) + { + if (relative) + moveCommand = "INCREMENTAL"; + else + moveCommand = "ABSOLUTE"; + ret_status = sendAndReceive(pAxis->pController, moveCommand, inputBuff, sizeof(inputBuff)); + if (ret_status) + return MOTOR_AXIS_ERROR; + } + else + { + if (relative) + moveCommand = "MOVEIINC"; + else + moveCommand = "MOVEABS"; + } + + if (acceleration > 0) + { /* only use the acceleration if > 0 */ + if (pAxis->pController->linear == 1) + sprintf(outputBuff, "RAMP RATE %.*f", pAxis->maxDigits, acceleration * fabs(pAxis->stepSize)); + else + sprintf(outputBuff, "RAMP RATE %s %.*f", pAxis->axisName, pAxis->maxDigits, acceleration * fabs(pAxis->stepSize)); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + } + + if (pAxis->pController->linear == 1) + sprintf(outputBuff, "LINEAR %s %.*f F%.*f", pAxis->axisName, pAxis->maxDigits, position * fabs(pAxis->stepSize), + pAxis->maxDigits, max_velocity * fabs(pAxis->stepSize)); + else + sprintf(outputBuff, "%s %s %.*f %.*f", moveCommand, pAxis->axisName, pAxis->maxDigits, position * fabs(pAxis->stepSize), + pAxis->maxDigits, max_velocity * fabs(pAxis->stepSize)); + + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + if (ret_status || inputBuff[0] != ASCII_ACK_CHAR) + { + if (inputBuff[0] == ASCII_FAULT_CHAR) + { + int taskerr; + + motorParam->setInteger(pAxis->params, motorAxisProblem, 1); /* Signal "Controller Error" to user. */ + sprintf(outputBuff, "~STATUS(%u, TaskErrorCode)", pAxis->pController->taskNumber); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + taskerr = atoi(&inputBuff[1]); + if (taskerr != 0) + pAxis->lastFault = taskerr; /* Indicate a Fault needs to be ACK'd. */ + } + return MOTOR_AXIS_ERROR; + } + + if (epicsMutexLock(pAxis->mutexId) == epicsMutexLockOK) + { + motorParam->setInteger(pAxis->params, motorAxisDirection, (int) posdir); + /* Ensure that the motor record's next status update sees motorAxisDone = False. */ + motorParam->setInteger(pAxis->params, motorAxisDone, 0); + motorParam->callCallback(pAxis->params); + epicsThreadSleep(0.010); /* Delay status update so controller has time to set MoveDone false. */ + epicsMutexUnlock(pAxis->mutexId); + } + + /* Send a signal to the poller task which will make it do a poll, and switch to the moving poll rate */ + epicsEventSignal(pAxis->pController->pollEventId); + + return MOTOR_AXIS_OK; } static int motorAxisHome(AXIS_HDL pAxis, double min_velocity, double max_velocity, double acceleration, int forwards) { - int ret_status; - char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; - epicsUInt32 hparam; - int axis; - - if (pAxis == NULL || pAxis->pController == NULL) - return MOTOR_AXIS_ERROR; - - axis = pAxis->axis; - - PRINT(pAxis->logParam, FLOW, "motorAxisHome: set card %d, axis %d to home, forwards = %d\n", - pAxis->card, axis, forwards); - - if (max_velocity > 0) - { - sprintf(outputBuff, "HomeSpeed.%s = %.*f", pAxis->axisName, pAxis->maxDigits, - max_velocity * fabs(pAxis->stepSize)); - ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); - } - - if (acceleration > 0) - { - sprintf(outputBuff, "HomeRampRate.%s = %.*f", pAxis->axisName, pAxis->maxDigits, - acceleration * fabs(pAxis->stepSize)); - ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); - } - hparam = pAxis->homeDirection; - hparam = forwards ? 0x00000001 : 0x0; - pAxis->homeDirection = hparam; - - sprintf(outputBuff, "HomeSetup.%s = %d", pAxis->axisName, hparam); - ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); - - sprintf(outputBuff, "HOME %s", pAxis->axisName); - ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); - - if (ret_status) - return(MOTOR_AXIS_ERROR); - if (epicsMutexLock(pAxis->mutexId) == epicsMutexLockOK) - { - motorParam->setInteger(pAxis->params, motorAxisDirection, forwards); - /* Ensure that the motor record's next status update sees motorAxisDone = False. */ - motorParam->setInteger(pAxis->params, motorAxisDone, 0); - motorParam->callCallback(pAxis->params); - epicsMutexUnlock(pAxis->mutexId); - } - - /* Send a signal to the poller task which will make it do a poll, and switch to the moving poll rate */ - epicsEventSignal(pAxis->pController->pollEventId); - - return MOTOR_AXIS_OK; + int ret_status; + char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; + epicsUInt32 hparam; + int axis, posdir; + + if (pAxis == NULL || pAxis->pController == NULL) + return MOTOR_AXIS_ERROR; + + axis = pAxis->axis; + + PRINT(pAxis->logParam, FLOW, "motorAxisHome: set card %d, axis %d to home, forwards = %d\n", + pAxis->card, axis, forwards); + + if (max_velocity > 0) + { + sprintf(outputBuff, "HomeSpeed.%s = %.*f", pAxis->axisName, pAxis->maxDigits, + max_velocity * fabs(pAxis->stepSize)); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + } + + if (acceleration > 0) + { + sprintf(outputBuff, "HomeRampRate.%s = %.*f", pAxis->axisName, pAxis->maxDigits, + acceleration * fabs(pAxis->stepSize)); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + } + + posdir = (forwards == (int) pAxis->reverseDirec); /* Adjust home direction for Reverse Direction paramter. */ + hparam = pAxis->homeDirection; + if (posdir == 1) + hparam |= 0x00000001; + else + hparam &= 0xFFFFFFFE; + pAxis->homeDirection = hparam; + + sprintf(outputBuff, "HomeSetup.%s = %d", pAxis->axisName, hparam); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + + sprintf(outputBuff, "HOME %s", pAxis->axisName); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + + if (ret_status) + return(MOTOR_AXIS_ERROR); + if (epicsMutexLock(pAxis->mutexId) == epicsMutexLockOK) + { + motorParam->setInteger(pAxis->params, motorAxisDirection, forwards); + /* Ensure that the motor record's next status update sees motorAxisDone = False. */ + motorParam->setInteger(pAxis->params, motorAxisDone, 0); + motorParam->callCallback(pAxis->params); + epicsMutexUnlock(pAxis->mutexId); + } + + /* Send a signal to the poller task which will make it do a poll, and switch to the moving poll rate */ + epicsEventSignal(pAxis->pController->pollEventId); + + return MOTOR_AXIS_OK; } static int motorAxisVelocityMove(AXIS_HDL pAxis, double min_velocity, double velocity, double acceleration) { - char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; - int ret_status; - - if (pAxis == NULL || pAxis->pController == NULL) - return MOTOR_AXIS_ERROR; - - sprintf(outputBuff, "AbortDecelRate.%s = %.*f", pAxis->axisName, pAxis->maxDigits, acceleration * fabs(pAxis->stepSize)); - ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); - sprintf(outputBuff, "RAMP RATE %s %.*f", pAxis->axisName, pAxis->maxDigits, acceleration * fabs(pAxis->stepSize)); - ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); - sprintf(outputBuff, "FREERUN %s %.*f", pAxis->axisName, pAxis->maxDigits, velocity * fabs(pAxis->stepSize)); - ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); - - if (epicsMutexLock(pAxis->mutexId) == epicsMutexLockOK) - { - motorParam->setInteger(pAxis->params, motorAxisDirection, (velocity > 0.0 ? 1 : 0)); - /* Ensure that the motor record's next status update sees motorAxisDone = False. */ - motorParam->setInteger(pAxis->params, motorAxisDone, 0); - motorParam->callCallback(pAxis->params); - epicsMutexUnlock(pAxis->mutexId); - } - - /* Send a signal to the poller task which will make it do a poll, and switch to the moving poll rate */ - epicsEventSignal(pAxis->pController->pollEventId); - - return ret_status; + char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; + int ret_status; + + if (pAxis == NULL || pAxis->pController == NULL) + return MOTOR_AXIS_ERROR; + + sprintf(outputBuff, "AbortDecelRate.%s = %.*f", pAxis->axisName, pAxis->maxDigits, acceleration * fabs(pAxis->stepSize)); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + sprintf(outputBuff, "RAMP RATE %s %.*f", pAxis->axisName, pAxis->maxDigits, acceleration * fabs(pAxis->stepSize)); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + sprintf(outputBuff, "FREERUN %s %.*f", pAxis->axisName, pAxis->maxDigits, velocity * fabs(pAxis->stepSize)); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + + if (epicsMutexLock(pAxis->mutexId) == epicsMutexLockOK) + { + motorParam->setInteger(pAxis->params, motorAxisDirection, (velocity > 0.0 ? 1 : 0)); + /* Ensure that the motor record's next status update sees motorAxisDone = False. */ + motorParam->setInteger(pAxis->params, motorAxisDone, 0); + motorParam->callCallback(pAxis->params); + epicsThreadSleep(0.010); /* Delay status update so controller has time to set MoveDone false. */ + epicsMutexUnlock(pAxis->mutexId); + } + + /* Send a signal to the poller task which will make it do a poll, and switch to the moving poll rate */ + epicsEventSignal(pAxis->pController->pollEventId); + + return ret_status; } static int motorAxisProfileMove(AXIS_HDL pAxis, int npoints, double positions[], double times[], int relative, int trigger) { - return MOTOR_AXIS_ERROR; + return MOTOR_AXIS_ERROR; } static int motorAxisTriggerProfile(AXIS_HDL pAxis) { - return MOTOR_AXIS_ERROR; + return MOTOR_AXIS_ERROR; } static int motorAxisStop(AXIS_HDL pAxis, double acceleration) { - int ret_status; - char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; + int tasknum, ret_status; + char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; + + if (pAxis == NULL || pAxis->pController == NULL) + return MOTOR_AXIS_ERROR; - if (pAxis == NULL || pAxis->pController == NULL) - return MOTOR_AXIS_ERROR; + tasknum = pAxis->pController->taskNumber; - PRINT(pAxis->logParam, FLOW, "Abort on card %d, axis %d\n", pAxis->card, pAxis->axis); + PRINT(pAxis->logParam, FLOW, "Abort on card %d, axis %d\n", pAxis->card, pAxis->axis); - /* we can't accurately determine which type of motion is occurring on the controller, - * so don't worry about the acceleration rate, just stop the motion on the axis */ - sprintf(outputBuff, "ABORT %s", pAxis->axisName); - ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); - return ret_status; + /* we can't accurately determine which type of motion is occurring on the controller, + * so don't worry about the acceleration rate, just stop the motion on the axis */ + sprintf(outputBuff, "~TASK %u", tasknum + 1); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + sprintf(outputBuff, "ABORT %s", pAxis->axisName); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + sprintf(outputBuff, "~TASK %u", tasknum); + ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + return ret_status; } static int motorAxisforceCallback(AXIS_HDL pAxis) { - if (pAxis == NULL || pAxis->pController == NULL) - return MOTOR_AXIS_ERROR; + if (pAxis == NULL || pAxis->pController == NULL) + return MOTOR_AXIS_ERROR; - PRINT(pAxis->logParam, FLOW, "motorAxisforceCallback: request card %d, axis %d status update\n", pAxis->card, pAxis->axis); + PRINT(pAxis->logParam, FLOW, "motorAxisforceCallback: request card %d, axis %d status update\n", pAxis->card, pAxis->axis); - /* Force a status update. */ - motorParam->forceCallback(pAxis->params); + /* Force a status update. */ + motorParam->forceCallback(pAxis->params); - /* Send a signal to the poller task which will make it do a status update */ - epicsEventSignal(pAxis->pController->pollEventId); - return MOTOR_AXIS_OK; + /* Send a signal to the poller task which will make it do a status update */ + epicsEventSignal(pAxis->pController->pollEventId); + return MOTOR_AXIS_OK; } static void A3200Poller(A3200Controller *pController) { - /* This is the task that polls the A3200 */ - double timeout; - AXIS_HDL pAxis; - int itera; - bool anyMoving; - char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; - const char* STATUS_FORMAT_STRING = "~STATUS (%s, AxisStatus) (%s, DriveStatus) (%s, AxisFault) (%s, ProgramPositionFeedback) (%s, ProgramPositionCommand) (%s, ProgramVelocityFeedback)"; - int status; - int axis_status, drive_status, axis_fault; - double pfbk, pcmd, vfbk; - bool move_active; - - timeout = pController->idlePollPeriod; - epicsEventSignal(pController->pollEventId); /* Force on poll at startup */ - - while (1) - { - if (timeout != 0.) - status = epicsEventWaitWithTimeout(pController->pollEventId, timeout); - else - status = epicsEventWait(pController->pollEventId); - - anyMoving = false; - - for (itera = 0; itera < pController->numAxes; itera++) - { - PARAMS params; - - pAxis = &pController->pAxis[itera]; - params = pAxis->params; - - if (!pAxis->mutexId) - break; - epicsMutexLock(pAxis->mutexId); - sprintf(outputBuff, STATUS_FORMAT_STRING, - pAxis->axisName, - pAxis->axisName, - pAxis->axisName, - pAxis->axisName, - pAxis->axisName, - pAxis->axisName); - - status = sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); - if (status != asynSuccess) - { - motorParam->setInteger(pAxis->params, motorAxisCommError, 1); - epicsMutexUnlock(pAxis->mutexId); - continue; - } - - if(inputBuff[0] != ASCII_ACK_CHAR) - { - motorParam->setInteger(pAxis->params, motorAxisCommError, 1); - epicsMutexUnlock(pAxis->mutexId); - continue; - } - - sscanf(&inputBuff[1], "%d %d %d %lf %lf %lf", &axis_status, &drive_status, &axis_fault, &pfbk, &pcmd, &vfbk); - - motorParam->setInteger(params, motorAxisCommError, 0); - - move_active = drive_status & DRIVESTATUS_MoveActive; - motorParam->setInteger(params, motorAxisDone, !move_active); - if (move_active) - anyMoving = true; - - motorParam->setInteger(pAxis->params, motorAxisPowerOn, (drive_status & DRIVESTATUS_Enabled) != 0); - motorParam->setInteger(pAxis->params, motorAxisHomeSignal, (axis_status & AXISSTATUS_Homed) != 0); - - if (pAxis->reverseDirec == false) - { - motorParam->setInteger(pAxis->params, motorAxisHighHardLimit, !((drive_status & DRIVESTATUS_CwEndOfTravelLimitInput) ^ pAxis->swconfig.Bits.CWEOTSWstate)); - motorParam->setInteger(pAxis->params, motorAxisLowHardLimit, !((drive_status & DRIVESTATUS_CcwEndOfTravelLimitInput) ^ pAxis->swconfig.Bits.CCWEOTSWstate)); - } - else - { - motorParam->setInteger(pAxis->params, motorAxisHighHardLimit, !((drive_status & DRIVESTATUS_CcwEndOfTravelLimitInput) ^ pAxis->swconfig.Bits.CCWEOTSWstate)); - motorParam->setInteger(pAxis->params, motorAxisLowHardLimit, !((drive_status & DRIVESTATUS_CwEndOfTravelLimitInput) ^ pAxis->swconfig.Bits.CWEOTSWstate)); - } - pAxis->axisStatus = axis_status; - - pfbk /= fabs(pAxis->stepSize); - motorParam->setDouble(pAxis->params, motorAxisEncoderPosn, pfbk); - - pcmd /= fabs(pAxis->stepSize); - motorParam->setDouble(pAxis->params, motorAxisPosition, pcmd); - pAxis->currentCmdPos = pcmd; - - PRINT(pAxis->logParam, IODRIVER, "A3200Poller: axis %s axisStatus=%x, position=%f\n", - pAxis->axisName, pAxis->axisStatus, pAxis->currentCmdPos); - - if(axis_fault && axis_fault != pAxis->lastFault) - { - PRINT(pAxis->logParam, TERROR, "A3200Poller: controller fault on axis=%s fault=0x%X\n", pAxis->axisName, axis_fault); - } - - pAxis->lastFault = axis_fault; - - vfbk /= fabs(pAxis->stepSize); - motorParam->setDouble(pAxis->params, motorAxisActualVel, vfbk); - - motorParam->callCallback(pAxis->params); - epicsMutexUnlock(pAxis->mutexId); - } /* Next axis */ - - timeout = anyMoving ? pController->movingPollPeriod : pController->idlePollPeriod; - } /* End while */ + /* This is the task that polls the A3200 */ + double timeout; + AXIS_HDL pAxis; + int itera; + bool anyMoving; + char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; + const char* STATUS_FORMAT_STRING = "~STATUS (%s, AxisStatus) (%s, DriveStatus) (%s, AxisFault) (%s, ProgramPositionFeedback) (%s, ProgramPositionCommand) (%s, ProgramVelocityFeedback)"; + int status; + int axis_status, drive_status, axis_fault; + double pfbk, pcmd, vfbk; + bool move_active; + + timeout = pController->idlePollPeriod; + epicsEventSignal(pController->pollEventId); /* Force on poll at startup */ + + while (1) + { + if (timeout != 0.) + status = epicsEventWaitWithTimeout(pController->pollEventId, timeout); + else + status = epicsEventWait(pController->pollEventId); + + anyMoving = false; + + for (itera = 0; itera < pController->numAxes; itera++) + { + PARAMS params; + + pAxis = &pController->pAxis[itera]; + params = pAxis->params; + + if (!pAxis->mutexId) + break; + epicsMutexLock(pAxis->mutexId); + sprintf(outputBuff, STATUS_FORMAT_STRING, + pAxis->axisName, + pAxis->axisName, + pAxis->axisName, + pAxis->axisName, + pAxis->axisName, + pAxis->axisName); + + status = sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + if (status != asynSuccess || inputBuff[0] != ASCII_ACK_CHAR) + { + motorParam->setInteger(pAxis->params, motorAxisCommError, 1); + epicsMutexUnlock(pAxis->mutexId); + continue; + } + + sscanf(&inputBuff[1], "%d %d %d %lf %lf %lf", &axis_status, &drive_status, &axis_fault, &pfbk, &pcmd, &vfbk); + + motorParam->setInteger(params, motorAxisCommError, 0); + + move_active = !(axis_status & AXISSTATUS_MoveDone); + motorParam->setInteger(params, motorAxisDone, !move_active); + if (move_active) + anyMoving = true; + + motorParam->setInteger(pAxis->params, motorAxisPowerOn, (drive_status & DRIVESTATUS_Enabled) != 0); + motorParam->setInteger(pAxis->params, motorAxisHomeSignal, (axis_status & AXISSTATUS_Homed) != 0); + + if ((axis_status & AXISSTATUS_NotVirtual) != 0) + { + if (pAxis->reverseDirec == false) + { + motorParam->setInteger(pAxis->params, motorAxisHighHardLimit, !((drive_status & DRIVESTATUS_CwEndOfTravelLimitInput) ^ pAxis->swconfig.Bits.CWEOTSWstate)); + motorParam->setInteger(pAxis->params, motorAxisLowHardLimit, !((drive_status & DRIVESTATUS_CcwEndOfTravelLimitInput) ^ pAxis->swconfig.Bits.CCWEOTSWstate)); + } + else + { + motorParam->setInteger(pAxis->params, motorAxisHighHardLimit, !((drive_status & DRIVESTATUS_CcwEndOfTravelLimitInput) ^ pAxis->swconfig.Bits.CCWEOTSWstate)); + motorParam->setInteger(pAxis->params, motorAxisLowHardLimit, !((drive_status & DRIVESTATUS_CwEndOfTravelLimitInput) ^ pAxis->swconfig.Bits.CWEOTSWstate)); + } + } + pAxis->axisStatus = axis_status; + + pfbk /= fabs(pAxis->stepSize); + motorParam->setDouble(pAxis->params, motorAxisEncoderPosn, pfbk); + + pcmd /= fabs(pAxis->stepSize); + motorParam->setDouble(pAxis->params, motorAxisPosition, pcmd); + pAxis->currentCmdPos = pcmd; + + PRINT(pAxis->logParam, IODRIVER, "A3200Poller: axis %s axisStatus=%x, position=%f\n", + pAxis->axisName, pAxis->axisStatus, pAxis->currentCmdPos); + + if (axis_fault && axis_fault != pAxis->lastFault) + { + PRINT(pAxis->logParam, TERROR, "A3200Poller: controller fault on axis=%s fault=0x%X\n", pAxis->axisName, axis_fault); + pAxis->lastFault = axis_fault; + } + + vfbk /= fabs(pAxis->stepSize); + motorParam->setDouble(pAxis->params, motorAxisActualVel, vfbk); + + motorParam->callCallback(pAxis->params); + epicsMutexUnlock(pAxis->mutexId); + } /* Next axis */ + + timeout = anyMoving ? pController->movingPollPeriod : pController->idlePollPeriod; + } /* End while */ } static int motorA3200LogMsg(void * param, const motorAxisLogMask_t mask, const char *pFormat, ...) { - va_list pvar; - int nchar; - - va_start(pvar, pFormat); - nchar = vfprintf(stdout, pFormat, pvar); - va_end (pvar); - printf("\n"); - return nchar; + va_list pvar; + int nchar; + + va_start(pvar, pFormat); + nchar = vfprintf(stdout, pFormat, pvar); + va_end(pvar); + printf("\n"); + return nchar; } int A3200AsynSetup(int num_controllers) /* number of A3200 controllers in system. */ { - - if (num_controllers < 1) - { - printf("A3200AsynSetup, num_controllers must be > 0\n"); - return MOTOR_AXIS_ERROR; - } - numA3200Controllers = num_controllers; - pA3200Controller = (A3200Controller *)calloc(numA3200Controllers, sizeof(A3200Controller)); - if(pA3200Controller == NULL) - { - printf("A3200AsynSetup, could not allocate memory\n"); - return MOTOR_AXIS_ERROR; - } - return MOTOR_AXIS_OK; + + if (num_controllers < 1) + { + printf("A3200AsynSetup, num_controllers must be > 0\n"); + return MOTOR_AXIS_ERROR; + } + numA3200Controllers = num_controllers; + pA3200Controller = (A3200Controller *)calloc(numA3200Controllers, sizeof(A3200Controller)); + if (pA3200Controller == NULL) + { + printf("A3200AsynSetup, could not allocate memory\n"); + return MOTOR_AXIS_ERROR; + } + return MOTOR_AXIS_OK; } int A3200AsynConfig(int card, /* Controller number */ - const char *portName, /* asyn port name of serial or GPIB port */ - int asynAddress, /* asyn subaddress for GPIB */ - int numAxes, /* The number of axes that the driver controls */ - int taskNumber, /* the task number to use for motion commands */ - int movingPollPeriod, /* Time to poll (msec) when an axis is in motion */ - int idlePollPeriod) /* Time to poll (msec) when an axis is idle. 0 for no polling */ - + const char *portName, /* asyn port name of serial or GPIB port */ + int asynAddress, /* asyn subaddress for GPIB */ + int numAxes, /* The number of axes that the driver controls */ + int movingPollPeriod, /* Time to poll (msec) when an axis is in motion */ + int idlePollPeriod, /* Time to poll (msec) when an axis is idle. 0 for no polling */ + int taskNumber, /* the task number to use for motion commands */ + int linear) /* Use linear (1) or single-axis (0) move commands. */ { - A3200Controller *pController; - char threadName[20]; - int axis, status, digits, retry = 0; - char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; - const char* GET_PARAM_FORMAT_STRING = "%s.%s"; - - if (numA3200Controllers < 1) - { - printf("A3200AsynConfig: no A3200 controllers allocated, call A3200 first\n"); - return MOTOR_AXIS_ERROR; - } - if ((card < 0) || (card >= numA3200Controllers)) - { - printf("A3200AsynConfig: card must in range 0 to %d\n", numA3200Controllers - 1); - return MOTOR_AXIS_ERROR; - } - - if(numAxes < 1 || numAxes > A3200_MAX_AXES) - { - printf("A3200AsynConfig: numAxes must be in the range of 1 to %u\n", A3200_MAX_AXES); - return MOTOR_AXIS_ERROR; - } - - pController = &pA3200Controller[card]; - - pController->numAxes = numAxes; - pController->taskNumber = taskNumber; - pController->movingPollPeriod = movingPollPeriod / 1000.; - pController->idlePollPeriod = idlePollPeriod / 1000.; - - pController->sendReceiveMutex = epicsMutexMustCreate(); - - status = pasynOctetSyncIO->connect(portName, asynAddress, &pController->pasynUser, NULL); - - if (status != asynSuccess) - { - printf("A3200AsynConfig: cannot connect to asyn port %s\n", portName); - return MOTOR_AXIS_ERROR; - } - - /* Set command End-of-string */ - pasynOctetSyncIO->setInputEos(pController->pasynUser, ASCII_EOS_STR, strlen(ASCII_EOS_STR)); - pasynOctetSyncIO->setOutputEos(pController->pasynUser, ASCII_EOS_STR, strlen(ASCII_EOS_STR)); - - pController->pAxis = (AXIS_HDL) calloc(numAxes, sizeof(motorAxis)); - if(pA3200Controller->pAxis == NULL) - { - printf("A3200AsynConfig, could not allocate memory\n"); - return MOTOR_AXIS_ERROR; - } - - retry = 0; - - do - { - sprintf(outputBuff, "~TASK %u", pController->taskNumber); - status = sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); - retry++; - } while(status != asynSuccess && retry < 3); - - if(status != asynSuccess) - return MOTOR_AXIS_ERROR; - - sendAndReceive(pController, "~STOPTASK", inputBuff, sizeof(inputBuff)); // reset the task - - /* Get axes info */ - for (axis = 0; axis < numAxes; axis++) - { - sprintf(outputBuff, "$strtask0 = GETPARMSTRING %d, PARAMETERID_AxisName", axis); - sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); - - sendAndReceive(pController, "~GETVARIABLE $strtask0", inputBuff, sizeof(inputBuff)); - if (inputBuff[0] == ASCII_ACK_CHAR) - { - AXIS_HDL pAxis = &pController->pAxis[axis]; - pAxis->pController = pController; - pAxis->card = card; - pAxis->axis = axis; - pAxis->mutexId = epicsMutexMustCreate(); - pAxis->params = motorParam->create(0, MOTOR_AXIS_NUM_PARAMS); - strncpy(pAxis->axisName, &inputBuff[1], sizeof(pAxis->axisName) - 1); - - sprintf(outputBuff, GET_PARAM_FORMAT_STRING, "PositionFeedbackType", pAxis->axisName); - sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); - if (inputBuff[0] == ASCII_ACK_CHAR && atoi(&inputBuff[1]) > 0) - { - pAxis->closedLoop = 1; - motorParam->setInteger(pAxis->params, motorAxisHasEncoder, 1); - } - - sprintf(outputBuff, GET_PARAM_FORMAT_STRING, "CountsPerUnit", pAxis->axisName); - sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); - if (inputBuff[0] == ASCII_ACK_CHAR) - pAxis->stepSize = 1 / atof(&inputBuff[1]); - else - pAxis->stepSize = 1; - digits = (int) -log10(fabs(pAxis->stepSize)) + 2; - pAxis->maxDigits = digits < 1 ? 1 : digits; - - sprintf(outputBuff, GET_PARAM_FORMAT_STRING, "HomeOffset", pAxis->axisName); - sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); - if (inputBuff[0] == ASCII_ACK_CHAR) - pAxis->homePreset = atof(&inputBuff[1]); - - sprintf(outputBuff, GET_PARAM_FORMAT_STRING, "HomeSetup", pAxis->axisName); - sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); - if (inputBuff[0] == ASCII_ACK_CHAR) - pAxis->homeDirection = atoi(&inputBuff[1]) & 0x1; - - sprintf(outputBuff, GET_PARAM_FORMAT_STRING, "EndOfTravelLimitSetup", pAxis->axisName); - sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); - if (inputBuff[0] == ASCII_ACK_CHAR) - pAxis->swconfig.All = atoi(&inputBuff[1]); - - /* Set RAMP MODE to RATE. */ - sprintf(outputBuff, "RAMP MODE RATE %s", pAxis->axisName); - sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); - - /* Get Reverse Direction indicator. */ - sprintf(outputBuff, GET_PARAM_FORMAT_STRING, "ReverseMotionDirection", pAxis->axisName); - if (inputBuff[0] == ASCII_ACK_CHAR) - pAxis->reverseDirec = (bool) atoi(&inputBuff[1]); - } - } - - sendAndReceive(pController, "~INITQUEUE", inputBuff, sizeof(inputBuff)); - - pController->pollEventId = epicsEventMustCreate(epicsEventEmpty); - - /* Create the poller thread for this controller */ - epicsSnprintf(threadName, sizeof(threadName), "A3200:%d", card); - epicsThreadCreate(threadName, epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), - (EPICSTHREADFUNC) A3200Poller, (void *) pController); - - return MOTOR_AXIS_OK; + A3200Controller *pController; + char threadName[20]; + int axis, status, digits, retry = 0; + char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; + const char* GET_PARAM_FORMAT_STRING = "%s.%s"; + + if (numA3200Controllers < 1) + { + printf("A3200AsynConfig: no A3200 controllers allocated, call A3200 first\n"); + return MOTOR_AXIS_ERROR; + } + if ((card < 0) || (card >= numA3200Controllers)) + { + printf("A3200AsynConfig: card must in range 0 to %d\n", numA3200Controllers - 1); + return MOTOR_AXIS_ERROR; + } + + if (numAxes < 1 || numAxes > A3200_MAX_AXES) + { + printf("A3200AsynConfig: numAxes must be in the range of 1 to %u\n", A3200_MAX_AXES); + return MOTOR_AXIS_ERROR; + } + + pController = &pA3200Controller[card]; + + pController->numAxes = numAxes; + pController->taskNumber = taskNumber; + pController->linear = linear; + pController->movingPollPeriod = movingPollPeriod / 1000.; + pController->idlePollPeriod = idlePollPeriod / 1000.; + + pController->sendReceiveMutex = epicsMutexMustCreate(); + + status = pasynOctetSyncIO->connect(portName, asynAddress, &pController->pasynUser, NULL); + + if (status != asynSuccess) + { + printf("A3200AsynConfig: cannot connect to asyn port %s\n", portName); + return MOTOR_AXIS_ERROR; + } + + /* Set command End-of-string */ + pasynOctetSyncIO->setInputEos(pController->pasynUser, ASCII_EOS_STR, strlen(ASCII_EOS_STR)); + pasynOctetSyncIO->setOutputEos(pController->pasynUser, ASCII_EOS_STR, strlen(ASCII_EOS_STR)); + + pController->pAxis = (AXIS_HDL) calloc(numAxes, sizeof(motorAxis)); + if (pA3200Controller->pAxis == NULL) + { + printf("A3200AsynConfig, could not allocate memory\n"); + return MOTOR_AXIS_ERROR; + } + + retry = 0; + + do + { + sprintf(outputBuff, "~TASK %u", pController->taskNumber); + status = sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + retry++; + } while(status != asynSuccess && retry < 3); + + if (status != asynSuccess) + return MOTOR_AXIS_ERROR; + + sendAndReceive(pController, "~STOPTASK", inputBuff, sizeof(inputBuff)); // reset the task + + /* Get axes info */ + for (axis = 0; axis < numAxes; axis++) + { + AXIS_HDL pAxis = &pController->pAxis[axis]; + pAxis->pController = pController; + pAxis->card = card; + pAxis->axis = axis; + pAxis->mutexId = epicsMutexMustCreate(); + pAxis->params = motorParam->create(0, MOTOR_AXIS_NUM_PARAMS); + + if (inputBuff[0] != ASCII_ACK_CHAR) + motorParam->setInteger(pAxis->params, motorAxisProblem, 1); /* Signal "Controller Error" to user. */ + else + { + sprintf(outputBuff, "$strtask0 = GETPARMSTRING %d, PARAMETERID_AxisName", axis); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + + sendAndReceive(pController, "~GETVARIABLE $strtask0", inputBuff, sizeof(inputBuff)); + + strncpy(pAxis->axisName, &inputBuff[1], sizeof(pAxis->axisName) - 1); + + sprintf(outputBuff, GET_PARAM_FORMAT_STRING, "PositionFeedbackType", pAxis->axisName); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + if (inputBuff[0] == ASCII_ACK_CHAR && atoi(&inputBuff[1]) > 0) + { + pAxis->closedLoop = 1; + motorParam->setInteger(pAxis->params, motorAxisHasEncoder, 1); + } + + sprintf(outputBuff, GET_PARAM_FORMAT_STRING, "CountsPerUnit", pAxis->axisName); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + if (inputBuff[0] == ASCII_ACK_CHAR) + pAxis->stepSize = 1 / atof(&inputBuff[1]); + else + pAxis->stepSize = 1; + digits = (int) -log10(fabs(pAxis->stepSize)) + 2; + pAxis->maxDigits = digits < 1 ? 1 : digits; + + sprintf(outputBuff, GET_PARAM_FORMAT_STRING, "HomeOffset", pAxis->axisName); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + if (inputBuff[0] == ASCII_ACK_CHAR) + pAxis->homePreset = atof(&inputBuff[1]); + + sprintf(outputBuff, GET_PARAM_FORMAT_STRING, "HomeSetup", pAxis->axisName); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + if (inputBuff[0] == ASCII_ACK_CHAR) + pAxis->homeDirection = atoi(&inputBuff[1]) & 0x1; + + sprintf(outputBuff, GET_PARAM_FORMAT_STRING, "EndOfTravelLimitSetup", pAxis->axisName); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + if (inputBuff[0] == ASCII_ACK_CHAR) + pAxis->swconfig.All = atoi(&inputBuff[1]); + + /* Set RAMP MODE to RATE. */ + sprintf(outputBuff, "RAMP MODE RATE %s", pAxis->axisName); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + + /* Get Reverse Direction indicator. */ + sprintf(outputBuff, GET_PARAM_FORMAT_STRING, "ReverseMotionDirection", pAxis->axisName); + if (inputBuff[0] == ASCII_ACK_CHAR) + pAxis->reverseDirec = (bool) atoi(&inputBuff[1]); + } + } + + if (inputBuff[0] != ASCII_ACK_CHAR) + return MOTOR_AXIS_ERROR; + + sendAndReceive(pController, "~INITQUEUE", inputBuff, sizeof(inputBuff)); + + /* Prevent Task #2 and #3 from blocking during LINEAR commands. */ + sendAndReceive(pController, (char *) "WAIT MODE AUTO", inputBuff, sizeof(inputBuff)); + sprintf(outputBuff, "~TASK %u", pController->taskNumber + 1); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + sendAndReceive(pController, (char *) "WAIT MODE AUTO", inputBuff, sizeof(inputBuff)); + sprintf(outputBuff, "~TASK %u", pController->taskNumber); + sendAndReceive(pController, outputBuff, inputBuff, sizeof(inputBuff)); + + pController->pollEventId = epicsEventMustCreate(epicsEventEmpty); + + /* Create the poller thread for this controller */ + epicsSnprintf(threadName, sizeof(threadName), "A3200:%d", card); + epicsThreadCreate(threadName, epicsThreadPriorityMedium, epicsThreadGetStackSize(epicsThreadStackMedium), + (EPICSTHREADFUNC) A3200Poller, (void *) pController); + + return MOTOR_AXIS_OK; } static asynStatus sendAndReceive(A3200Controller *pController, const char *outputBuff, char *inputBuff, size_t inputSize) { - size_t nWriteRequested; - size_t nWrite, nRead; - int eomReason; - asynStatus status; - AXIS_HDL pAxis; - - if (pController == NULL) - return asynError; - - pAxis = &pController->pAxis[0]; - nWriteRequested = strlen(outputBuff); - - /* sendAndReceive is intended only for "fast" read-write operations (such as getting parameter/status values), - * so we don't expect much latency on read/writes */ - epicsMutexLock(pController->sendReceiveMutex); - - status = pasynOctetSyncIO->writeRead(pController->pasynUser, outputBuff, nWriteRequested, - inputBuff, inputSize, TIMEOUT, &nWrite, &nRead, &eomReason); - - if (nWrite != nWriteRequested) - status = asynError; - else if (status == asynTimeout) - { - int retry = 1; - - while (retry <= 3 && status == asynTimeout) - { - PRINT(pAxis->logParam, TERROR, "%s:sendAndReceive: Retrying read, retry# = %d.\n", DRIVER_NAME, retry); - status = pasynOctetSyncIO->read(pController->pasynUser, inputBuff, inputSize, TIMEOUT, &nRead, &eomReason); - retry++; - } - if (retry > 3) - PRINT(pAxis->logParam, TERROR, - "%s:sendAndReceive: Retries exhausted on response to command = %s.\n", DRIVER_NAME, outputBuff); - else - PRINT(pAxis->logParam, TERROR, - "%s:sendAndReceive: Retry succeeded for command = %s with response = %s\n", DRIVER_NAME, outputBuff, inputBuff); - } - - if (status != asynSuccess) - asynPrint(pController->pasynUser, ASYN_TRACE_ERROR, - "%s:sendAndReceive writeRead error, output=%s status=%d, error=%s\n", DRIVER_NAME, - outputBuff, status, pController->pasynUser->errorMessage); - else - { - /* read until we have an ACK followed by a string (most likely will be the numeric value we're looking for) */ - while (status == asynSuccess && nRead > 1 && inputBuff[0] == ASCII_ACK_CHAR && inputBuff[1] == ASCII_EOS_CHAR) - status = pasynOctetSyncIO->read(pController->pasynUser, inputBuff, inputSize, TIMEOUT, &nRead, &eomReason); - if (status != asynSuccess) - asynPrint(pController->pasynUser, ASYN_TRACE_ERROR, - "%s:sendAndReceive error calling read, status=%d, error=%s\n", DRIVER_NAME, - status, pController->pasynUser->errorMessage); - } - epicsMutexUnlock(pController->sendReceiveMutex); - return status; + size_t nWriteRequested; + size_t nWrite, nRead; + int eomReason; + asynStatus status; + AXIS_HDL pAxis; + + if (pController == NULL) + return asynError; + + pAxis = &pController->pAxis[0]; + nWriteRequested = strlen(outputBuff); + + /* sendAndReceive is intended only for "fast" read-write operations (such as getting parameter/status values), + * so we don't expect much latency on read/writes */ + epicsMutexLock(pController->sendReceiveMutex); + + status = pasynOctetSyncIO->writeRead(pController->pasynUser, outputBuff, nWriteRequested, + inputBuff, inputSize, TIMEOUT, &nWrite, &nRead, &eomReason); + + if (nWrite != nWriteRequested) + status = asynError; + else if (status == asynTimeout) + { + int retry = 1; + + while (retry <= 3 && status == asynTimeout) + { + PRINT(pAxis->logParam, TERROR, "%s:sendAndReceive: Retrying read, retry# = %d.\n", DRIVER_NAME, retry); + status = pasynOctetSyncIO->read(pController->pasynUser, inputBuff, inputSize, TIMEOUT, &nRead, &eomReason); + retry++; + } + if (retry > 3) + PRINT(pAxis->logParam, TERROR, + "%s:sendAndReceive: Retries exhausted on response to command = %s.\n", DRIVER_NAME, outputBuff); + else + PRINT(pAxis->logParam, TERROR, + "%s:sendAndReceive: Retry succeeded for command = %s with response = %s\n", DRIVER_NAME, outputBuff, inputBuff); + } + + if (status != asynSuccess) + asynPrint(pController->pasynUser, ASYN_TRACE_ERROR, + "%s:sendAndReceive writeRead error, output=%s status=%d, error=%s\n", DRIVER_NAME, + outputBuff, status, pController->pasynUser->errorMessage); + else + { + /* read until we have an ACK followed by a string (most likely will be the numeric value we're looking for) */ + while (status == asynSuccess && nRead > 1 && inputBuff[0] == ASCII_ACK_CHAR && inputBuff[1] == ASCII_EOS_CHAR) + status = pasynOctetSyncIO->read(pController->pasynUser, inputBuff, inputSize, TIMEOUT, &nRead, &eomReason); + if (status != asynSuccess) + asynPrint(pController->pasynUser, ASYN_TRACE_ERROR, + "%s:sendAndReceive error calling read, status=%d, error=%s\n", DRIVER_NAME, + status, pController->pasynUser->errorMessage); + } + epicsMutexUnlock(pController->sendReceiveMutex); + return status; } diff --git a/motorApp/AerotechSrc/drvA3200Asyn.h b/motorApp/AerotechSrc/drvA3200Asyn.h index 4e87cb9..8d57ac1 100644 --- a/motorApp/AerotechSrc/drvA3200Asyn.h +++ b/motorApp/AerotechSrc/drvA3200Asyn.h @@ -2,10 +2,6 @@ FILENAME... drvA3200Asyn.h USAGE... This file contains Aerotech A3200 Asyn driver "include" information. -Version: $Revision: 17434 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2014-05-21 11:43:51 -0500 (Wed, 21 May 2014) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/AerotechSrc/drvA3200Asyn.h $ */ /* @@ -47,16 +43,16 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- extern "C" { #endif - int A3200AsynSetup(int numControllers); /* number of A3200 controllers in system. */ - - int A3200AsynConfig(int card, /* Controller number */ - const char *portName, /* asyn port name of serial or GPIB port */ - int asynAddress, /* asyn subaddress for GPIB */ - int numAxes, /* The number of axes that the driver controls */ - int taskNumber, /* The task number to use for motion commands */ - int movingPollPeriod, /* Time to poll (msec) when an axis is in motion */ - int idlePollPeriod); /* Time to poll (msec) when an axis is idle. 0 for no polling */ + int A3200AsynSetup(int numControllers); /* number of A3200 controllers in system. */ + int A3200AsynConfig(int card, /* Controller number */ + const char *portName, /* asyn port name of serial or GPIB port */ + int asynAddress, /* asyn subaddress for GPIB */ + int numAxes, /* The number of axes that the driver controls */ + int movingPollPeriod, /* Time to poll (msec) when an axis is in motion */ + int idlePollPeriod, /* Time to poll (msec) when an axis is idle. 0 for no polling */ + int taskNumber, /* the task number to use for motion commands */ + int linear); /* linear (1) or single-axis (0) move commands. */ #ifdef __cplusplus } #endif diff --git a/motorApp/AerotechSrc/drvEnsembleAsyn.cc b/motorApp/AerotechSrc/drvEnsembleAsyn.cc index d6c5620..92941bc 100644 --- a/motorApp/AerotechSrc/drvEnsembleAsyn.cc +++ b/motorApp/AerotechSrc/drvEnsembleAsyn.cc @@ -2,10 +2,6 @@ FILENAME... drvEnsembleAsyn.cc USAGE... Motor record asyn driver level support for Aerotech Ensemble. -Version: $Revision: 18150 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2014-11-24 11:47:32 -0600 (Mon, 24 Nov 2014) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/AerotechSrc/drvEnsembleAsyn.cc $ */ /* @@ -68,6 +64,11 @@ in file LICENSE that is included with this distribution. * .19 09-11-14 rls - sendAndReceive() diagnostic message added when controller returns NAK. * .20 11-24-14 rls - Moved "WAIT MODE NOWAIT" from EnsembleAsynConfig to motorAxisSetInteger * where torque is enabled/disabled. +* .21 10-14-15 rls - Use "ReverseDirec" parameter to set "HomeSetup" parameter. +* .22 05-29-18 rls - To avoid EPICS IOC reboots after parameter file changes, update +* CountsPerUnit everytime torque is enabled. +* .23 06-28-18 rls - If disabling torque due to a fault, clear motorAxisProblem so that +* user can Jog off limit switch. */ @@ -96,9 +97,13 @@ in file LICENSE that is included with this distribution. #include "paramLib.h" #include "drvEnsembleAsyn.h" -#include "ParameterId.h" #include "epicsExport.h" +/* NOTE: The following two files are copied from the Ensemble C library include files. +* If changing the driver to target a different version of the Ensemble, copy the following two files from that version's C library include files */ +#include "EnsembleCommonStructures.h" +#include "EnsembleParameterId.h" + motorAxisDrvSET_t motorEnsemble = { 14, @@ -209,9 +214,6 @@ static int numEnsembleControllers; /* Pointer to array of controller structures */ static EnsembleController *pEnsembleController=NULL; -#define MAX(a,b) ((a)>(b)? (a): (b)) -#define MIN(a,b) ((a)<(b)? (a): (b)) - static void motorAxisReportAxis(AXIS_HDL pAxis, int level) { if (level > 0) @@ -414,6 +416,7 @@ static int motorAxisSetInteger(AXIS_HDL pAxis, motorAxisParam_t function, int va int ret_status = MOTOR_AXIS_ERROR; int status, FaultStatus; char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; + static char getparamstr[] = "GETPARM(@%d, %d)"; if (pAxis == NULL || pAxis->pController == NULL) return (MOTOR_AXIS_ERROR); @@ -424,9 +427,24 @@ static int motorAxisSetInteger(AXIS_HDL pAxis, motorAxisParam_t function, int va { case motorAxisClosedLoop: if (value == 0) + { + int TravelLimitFaultMask = (1 << AXISFAULTBITS_CwEndOfTravelLimitFaultBit) | (1 << AXISFAULTBITS_CcwEndOfTravelLimitFaultBit); sprintf(outputBuff, "DISABLE @%d", pAxis->axis); + if ((pAxis->lastFault & TravelLimitFaultMask) != 0 ) /* If disabled due to a Travel Limit fault, clear motorAxisProblem. */ + motorParam->setInteger(pAxis->params, motorAxisProblem, 0); + } else { + sprintf(outputBuff, getparamstr, pAxis->axis, PARAMETERID_CountsPerUnit); + sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + if (inputBuff[0] == ASCII_ACK_CHAR) + { + double localstepsize; + localstepsize = 1 / atof(&inputBuff[1]); + if (localstepsize != pAxis->stepSize) + pAxis->stepSize = localstepsize; /* Update new stepsize. */ + } + sprintf(outputBuff, "AXISFAULT @%d", pAxis->axis); ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); @@ -439,6 +457,8 @@ static int motorAxisSetInteger(AXIS_HDL pAxis, motorAxisParam_t function, int va sprintf(outputBuff, "ENABLE @%d", pAxis->axis); } ret_status = sendAndReceive(pAxis->pController, outputBuff, inputBuff, sizeof(inputBuff)); + /* Set indicator to force status update when Enable does not work. */ + motorParam->setInteger(pAxis->params, motorAxisPowerOn, value); /* Prevent ASCII interpreter from blocking during MOVEABS/INC commands. */ ret_status = sendAndReceive(pAxis->pController, (char *) "WAIT MODE NOWAIT", inputBuff, sizeof(inputBuff)); @@ -531,7 +551,7 @@ static int motorAxisHome(AXIS_HDL pAxis, double min_velocity, double max_velocit int ret_status; char inputBuff[BUFFER_SIZE], outputBuff[BUFFER_SIZE]; epicsUInt32 hparam; - int axis; + int axis, posdir; if (pAxis == NULL || pAxis->pController == NULL) return (MOTOR_AXIS_ERROR); @@ -552,8 +572,9 @@ static int motorAxisHome(AXIS_HDL pAxis, double min_velocity, double max_velocit sprintf(outputBuff, "SETPARM @%d, %d, %.*f", axis, PARAMETERID_HomeRampRate, pAxis->maxDigits, acceleration * fabs(pAxis->stepSize)); /* HomeAccelDecelRate */ + posdir = (forwards == (int) pAxis->ReverseDirec); /* Adjust home direction for Reverse Direction paramter. */ hparam = pAxis->homeDirection; - if (forwards == 1) + if (posdir == 1) hparam |= 0x00000001; else hparam &= 0xFFFFFFFE; @@ -820,7 +841,7 @@ static void EnsemblePoller(EnsembleController *pController) } else { - double actvelocity = atof(&inputBuff[1]) * 1000.; + double actvelocity = atof(&inputBuff[1]) / fabs(pAxis->stepSize); motorParam->setDouble(pAxis->params, motorAxisActualVel, actvelocity); } motorParam->callCallback(pAxis->params); diff --git a/motorApp/AerotechSrc/drvEnsembleAsyn.h b/motorApp/AerotechSrc/drvEnsembleAsyn.h index 3c22301..f1fae64 100644 --- a/motorApp/AerotechSrc/drvEnsembleAsyn.h +++ b/motorApp/AerotechSrc/drvEnsembleAsyn.h @@ -2,10 +2,6 @@ FILENAME... drvEnsembleAsyn.h USAGE... This file contains Aerotech Ensemble Asyn driver "include" information. -Version: $Revision: 10834 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2010-04-29 12:04:39 -0500 (Thu, 29 Apr 2010) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/AerotechSrc/drvEnsembleAsyn.h $ */ /* diff --git a/motorApp/AerotechSrc/drvSoloist.cc b/motorApp/AerotechSrc/drvSoloist.cc index 87583da..dc0e0fd 100644 --- a/motorApp/AerotechSrc/drvSoloist.cc +++ b/motorApp/AerotechSrc/drvSoloist.cc @@ -2,10 +2,6 @@ * FILENAME... drvSoloist.cc * USAGE... Motor record driver level support for Aerotech Soloist. * -* Version: $Revision: 14155 $ -* Modified By: $Author: sluiter $ -* Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ -* HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/AerotechSrc/drvSoloist.cc $ */ /* @@ -47,6 +43,8 @@ #include #include #include +#include +#include #include "motor.h" #include "drvSoloist.h" #include "asynOctetSyncIO.h" @@ -220,7 +218,7 @@ static int set_status(int card, int signal) // get the axis status sprintf(buff, "AXISSTATUS()"); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); comm_status = recv_mess(card, buff, 1); if (comm_status > 0 && buff[0] == ASCII_ACK_CHAR) { @@ -273,7 +271,7 @@ static int set_status(int card, int signal) /* get the axis fault status */ sprintf(buff, "AXISFAULT()"); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); comm_status = recv_mess(card, buff, 1); axis_status = atoi(&buff[1]); status.Bits.RA_PLUS_LS = axis_status & CW_FAULT_BIT ? 1 : 0; @@ -287,7 +285,7 @@ static int set_status(int card, int signal) // get the position sprintf(buff, "PFBKPROG()"); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); recv_mess(card, buff, 1); if (buff[0] == ASCII_ACK_CHAR) { @@ -339,7 +337,7 @@ static int set_status(int card, int signal) if ((status.Bits.RA_DONE || ls_active) && nodeptr != 0 && nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -593,7 +591,7 @@ static int motor_init() // we only care if we get a response // so we don't need to send a valid command strcpy(buff, "NONE"); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); status = recv_mess(card_index, buff, 1); retry++; @@ -605,7 +603,7 @@ static int motor_init() brdptr->motor_in_motion = 0; // Read controller ID string strcpy(buff, "GETPARM(265)"); //UserString1 - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); if (buff[0] == ASCII_ACK_CHAR) { @@ -622,7 +620,7 @@ static int motor_init() { // Does this axis actually exist? sprintf(buff, "GETPARM(257)"); //AxisName - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); // We know the axis exists if we got an ACK response @@ -647,7 +645,7 @@ static int motor_init() // Determine if encoder present based on open/closed loop mode. sprintf(buff, "GETPARM(58)"); //CfgFbkPosType - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); if (buff[0] == ASCII_ACK_CHAR) { @@ -660,7 +658,7 @@ static int motor_init() // Determine if gains are supported based on the motor type. sprintf(buff, "GETPARM(33)"); //CfgMotType - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); if (buff[0] == ASCII_ACK_CHAR) { @@ -673,12 +671,12 @@ static int motor_init() // Stop all motors sprintf(buff, "ABORT"); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); // Determine drive resolution sprintf(buff, "GETPARM(3)"); //PosScaleFactor - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); if (buff[0] == ASCII_ACK_CHAR) { @@ -698,7 +696,7 @@ static int motor_init() // Save home preset position sprintf(buff, "GETPARM(108)"); //HomeOffset - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); if (buff[0] == ASCII_ACK_CHAR) { @@ -707,7 +705,7 @@ static int motor_init() // Determine low limit sprintf(buff, "GETPARM(47)"); //ThresholdSoftCCW - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); if (buff[0] == ASCII_ACK_CHAR) { @@ -716,7 +714,7 @@ static int motor_init() // Determine high limit sprintf(buff, "GETPARM(48)"); //ThresholdSoftCW - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); if (buff[0] == ASCII_ACK_CHAR) { @@ -725,7 +723,7 @@ static int motor_init() // Save the HomeDirection parameter sprintf(buff, "GETPARM(106)"); //HomeDirection - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); if (buff[0] == ASCII_ACK_CHAR) { diff --git a/motorApp/AerotechSrc/drvSoloist.h b/motorApp/AerotechSrc/drvSoloist.h index 8f1b829..ca7e686 100644 --- a/motorApp/AerotechSrc/drvSoloist.h +++ b/motorApp/AerotechSrc/drvSoloist.h @@ -2,10 +2,6 @@ FILENAME... drvSoloist.h USAGE... This file contains Aerotech Soloist driver "include" information. -Version: $Revision: 10834 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2010-04-29 12:04:39 -0500 (Thu, 29 Apr 2010) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/AerotechSrc/drvSoloist.h $ */ /* diff --git a/motorApp/AttocubeSrc/drvANC150Asyn.cc b/motorApp/AttocubeSrc/drvANC150Asyn.cc index ef35b7d..416b2ef 100644 --- a/motorApp/AttocubeSrc/drvANC150Asyn.cc +++ b/motorApp/AttocubeSrc/drvANC150Asyn.cc @@ -3,9 +3,6 @@ FILENAME... drvANC150Asyn.cc USAGE... asyn motor driver support for attocube systems AG ANC150 Piezo Step Controller. -Version: $Revision: 1.9 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2009-08-13 20:05:24 $ */ diff --git a/motorApp/Db/ANF2Aux.template b/motorApp/Db/ANF2Aux.template new file mode 100644 index 0000000..93a255d --- /dev/null +++ b/motorApp/Db/ANF2Aux.template @@ -0,0 +1,28 @@ +# Database for extra PVs for AMCI ANG1 controllers + +record(bo,"$(P)$(R)ResetErrors") { + field(DESC,"Reset Errors") + field(PINI, "0") + field(VAL,"0") + field(DTYP, "asynInt32") + field(OUT,"@asyn($(PORT),$(ADDR))ANF2_RESET_ERRORS") + field(ZNAM, "Done") + field(ONAM, "Reset") +} + +record(bo,"$(P)$(R)GetInfo") { + field(DESC,"Get Info") + field(PINI, "0") + field(VAL,"0") + field(DTYP, "asynInt32") + field(OUT,"@asyn($(PORT),$(ADDR))ANF2_GET_INFO") +} + +# Reconfig isn't yet implemented in a generally-useful way +#record(longout,"$(P)$(R)Reconfig") { +# field(DESC,"Reconfig") +# field(PINI, "0") +# field(VAL,"0") +# field(DTYP, "asynInt32") +# field(OUT,"@asyn($(PORT),$(ADDR))ANF2_RECONFIG") +#} diff --git a/motorApp/Db/EnsemblePSOFly.db b/motorApp/Db/EnsemblePSOFly.db index ed9b636..f88da38 100644 --- a/motorApp/Db/EnsemblePSOFly.db +++ b/motorApp/Db/EnsemblePSOFly.db @@ -30,8 +30,8 @@ record(ao, "$(P)$(Q)startPos") { record(calcout, "$(P)$(Q)startPosDial") { field(INPA, "$(P)$(Q)startPos CP") - field(INPB, "$(M).OFF") - field(INPC, "$(M).DIR") + field(INPB, "$(M).OFF CP") + field(INPC, "$(M).DIR CP") field(PREC, "5") field(CALC, "(a-b)*(c?-1:1)") } @@ -44,8 +44,8 @@ record(ao, "$(P)$(Q)endPos") { record(calcout, "$(P)$(Q)endPosDial") { field(INPA, "$(P)$(Q)endPos CP") - field(INPB, "$(M).OFF") - field(INPC, "$(M).DIR") + field(INPB, "$(M).OFF CP") + field(INPC, "$(M).DIR CP") field(PREC, "5") field(CALC, "(a-b)*(c?-1:1)") } @@ -227,7 +227,7 @@ record(scalcout, "$(P)$(Q)calcPulseTime0") { } record(scalcout, "$(P)$(Q)calcPulseTime") { field(INPE, "$(P)$(Q)pulseType") - field(AA, "PSOPULSE X TIME ") + field(AA, "PSOPULSE $(AXIS=X) TIME ") field(BB, "2,1 ") field(INCC, "$(P)$(Q)calcPulseTime0.SVAL PP") field(CALC, "AA+(e?cc:bb)") @@ -236,19 +236,19 @@ record(scalcout, "$(P)$(Q)calcPulseTime") { record(sseq, "$(P)$(Q)initPSO") { field(LNK2, "$(P)$(Q)cmdWriteRead.BOUT CA") - field(STR2, "PSOOUTPUT X CONTROL 1") + field(STR2, "PSOOUTPUT $(AXIS=X) CONTROL 1") field(LNK3, "$(P)$(Q)cmdWriteRead.BOUT CA") field(DOL3, "$(P)$(Q)calcPulseTime.SVAL PP") field(LNK4, "$(P)$(Q)cmdWriteRead.BOUT CA") - field(STR4, "PSOOUTPUT X PULSE WINDOW MASK ") + field(STR4, "PSOOUTPUT $(AXIS=X) PULSE WINDOW MASK ") field(LNK5, "$(P)$(Q)cmdWriteRead.BOUT CA") - field(STR5, "PSOTRACK X INPUT 3") + field(STR5, "PSOTRACK $(AXIS=X) INPUT 3") field(LNK6, "$(P)$(Q)pulseDstBld.PROC CA") field(LNK7, "$(P)$(Q)cmdWriteRead.BOUT CA") - field(STR7, "PSOWINDOW X 1 INPUT 3") + field(STR7, "PSOWINDOW $(AXIS=X) 1 INPUT 3") field(LNK8, "$(P)$(Q)pulseWndwBld.PROC CA") field(LNK1, "$(P)$(Q)cmdWriteRead.BOUT CA") - field(STR1, "PSOCONTROL X RESET") + field(STR1, "PSOCONTROL $(AXIS=X) RESET") field(WAIT1, "Wait") field(WAIT2, "Wait") field(WAIT3, "Wait") @@ -273,7 +273,7 @@ record(scalcout, "$(P)$(Q)pulseDstBld") { field(CALC, "$P(AA,A)") field(INPA, "$(P)$(Q)scanDelta.VAL") field(OUT, "$(P)$(Q)cmdWriteRead.BOUT PP") - field(AA, "PSODISTANCE X FIXED %f UNITS") + field(AA, "PSODISTANCE $(AXIS=X) FIXED %f UNITS") } # The PSO range command arguments are relative to the motor position at which @@ -301,7 +301,7 @@ record(scalcout, "$(P)$(Q)pulseWndwBld") { field(INPC, "$(P)$(Q)calcRangeOffset PP") field(INPD, "$(P)$(Q)scanControl NPP") field(INPE, "$(P)$(Q)scanDelta NPP") - field(AA, "PSOWINDOW X 1 RANGE %.6f,") + field(AA, "PSOWINDOW $(AXIS=X) 1 RANGE %.6f,") field(CALC, "$P(AA,min(A,B)-(d?0:C)-(a>b?e:0))") field(OUT, "$(P)$(Q)pulseWndwBlds.A NPP") field(FLNK, "$(P)$(Q)pulseWndwBld2") @@ -335,16 +335,16 @@ record(aSub, "$(P)$(Q)pulseWndwBlds") { } record(scalcout, "$(P)$(Q)armPSO") { - field(AA, "PSOCONTROL X ARM") + field(AA, "PSOCONTROL $(AXIS=X) ARM") field(CALC, "aa") field(OUT, "$(P)$(Q)cmdWriteRead.BOUT PP") } record(sseq, "$(P)$(Q)disablePSO") { field(LNK1, "$(P)$(Q)cmdWriteRead.BOUT CA") - field(STR1, "PSOWINDOW X 1 OFF") + field(STR1, "PSOWINDOW $(AXIS=X) 1 OFF") field(LNK2, "$(P)$(Q)cmdWriteRead.BOUT CA") - field(STR2, "PSOCONTROL X OFF") + field(STR2, "PSOCONTROL $(AXIS=X) OFF") field(WAIT1, "Wait") field(WAIT2, "Wait") } @@ -353,8 +353,8 @@ record(stringout, "$(P)$(Q)motorName") { field(VAL, "$(M)") } -# Provide records for the user to program -# prefly and postfly operations +# Provide blank records for the user to program custom prefly and postfly +# operations record(bo, "$(P)$(Q)scanControl") { field(ZNAM, "Standard") field(ONAM, "Custom") @@ -364,8 +364,10 @@ record(calcout, "$(P)$(Q)userCalc1") { field(CALC, "0") } record(calcout, "$(P)$(Q)userCalc2") { + field(DESC, "") field(PREC, "5") field(CALC, "0") + } record(sseq, "$(P)$(Q)userPreTaxi") { field(SDIS, "$(P)$(Q)scanControl") diff --git a/motorApp/Db/Makefile b/motorApp/Db/Makefile index f872ed3..2c53922 100644 --- a/motorApp/Db/Makefile +++ b/motorApp/Db/Makefile @@ -26,6 +26,7 @@ DB += XPSAuxBo.db DB += XPSAuxLi.db DB += XPSAuxLo.db DB += XPS_extra.db +DB += XPSPositionCompare.db DB += XPSTclScript.template DB += HXP_extra.db DB += HXP_coords.db @@ -44,6 +45,8 @@ DB += profileMoveControllerXPS.template DB += profileMoveAxisXPS.template DB += PI_Support.db PI_SupportCtrl.db DB += Phytron_motor.db Phytron_I1AM01.db Phytron_MCM01.db +DB += asyn_auto_power.db +DB += ScriptMotorReload.db #---------------------------------------------------- # Declare template files which do not show up in DB diff --git a/motorApp/Db/ScriptMotorReload.db b/motorApp/Db/ScriptMotorReload.db new file mode 100644 index 0000000..6390445 --- /dev/null +++ b/motorApp/Db/ScriptMotorReload.db @@ -0,0 +1,9 @@ +record(bo, "$(P)$(PORT):ScriptReload") +{ + field(DESC, "$(PORT) Script Reload") + field(DTYP, "asynInt32") + field(OUT, "@asyn($(PORT), 0, 0)RELOAD_SCRIPT") + + field(ZNAM, "Loaded") + field(ONAM, "Reload") +} diff --git a/motorApp/Db/XPSAuxAo.db b/motorApp/Db/XPSAuxAo.db index cca84fe..c9cf191 100644 --- a/motorApp/Db/XPSAuxAo.db +++ b/motorApp/Db/XPSAuxAo.db @@ -1,9 +1,23 @@ -grecord(ao,"$(P)$(R)") { - field(DTYP,"asynFloat64") - field(OUT,"@asyn($(PORT) $(CHAN))ANALOG_OUTPUT") - field(DRVL,"$(DRVL)") - field(LOPR,"$(LOPR)") - field(DRVH,"$(DRVH)") - field(HOPR,"$(HOPR)") - field(PREC,"$(PREC)") +record(ao,"$(P)$(R)") { + field(DTYP,"asynFloat64") + field(OUT,"@asyn($(PORT) $(CHAN))ANALOG_OUTPUT") + field(DRVL,"$(DRVL)") + field(LOPR,"$(LOPR)") + field(DRVH,"$(DRVH)") + field(HOPR,"$(HOPR)") + field(PREC,"$(PREC)") +} + +record(ao,"$(P)$(R)_tweakVal") { + field(PREC,"$(PREC)") +} + +record(transform,"$(P)$(R)_tweak") { + field(CLCE,"a?d-c:b?d+c:d") + field(INPC,"$(P)$(R)_tweakVal.VAL NPP MS") + field(INPD,"$(P)$(R).VAL NPP MS") + field(OUTE,"$(P)$(R).VAL PP MS") + field(OUTF,"$(P)$(R)_tweak.A NPP MS") + field(OUTG,"$(P)$(R)_tweak.B NPP MS") + field(PREC,"3") } diff --git a/motorApp/Db/XPSPositionCompare.db b/motorApp/Db/XPSPositionCompare.db new file mode 100644 index 0000000..1165838 --- /dev/null +++ b/motorApp/Db/XPSPositionCompare.db @@ -0,0 +1,131 @@ +# Database for PositionerPositionCompare functions in Newport XPS +# Mark Rivers +# March 10, 2015 + +record(mbbo,"$(P)$(R)PositionCompareMode") { + field(DTYP, "asynInt32") + field(OUT,"@asyn($(PORT),$(ADDR))XPS_POSITION_COMPARE_MODE") + field(ZRVL, "0") + field(ZRST, "Disable") + field(ONVL, "1") + field(ONST, "Position compare") + field(TWVL, "2") + field(TWST, "AquadB windowed") + field(THVL, "3") + field(THST, "AquadB always") +} + +record(mbbi,"$(P)$(R)PositionCompareMode_RBV") { + field(DTYP, "asynInt32") + field(INP,"@asyn($(PORT),$(ADDR))XPS_POSITION_COMPARE_MODE") + field(ZRVL, "0") + field(ZRST, "Disable") + field(ONVL, "1") + field(ONST, "Position compare") + field(TWVL, "2") + field(TWST, "AquadB windowed") + field(THVL, "3") + field(THST, "AquadB always") + field(SCAN, "I/O Intr") +} + +record(ao,"$(P)$(R)PositionCompareMinPosition") { + field(PINI, "YES") + field(PREC,"$(PREC)") + field(DTYP, "asynFloat64") + field(OUT,"@asyn($(PORT),$(ADDR))XPS_POSITION_COMPARE_MIN_POSITION") +} + +record(ai,"$(P)$(R)PositionCompareMinPosition_RBV") { + field(PREC,"$(PREC)") + field(DTYP, "asynFloat64") + field(INP,"@asyn($(PORT),$(ADDR))XPS_POSITION_COMPARE_MIN_POSITION") + field(SCAN, "I/O Intr") +} + +record(ao,"$(P)$(R)PositionCompareMaxPosition") { + field(PINI, "YES") + field(PREC,"$(PREC)") + field(DTYP, "asynFloat64") + field(OUT,"@asyn($(PORT),$(ADDR))XPS_POSITION_COMPARE_MAX_POSITION") +} + +record(ai,"$(P)$(R)PositionCompareMaxPosition_RBV") { + field(PREC,"$(PREC)") + field(DTYP, "asynFloat64") + field(INP,"@asyn($(PORT),$(ADDR))XPS_POSITION_COMPARE_MAX_POSITION") + field(SCAN, "I/O Intr") +} + +record(ao,"$(P)$(R)PositionCompareStepSize") { + field(PINI, "YES") + field(PREC,"$(PREC)") + field(DTYP, "asynFloat64") + field(OUT,"@asyn($(PORT),$(ADDR))XPS_POSITION_COMPARE_STEP_SIZE") +} + +record(ai,"$(P)$(R)PositionCompareStepSize_RBV") { + field(PREC,"$(PREC)") + field(DTYP, "asynFloat64") + field(INP,"@asyn($(PORT),$(ADDR))XPS_POSITION_COMPARE_STEP_SIZE") + field(SCAN, "I/O Intr") +} + +record(mbbo,"$(P)$(R)PositionComparePulseWidth") { + field(PINI, "YES") + field(DTYP, "asynInt32") + field(OUT,"@asyn($(PORT),$(ADDR))XPS_POSITION_COMPARE_PULSE_WIDTH") + field(ZRVL, "0") + field(ZRST, "0.2") + field(ONVL, "1") + field(ONST, "1.0") + field(TWVL, "2") + field(TWST, "2.5") + field(THVL, "3") + field(THST, "10.0") +} + +record(mbbi,"$(P)$(R)PositionComparePulseWidth_RBV") { + field(PINI, "YES") + field(DTYP, "asynInt32") + field(INP,"@asyn($(PORT),$(ADDR))XPS_POSITION_COMPARE_PULSE_WIDTH") + field(ZRVL, "0") + field(ZRST, "0.2") + field(ONVL, "1") + field(ONST, "1.0") + field(TWVL, "2") + field(TWST, "2.5") + field(THVL, "3") + field(THST, "10.0") + field(SCAN, "I/O Intr") +} + +record(mbbo,"$(P)$(R)PositionCompareSettlingTime") { + field(PINI, "YES") + field(DTYP, "asynInt32") + field(OUT,"@asyn($(PORT),$(ADDR))XPS_POSITION_COMPARE_SETTLING_TIME") + field(ZRVL, "0") + field(ZRST, "0.075") + field(ONVL, "1") + field(ONST, "1.0") + field(TWVL, "2") + field(TWST, "4.0") + field(THVL, "3") + field(THST, "12.0") +} + +record(mbbi,"$(P)$(R)PositionCompareSettlingTime_RBV") { + field(PINI, "YES") + field(DTYP, "asynInt32") + field(INP,"@asyn($(PORT),$(ADDR))XPS_POSITION_COMPARE_SETTLING_TIME") + field(ZRVL, "0") + field(ZRST, "0.075") + field(ONVL, "1") + field(ONST, "1.0") + field(TWVL, "2") + field(TWST, "4.0") + field(THVL, "3") + field(THST, "12.0") + field(SCAN, "I/O Intr") +} + diff --git a/motorApp/Db/XPSPositionCompare_settings.req b/motorApp/Db/XPSPositionCompare_settings.req new file mode 100644 index 0000000..b810b55 --- /dev/null +++ b/motorApp/Db/XPSPositionCompare_settings.req @@ -0,0 +1,6 @@ +$(P)$(R)PositionCompareMode +$(p)$(r)pOSITIONcompareMinPosition +$(P)$(R)PositionCompareMaxPosition +$(P)$(R)PositionCompareStepSize +$(P)$(R)PositionComparePulseWidth +$(P)$(R)PositionCompareSettlingTime diff --git a/motorApp/Db/asyn_auto_power.db b/motorApp/Db/asyn_auto_power.db new file mode 100644 index 0000000..c80875c --- /dev/null +++ b/motorApp/Db/asyn_auto_power.db @@ -0,0 +1,90 @@ + +############################################################ +# +# Template to provide records that enable automatic control +# of the amplifier power. This works with the Asyn model 3 +# based drivers. Amplifier power control is done via the +# setClosedLoop driver function (which also maps to the +# motor record CNEN field). +# +# Macros: +# P, M - motor name +# PORT - asyn port +# ADDR - asyn addr +# FRAC - holding current % (optional, default 0) +# +# Matt Pearson, ORNL +# March 2015 +# +############################################################ + +# /// +# /// Automatically control amplifier power. +# /// +record(bo, "$(P)$(M):AutoEnable") +{ + field(DESC, "Auto Power Control") + field(DTYP, "asynInt32") + field(OUT, "@asyn($(PORT),$(ADDR))MOTOR_POWER_AUTO_ONOFF") + field(VAL, "0") + field(PINI, "YES") + field(ZNAM, "Disabled") + field(ONAM, "Enabled") + info(autosaveFields, "VAL") +} + +# /// +# /// Delay the move after the amplifier has been +# /// automatically enabled. +# /// +record(ao, "$(P)$(M):AutoEnableDelay") +{ + field(DESC, "Delay after power on") + field(DTYP, "asynFloat64") + field(OUT, "@asyn($(PORT),$(ADDR))MOTOR_POWER_ON_DELAY") + field(VAL, "0") + field(PINI, "YES") + field(EGU, "s") + field(PREC, "1") + info(autosaveFields, "VAL") +} + +# /// +# /// Delay the end of move after the amplifier has been +# /// automatically disabled. +# /// This is independent of the motor record DLY +# /// field, but the delay will only start once the driver +# /// notified that the move is complete (which takes +# /// into account any controller specific post move delay). +# /// +record(ao, "$(P)$(M):AutoDisableDelay") +{ + field(DESC, "Delay after power off") + field(DTYP, "asynFloat64") + field(OUT, "@asyn($(PORT),$(ADDR))MOTOR_POWER_OFF_DELAY") + field(VAL, "0") + field(PINI, "YES") + field(EGU, "s") + field(PREC, "1") + info(autosaveFields, "VAL") +} + +# /// +# /// Instead of power off completely, set a holding current +# /// which is a fraction of the moving current. +# /// +# /// If this is non zero it needs to be handled in the +# /// controller specific driver setClosedLoop function. +# /// +record(longout, "$(P)$(M):PowerOffFraction") +{ + field(DESC, "Holding Current %") + field(DTYP, "asynInt32") + field(OUT, "@asyn($(PORT),$(ADDR))MOTOR_POWER_OFF_FRACTION") + field(VAL, "$(FRAC=0)") + field(PINI, "YES") + field(HOPR, "100") + field(LOPR, "0") + info(autosaveFields, "VAL") +} + diff --git a/motorApp/Db/asyn_motor.db b/motorApp/Db/asyn_motor.db index f481121..aeb0a43 100644 --- a/motorApp/Db/asyn_motor.db +++ b/motorApp/Db/asyn_motor.db @@ -52,6 +52,40 @@ record(calcout, "$(P)$(M)_twCh") { field(OUT, "$(P)$(M).TWV") } +# These records make the motor resolution, offset and direction available to the driver +# which is needed for profile moves and other applications + +# Motor direction for this axis +record(longout,"$(P)$(M)Direction") { + field(DESC, "$(M) direction") + field(DOL, "$(P)$(M).DIR CP MS") + field(OMSL, "closed_loop") + field(DTYP, "asynInt32") + field(OUT, "@asyn($(PORT),$(ADDR))MOTOR_REC_DIRECTION") +} + + +# Motor offset for this axis +record(ao,"$(P)$(M)Offset") { + field(DESC, "$(M) offset") + field(DOL, "$(P)$(M).OFF CP MS") + field(OMSL, "closed_loop") + field(DTYP, "asynFloat64") + field(OUT, "@asyn($(PORT),$(ADDR))MOTOR_REC_OFFSET") + field(PREC, "$(PREC)") +} + + +# Motor resolution for this axis +record(ao,"$(P)$(M)Resolution") { + field(DESC, "$(M) resolution") + field(DOL, "$(P)$(M).MRES CP MS") + field(OMSL, "closed_loop") + field(DTYP, "asynFloat64") + field(OUT, "@asyn($(PORT),$(ADDR))MOTOR_REC_RESOLUTION") + field(PREC, "$(PREC)") +} + #! Further lines contain data used by VisualDCT #! View(405,484,0.9) #! Record("$(P)$(M)",840,675,0,0,"$(P)$(M)") diff --git a/motorApp/Db/asyn_motor_settings.req b/motorApp/Db/asyn_motor_settings.req index 57a0d9b..c6ca182 100644 --- a/motorApp/Db/asyn_motor_settings.req +++ b/motorApp/Db/asyn_motor_settings.req @@ -1,8 +1,4 @@ # FILE... motor_settings.req -# Version: $Revision$ -# Modified By: $Author$ -# Last Modified: $Date$ -# HeadURL: $URL$ file basic_motor_settings.req P=$(P),M=$(M) $(P)$(M)_able.VAL diff --git a/motorApp/Db/basic_asyn_motor.db b/motorApp/Db/basic_asyn_motor.db index c114689..a185980 100644 --- a/motorApp/Db/basic_asyn_motor.db +++ b/motorApp/Db/basic_asyn_motor.db @@ -19,3 +19,37 @@ record(motor,"$(P)$(M)") field(TWV,"1") } +# These records make the motor resolution, offset and direction available to the driver +# which is needed for profile moves and other applications + +# Motor direction for this axis +record(longout,"$(P)$(M)Direction") { + field(DESC, "$(M) direction") + field(DOL, "$(P)$(M).DIR CP MS") + field(OMSL, "closed_loop") + field(DTYP, "asynInt32") + field(OUT, "@asyn($(PORT),$(ADDR))MOTOR_REC_DIRECTION") +} + + +# Motor offset for this axis +record(ao,"$(P)$(M)Offset") { + field(DESC, "$(M) offset") + field(DOL, "$(P)$(M).OFF CP MS") + field(OMSL, "closed_loop") + field(DTYP, "asynFloat64") + field(OUT, "@asyn($(PORT),$(ADDR))MOTOR_REC_OFFSET") + field(PREC, "$(PREC)") +} + + +# Motor resolution for this axis +record(ao,"$(P)$(M)Resolution") { + field(DESC, "$(M) resolution") + field(DOL, "$(P)$(M).MRES CP MS") + field(OMSL, "closed_loop") + field(DTYP, "asynFloat64") + field(OUT, "@asyn($(PORT),$(ADDR))MOTOR_REC_RESOLUTION") + field(PREC, "$(PREC)") +} + diff --git a/motorApp/Db/basic_motor_settings.req b/motorApp/Db/basic_motor_settings.req index 529046f..5b4a1aa 100644 --- a/motorApp/Db/basic_motor_settings.req +++ b/motorApp/Db/basic_motor_settings.req @@ -1,8 +1,4 @@ # FILE... basic_motor_settings.req -# Version: $Revision$ -# Modified By: $Author$ -# Last Modified: $Date$ -# HeadURL: $URL$ $(P)$(M).DIR $(P)$(M).DHLM @@ -19,6 +15,7 @@ $(P)$(M).BDST $(P)$(M).BVEL $(P)$(M).BACC $(P)$(M).RDBD +$(P)$(M).SPDB $(P)$(M).DESC $(P)$(M).EGU $(P)$(M).RTRY diff --git a/motorApp/Db/motor.db b/motorApp/Db/motor.db index 40df7fe..33ad212 100644 --- a/motorApp/Db/motor.db +++ b/motorApp/Db/motor.db @@ -43,7 +43,7 @@ record(calcout, "$(P)$(M)_vCh") { record(calcout, "$(P)$(M)_twCh") { field(DESC, "change TWV") - field(CALC, "min(max(a*b,c),d-e)") + field(CALC, "min(max(a*b,abs(c)),d-e)") field(INPB, "$(P)$(M).TWV") field(INPC, "$(P)$(M).MRES") field(INPD, "$(P)$(M).HLM") diff --git a/motorApp/Db/motor_settings.req b/motorApp/Db/motor_settings.req index 57a0d9b..c6ca182 100644 --- a/motorApp/Db/motor_settings.req +++ b/motorApp/Db/motor_settings.req @@ -1,8 +1,4 @@ # FILE... motor_settings.req -# Version: $Revision$ -# Modified By: $Author$ -# Last Modified: $Date$ -# HeadURL: $URL$ file basic_motor_settings.req P=$(P),M=$(M) $(P)$(M)_able.VAL diff --git a/motorApp/Db/profileMoveAxis.template b/motorApp/Db/profileMoveAxis.template index c0644e7..7dc34e1 100644 --- a/motorApp/Db/profileMoveAxis.template +++ b/motorApp/Db/profileMoveAxis.template @@ -67,36 +67,3 @@ record(waveform,"$(P)$(R)M$(M)FollowingErrors") { field(SCAN, "I/O Intr") } -# These records make the motor resolution, offset and direction available to the driver -# which is needed for profile moves - -# Motor direction for this axis -record(longout,"$(P)$(R)M$(M)Direction") { - field(DESC, "$(ADDR) direction") - field(DOL, "$(MOTOR).DIR CP MS") - field(OMSL, "closed_loop") - field(DTYP, "asynInt32") - field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))PROFILE_MOTOR_DIRECTION") -} - - -# Motor offset for this axis -record(ao,"$(P)$(R)M$(M)Offset") { - field(DESC, "$(ADDR) offset") - field(DOL, "$(MOTOR).OFF CP MS") - field(OMSL, "closed_loop") - field(DTYP, "asynFloat64") - field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))PROFILE_MOTOR_OFFSET") - field(PREC, "$(PREC)") -} - - -# Motor resolution for this axis -record(ao,"$(P)$(R)M$(M)Resolution") { - field(DESC, "$(ADDR) resolution") - field(DOL, "$(MOTOR).MRES CP MS") - field(OMSL, "closed_loop") - field(DTYP, "asynFloat64") - field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))PROFILE_MOTOR_RESOLUTION") - field(PREC, "$(PREC)") -} diff --git a/motorApp/Db/trajectoryScan.db b/motorApp/Db/trajectoryScan.db index f571f58..570fbcf 100644 --- a/motorApp/Db/trajectoryScan.db +++ b/motorApp/Db/trajectoryScan.db @@ -81,6 +81,10 @@ grecord(ao,"$(P)$(R)NewPulsePositions") { field(PREC, "3") } +grecord(longout,"$(P)$(R)NumPulsePositions") { + field(DESC,"Num pulse positions to load") +} + record(mbbo, "$(P)$(R)PulseDir") { field(DESC,"Both, Neg, or Pos") field(ZRVL, "0") diff --git a/motorApp/Db/trajectoryScan_settings.req b/motorApp/Db/trajectoryScan_settings.req index cca5183..2600d56 100644 --- a/motorApp/Db/trajectoryScan_settings.req +++ b/motorApp/Db/trajectoryScan_settings.req @@ -1,4 +1,4 @@ -$(P)$(R)Nelements +ed $(P)$(R)Nelements $(P)$(R)MoveMode $(P)$(R)Npulses $(P)$(R)StartPulses @@ -56,3 +56,4 @@ $(P)$(R)PulseLenUS $(P)$(R)PulseSrc $(P)$(R)PulseMode $(P)$(R)PulsePositions +$(P)$(R)NumPulsePositions diff --git a/motorApp/DeltaTauSrc/devPmac.cc b/motorApp/DeltaTauSrc/devPmac.cc index c5296bc..d159780 100644 --- a/motorApp/DeltaTauSrc/devPmac.cc +++ b/motorApp/DeltaTauSrc/devPmac.cc @@ -2,9 +2,6 @@ FILENAME... devPmac.cc USAGE... Device level support for Delta Tau PMAC. -Version: $Revision: 1.5 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-03-14 20:09:01 $ */ /* @@ -41,6 +38,7 @@ Last Modified: $Date: 2008-03-14 20:09:01 $ #include #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -52,7 +50,7 @@ extern int Pmac_num_cards; extern struct driver_table Pmac_access; /* ----------------Create the dsets for devOMS----------------- */ -static long Pmac_init(void *); +static long Pmac_init(int); static long Pmac_init_record(void *); static long Pmac_start_trans(struct motorRecord *); static RTN_STATUS Pmac_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -60,7 +58,7 @@ static RTN_STATUS Pmac_end_trans(struct motorRecord *); struct motor_dset devPmac = { - {8, NULL, Pmac_init, Pmac_init_record, NULL}, + {8, NULL, (DEVSUPFUN) Pmac_init, (DEVSUPFUN) Pmac_init_record, NULL}, motor_update_values, Pmac_start_trans, Pmac_build_trans, @@ -100,10 +98,8 @@ static msg_types Pmac_table[] = { static struct board_stat **Pmac_cards; static const char errmsg[] = {"\n\n!!!ERROR!!! - Oms driver uninitialized.\n"}; -static long Pmac_init(void *arg) +static long Pmac_init(int after) { - int after = (arg == 0) ? 0 : 1; - if (*(Pmac_access.init_indicator) == NO) { errlogSevPrintf(errlogMinor, "%s", errmsg); diff --git a/motorApp/DeltaTauSrc/drvPmac.cc b/motorApp/DeltaTauSrc/drvPmac.cc index 960f8b1..13a8851 100644 --- a/motorApp/DeltaTauSrc/drvPmac.cc +++ b/motorApp/DeltaTauSrc/drvPmac.cc @@ -2,9 +2,6 @@ FILENAME... drvPmac.cc USAGE... Driver level support for Delta Tau PMAC model. -Version: $Revision: 1.11 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2009-09-08 18:25:19 $ */ /* @@ -51,10 +48,12 @@ Last Modified: $Date: 2009-09-08 18:25:19 $ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -222,7 +221,7 @@ static int set_status(int card, int signal) status.Bits.EA_POSITION = (motorstat.word1.Bits.amp_enabled == YES) ? 1 : 0; sprintf(outbuf, "M%.2d61", (signal + 1)); // Get Commanded Position. - send_mess(card, outbuf, (char) NULL); + send_mess(card, outbuf, (char*) NULL); recv_mess(card, buff, 1); motorData = atof(buff); @@ -272,7 +271,7 @@ static int set_status(int card, int signal) status.Bits.EA_HOME = 0; sprintf(outbuf, "M%.2d62", (signal + 1)); - send_mess(card, outbuf, (char) NULL); // Get Actual Position. + send_mess(card, outbuf, (char*) NULL); // Get Actual Position. recv_mess(card, buff, 1); motorData = atof(buff); motor_info->encoder_position = (int32_t) motorData; @@ -295,7 +294,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -588,7 +587,7 @@ static int motorIsrEnable(int card) status = pdevLibVirtualOS->pDevConnectInterruptVME( PmacInterruptVector + card, -#if LT_EPICSBASE(3,14,8) +#if LT_EPICSBASE(3,14,8,0) (void (*)()) motorIsr, #else (void (*)(void *)) motorIsr, @@ -836,10 +835,10 @@ static int motor_init() count = pmotor->response[0]; } - send_mess(card_index, "TYPE", (char) NULL); + send_mess(card_index, "TYPE", (char*) NULL); recv_mess(card_index, (char *) pmotorState->ident, 1); - send_mess(card_index, "VERSION", (char) NULL); + send_mess(card_index, "VERSION", (char*) NULL); recv_mess(card_index, axis_pos, 1); strcat((char *) &pmotorState->ident, ", "); strcat((char *) &pmotorState->ident, axis_pos); @@ -852,7 +851,7 @@ static int motor_init() char outbuf[10]; sprintf(outbuf, "I%.2d00", (total_axis + 1)); - send_mess(card_index, outbuf, (char) NULL); + send_mess(card_index, outbuf, (char*) NULL); recv_mess(card_index, axis_pos, 1); if (strcmp(axis_pos, "0") == 0) errind = true; @@ -863,12 +862,12 @@ static int motor_init() // Set Ixx20=1 and Ixx21=0; control acceleration via Ixx19. sprintf(outbuf, "I%.2d20=1", (total_axis + 1)); - send_mess(card_index, outbuf, (char) NULL); + send_mess(card_index, outbuf, (char*) NULL); sprintf(outbuf, "I%.2d21=0", (total_axis + 1)); - send_mess(card_index, outbuf, (char) NULL); + send_mess(card_index, outbuf, (char*) NULL); sprintf(outbuf, "I%.2d08", (total_axis + 1)); - send_mess(card_index, outbuf, (char) NULL); + send_mess(card_index, outbuf, (char*) NULL); recv_mess(card_index, axis_pos, 1); cntrl->pos_scaleFac[total_axis] = atof(axis_pos) * 32.0; } diff --git a/motorApp/DeltaTauSrc/drvPmac.h b/motorApp/DeltaTauSrc/drvPmac.h index c314d7d..9ddb6ef 100644 --- a/motorApp/DeltaTauSrc/drvPmac.h +++ b/motorApp/DeltaTauSrc/drvPmac.h @@ -2,9 +2,6 @@ FILENAME... drvPmac.h USAGE... This file contains Delta Tau PMAC driver "include" information. -Version: $Revision: 1.3 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2009-05-01 18:26:29 $ */ /* diff --git a/motorApp/FaulhaberSrc/devMCDC2805.cc b/motorApp/FaulhaberSrc/devMCDC2805.cc index 7ad38cc..ffce31d 100644 --- a/motorApp/FaulhaberSrc/devMCDC2805.cc +++ b/motorApp/FaulhaberSrc/devMCDC2805.cc @@ -3,9 +3,6 @@ FILENAME... devMCDC2805.cc USAGE... Motor record device level support for Intelligent Motion Systems, Inc. MCDC2805 series of controllers. -Version: $Revision: 1.3 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-03-14 20:09:24 $ */ /* @@ -39,6 +36,7 @@ Last Modified: $Date: 2008-03-14 20:09:24 $ */ #include +#include #include "motorRecord.h" #include "motor.h" @@ -52,7 +50,7 @@ extern struct driver_table MCDC2805_access; /* ----------------Create the dsets for devMCDC2805----------------- */ STATIC struct driver_table *drvtabptr; -STATIC long MCDC2805_init(void *); +STATIC long MCDC2805_init(int); STATIC long MCDC2805_init_record(void *); STATIC long MCDC2805_start_trans(struct motorRecord *); STATIC RTN_STATUS MCDC2805_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -106,12 +104,11 @@ static struct board_stat **MCDC2805_cards; /* initialize device support for MCDC2805 stepper motor */ -STATIC long MCDC2805_init(void *arg) +STATIC long MCDC2805_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &MCDC2805_access; (drvtabptr->init)(); diff --git a/motorApp/FaulhaberSrc/drvMCDC2805.cc b/motorApp/FaulhaberSrc/drvMCDC2805.cc index 00aeb34..63876c1 100644 --- a/motorApp/FaulhaberSrc/drvMCDC2805.cc +++ b/motorApp/FaulhaberSrc/drvMCDC2805.cc @@ -2,11 +2,6 @@ FILENAME... drvMCDC2805.cc USAGE... Motor record driver level support for Faulhaber MCDC2805 -Version: $Revision: 14155 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/FaulhaberSrc/drvMCDC2805.cc $ -Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ */ /* @@ -52,6 +47,7 @@ DESIGN LIMITATIONS... #include #include #include +#include #include "motor.h" #include "drvMCDC2805.h" #include "asynOctetSyncIO.h" diff --git a/motorApp/FaulhaberSrc/drvMCDC2805.h b/motorApp/FaulhaberSrc/drvMCDC2805.h index a24dbef..9dae153 100644 --- a/motorApp/FaulhaberSrc/drvMCDC2805.h +++ b/motorApp/FaulhaberSrc/drvMCDC2805.h @@ -2,9 +2,6 @@ FILENAME... drvMCDC2805.h USAGE... This file contains driver "include" information for the Faulhaber MCDC 2805 controller. -Version: $Revision: 1.2 $ -Modified By: $Author: rivers $ -Last Modified: $Date: 2005-11-04 23:05:35 $ */ /* diff --git a/motorApp/HytecSrc/HytecMotorDriver.cpp b/motorApp/HytecSrc/HytecMotorDriver.cpp index a66da36..794d0ca 100644 --- a/motorApp/HytecSrc/HytecMotorDriver.cpp +++ b/motorApp/HytecSrc/HytecMotorDriver.cpp @@ -1067,6 +1067,9 @@ extern "C" int Hytec8601Configure(const char *portName, return(asynSuccess); } +extern "C" +{ + static const iocshArg Hy8601ConfigArg0 = {"portName", iocshArgString}; static const iocshArg Hy8601ConfigArg1 = {"numAxes", iocshArgInt}; static const iocshArg Hy8601ConfigArg2 = {"movingPollPeriod", iocshArgInt}; @@ -1110,4 +1113,4 @@ static void Hytec8601Register(void) epicsExportRegistrar(Hytec8601Register); - +} diff --git a/motorApp/HytecSrc/README_Hy8601Asyn b/motorApp/HytecSrc/README_Hy8601Asyn index e2c3962..47445d6 100644 --- a/motorApp/HytecSrc/README_Hy8601Asyn +++ b/motorApp/HytecSrc/README_Hy8601Asyn @@ -37,53 +37,53 @@ Support modules Hytec 8002/8003/8004 carrier card configuration =============================================== - -This board is a 6U VME64x carrier card. It provides four single size IP slots and -is configurable for many parameters. It supports interrupt level from 0 to 7. Any -IP cards can be enabled/disabled interrupt. The clock can be set to either 8MHz or -32MHz. For IPAC Memory space if required, the base address can be defined automatically -by geographical addressing when VME64x crate is used. For other type of crates, -the base address can be set by configuring a series of jumpers on the board or by -passing parameter to the memory offset register in the ipacAddCarrier call. - -The IPAC Carrier Driver for this board is found in the file drvHy8002.c which -implements two commands ipacAddHy8002 and Hy8002CarrierInfo. The ipacAddHy8002 -command is used to add a Hytec 8002/8003 board to the system. The Hy8002CarrierInfo -reports hardware information for a specified board or all boards in the system if -the parameter passed down is 0xFFFF. These commands are registered by the registrar -routine Hy8002Registrar to add them to the iocsh and link the driver into a final -IOC executable, for which it must be listed in the IOC's .dbd file thus: - - registrar(Hy8002Registrar) - - + +This board is a 6U VME64x carrier card. It provides four single size IP slots and +is configurable for many parameters. It supports interrupt level from 0 to 7. Any +IP cards can be enabled/disabled interrupt. The clock can be set to either 8MHz or +32MHz. For IPAC Memory space if required, the base address can be defined automatically +by geographical addressing when VME64x crate is used. For other type of crates, +the base address can be set by configuring a series of jumpers on the board or by +passing parameter to the memory offset register in the ipacAddCarrier call. + +The IPAC Carrier Driver for this board is found in the file drvHy8002.c which +implements two commands ipacAddHy8002 and Hy8002CarrierInfo. The ipacAddHy8002 +command is used to add a Hytec 8002/8003 board to the system. The Hy8002CarrierInfo +reports hardware information for a specified board or all boards in the system if +the parameter passed down is 0xFFFF. These commands are registered by the registrar +routine Hy8002Registrar to add them to the iocsh and link the driver into a final +IOC executable, for which it must be listed in the IOC's .dbd file thus: + + registrar(Hy8002Registrar) + + 1). Configuration Command and Parameter --------------------------------------- - -- int ipacAddHYy8002(const char *cardParams); - -The parameter string should comprise two (2) to six (6) parameters which are comma -separated. The first two are mandate and have to be separated only by one comma. +-------------------------------------- + +- int ipacAddHYy8002(const char *cardParams); + +The parameter string should comprise two (2) to six (6) parameters which are comma +separated. The first two are mandate and have to be separated only by one comma. The others are key/value pairs and are optional as per the conditions of the operating -system used. The format is defined as - -s,i,IPMEM=d,IPCLCK=d,ROAK=d,MEMOFFS=d - -where d is a decimal integer number. +system used. The format is defined as + +s,i,IPMEM=d,IPCLCK=d,ROAK=d,MEMOFFS=d + +where d is a decimal integer number. s defines the VME slot number of the carrier card. Valid number is 2 ~ 21. this number MUST be the same as the VME slot number where the carrier - card is plugged in. -i defines the interrupt level. Valid number is 0 ~ 7. -IPMEM=d defines the maximum memory size of the IP module. The valid values are 1, 2, + card is plugged in. +i defines the interrupt level. Valid number is 0 ~ 7. +IPMEM=d defines the maximum memory size of the IP module. The valid values are 1, 2, 4 or 8 that represent 1MB, 2MB, 4MB or 8MB respectively. Default is 1. For majority Hytec ADCs, DACs such as 8401, 8414, 8417, 8402 and 8415 etc, they all have 2MB on board. The user can choose to use either 1MB or 2MB. None of - the Hytec IPs has more than 2MB on board memory. Other vendors might have. -IPCLCK=d defines the clock that its value has to be either 8 for 8MHz or 32 for - 32Mhz. Default is 8. -ROAK=d if d =1, it defines carrier card to release the interrupt upon the - acknowledgment. If d=0, the interrupt is released by user interrupt - service routine. Default is 0. + the Hytec IPs has more than 2MB on board memory. Other vendors might have. +IPCLCK=d defines the clock that its value has to be either 8 for 8MHz or 32 for + 32Mhz. Default is 8. +ROAK=d if d =1, it defines carrier card to release the interrupt upon the + acknowledgment. If d=0, the interrupt is released by user interrupt + service routine. Default is 0. MEMOFFS=d this parameter defines the A32 memory access base address. "d" is a decimal number that represents the offset (the upper WORD) of the A32 base address. It is needed when any of the two statements below is true: @@ -150,15 +150,15 @@ the VME slot number in the calculation just makes better logical sense and fits natual of human being's thinking. Some examples are shown below. Let's assume IPMEM=1 (the default setting), this gives 4MB memory space for a 8002 -carrier so starting address line is A22. The remaining must be 0. - +carrier so starting address line is A22. The remaining must be 0. + MEMOFFS BIT 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 A31 A30 A29 A28 A27 A26 A25 A24 A23 A22 0 0 0 0 0 0 For a carrier in VME slot 2, we can define its A32 base address as 0x00400000, plus VME_A32_MSTR_LOCAL. For VME slot 3, it could be 0x00800000 plus VME_A32_MSTR_LOCAL -and for VME slot 4, it could be 0x00C00000 plus VME_A32_MSTR_LOCAL and so forth. - +and for VME slot 4, it could be 0x00C00000 plus VME_A32_MSTR_LOCAL and so forth. + Assuming VME_A32_MSTR_LOCAL is 0x20000000, then for VME slot 4, the calculated base address should be 0x00C00000 + 0x20000000 = 0x20C000000. Hence the MEMOFFS = 8384 (decimal, i.e. 0x20C0). For slot 5, the derived base address could be 0x01000000 + @@ -180,45 +180,45 @@ base address should be 0x01800000 + 0x20000000 = 0x218000000. Hence the MEMOFFS (decimal, i.e. 0x2180). For slot 5, the derived base address could be 0x02000000 + 0x20000000 = 0x22000000. Hence the MEMOFFS = 8704 (decimal, i.e. 0x2200) and so forth. - - -- int Hy8002CarrierInfo(int carrier); - -where 'carrier' is the registered carrier number in the system. If it is specified, -this function prints out the specified carrier hardware information. If carrier = 0xFFFF, -then all carriers' hardware information will be printed out. - - + + +- int Hy8002CarrierInfo(int carrier); + +where 'carrier' is the registered carrier number in the system. If it is specified, +this function prints out the specified carrier hardware information. If carrier = 0xFFFF, +then all carriers' hardware information will be printed out. + + 2). Configuration Examples -------------------------- - -ipacAddHy8002("3,2") - -This indicates that the carrier is in slot 3 and the interrupt level is set to 2. -IP memory uses default 1MB. Clock uses default 8MHz. RORA as default. use geographical -addressing etc. - -ipacAddHy8002("5,4,IPMEM=1,IPCLCK=8,ROAK=1,MEMOFFS=256 ") - -Here the slot is 5, interrupt level is 4. IP memory size is 1MB, clock uses 8MHz. -Use ROAK but not using geographic addressing. The memory offset is 256 which means its -base address is 0x01000000 assuming the VME_A32_MSTR_LOCAL is set to 0x00000000. - +------------------------- + +ipacAddHy8002("3,2") + +This indicates that the carrier is in slot 3 and the interrupt level is set to 2. +IP memory uses default 1MB. Clock uses default 8MHz. RORA as default. use geographical +addressing etc. + +ipacAddHy8002("5,4,IPMEM=1,IPCLCK=8,ROAK=1,MEMOFFS=256 ") + +Here the slot is 5, interrupt level is 4. IP memory size is 1MB, clock uses 8MHz. +Use ROAK but not using geographic addressing. The memory offset is 256 which means its +base address is 0x01000000 assuming the VME_A32_MSTR_LOCAL is set to 0x00000000. + 3). Interrupt Commands Supported -------------------------------- - -The interrupt level can be set by the second parameter of the ipacAddHy8002 routine. -Individual IP module can be set to generate interrupt or not. The commands supported -for ipmIrqCmd are illustrated below. - -cmd Value Returned -ipac_irqGetLevel Carrier interrupt level (0 ~ 7) -ipac_irqEnable 0 = OK -ipac_irqDisable 0 = OK -ipac_irqPoll >0 if the interrupt line is active, else 0 -(other commands) S_IPAC_notImplemented - - +------------------------------- + +The interrupt level can be set by the second parameter of the ipacAddHy8002 routine. +Individual IP module can be set to generate interrupt or not. The commands supported +for ipmIrqCmd are illustrated below. + +cmd Value Returned +ipac_irqGetLevel Carrier interrupt level (0 ~ 7) +ipac_irqEnable 0 = OK +ipac_irqDisable 0 = OK +ipac_irqPoll >0 if the interrupt line is active, else 0 +(other commands) S_IPAC_notImplemented + + Hy8601 IP Asyn Driver Usage ============================ @@ -507,4 +507,4 @@ The following example is for an IOC that uses RTEMS R4.9.4, MVME5500 processor b - + diff --git a/motorApp/ImsSrc/ImsMDrivePlusMotorAxis.cpp b/motorApp/ImsSrc/ImsMDrivePlusMotorAxis.cpp index 72ee756..7d9e821 100644 --- a/motorApp/ImsSrc/ImsMDrivePlusMotorAxis.cpp +++ b/motorApp/ImsSrc/ImsMDrivePlusMotorAxis.cpp @@ -3,8 +3,9 @@ //! MDrivePlus series; M17, M23, M34. //! Use "model 3" asyn motor, asynMotorController and asynMotorAxis classes. //! -//! Author : Nia Fong +//! Original Author : Nia Fong //! Date : 11-21-2011 +//! Current Author : Mitch D'Ewart (SLAC) // // Revision History // ---------------- diff --git a/motorApp/ImsSrc/ImsMDrivePlusMotorController.cpp b/motorApp/ImsSrc/ImsMDrivePlusMotorController.cpp index ecee321..440529e 100644 --- a/motorApp/ImsSrc/ImsMDrivePlusMotorController.cpp +++ b/motorApp/ImsSrc/ImsMDrivePlusMotorController.cpp @@ -3,8 +3,9 @@ //! MDrivePlus series; M17, M23, M34. //! Simple implementation using "model 3" asynMotorController and asynMotorAxis base classes (derived from asynPortDriver) //! -//! Author : Nia Fong +//! Original Author : Nia Fong //! Date : 11-21-2011 +//! Current Author : Mitch D'Ewart (SLAC) //! //! Assumptions : //! 1) Like all controllers, the MDrivePlus must be powered-on when EPICS is first booted up. @@ -62,7 +63,7 @@ ImsMDrivePlusMotorController::ImsMDrivePlusMotorController(const char *motorPort pAxes_ = (ImsMDrivePlusMotorAxis **)(asynMotorController::pAxes_); // copy names - strcpy(motorName, motorPortName); + strncpy(motorName, motorPortName, (MAX_NAME_LEN - 1)); // setup communication status = pasynOctetSyncIO->connect(IOPortName, 0, &pAsynUserIMS, NULL); @@ -110,7 +111,7 @@ ImsMDrivePlusMotorController::ImsMDrivePlusMotorController(const char *motorPort //////////////////////////////////////// void ImsMDrivePlusMotorController::initController(const char *devName, double movingPollPeriod, double idlePollPeriod) { - strcpy(this->deviceName, devName); + strncpy(this->deviceName, devName, (MAX_NAME_LEN - 1)); // initialize asynMotorController variables this->numAxes_ = NUM_AXES; // only support single axis diff --git a/motorApp/ImsSrc/ImsRegister.cc b/motorApp/ImsSrc/ImsRegister.cc index 8322ef2..15298d7 100644 --- a/motorApp/ImsSrc/ImsRegister.cc +++ b/motorApp/ImsSrc/ImsRegister.cc @@ -2,9 +2,6 @@ FILENAME... ImsRegister.cc USAGE... Register IMS motor device driver shell commands. -Version: $Revision: 1.3 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2004-07-16 19:10:15 $ */ /***************************************************************** diff --git a/motorApp/ImsSrc/devIM483PL.cc b/motorApp/ImsSrc/devIM483PL.cc index 6135d69..ca9ce84 100644 --- a/motorApp/ImsSrc/devIM483PL.cc +++ b/motorApp/ImsSrc/devIM483PL.cc @@ -3,10 +3,6 @@ FILENAME... devIM483PL.cc USAGE... Motor record device level support for Intelligent Motion Systems, Inc. IM483(I/IE). -Version: $Revision: 16590 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2013-06-17 09:20:08 -0500 (Mon, 17 Jun 2013) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/ImsSrc/devIM483PL.cc $ */ /* @@ -45,6 +41,7 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motor */ #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -57,7 +54,7 @@ extern struct driver_table IM483PL_access; /* ----------------Create the dsets for devIM483PL----------------- */ STATIC struct driver_table *drvtabptr; -STATIC long IM483PL_init(void *); +STATIC long IM483PL_init(int); STATIC long IM483PL_init_record(void *); STATIC long IM483PL_start_trans(struct motorRecord *); STATIC RTN_STATUS IM483PL_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -111,12 +108,11 @@ static struct board_stat **IM483PL_cards; /* initialize device support for IM483PL stepper motor */ -STATIC long IM483PL_init(void *arg) +STATIC long IM483PL_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &IM483PL_access; (drvtabptr->init)(); diff --git a/motorApp/ImsSrc/devIM483SM.cc b/motorApp/ImsSrc/devIM483SM.cc index ea60923..b4321e0 100644 --- a/motorApp/ImsSrc/devIM483SM.cc +++ b/motorApp/ImsSrc/devIM483SM.cc @@ -3,10 +3,6 @@ FILENAME... devIM483SM.cc USAGE... Motor record device level support for Intelligent Motion Systems, Inc. IM483(I/IE). -Version: $Revision: 16590 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2013-06-17 09:20:08 -0500 (Mon, 17 Jun 2013) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/ImsSrc/devIM483SM.cc $ */ /* @@ -45,6 +41,7 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motor */ #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -57,7 +54,7 @@ extern struct driver_table IM483SM_access; /* ----------------Create the dsets for devIM483SM----------------- */ STATIC struct driver_table *drvtabptr; -STATIC long IM483SM_init(void *); +STATIC long IM483SM_init(int); STATIC long IM483SM_init_record(void *); STATIC long IM483SM_start_trans(struct motorRecord *); STATIC RTN_STATUS IM483SM_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -111,12 +108,11 @@ static struct board_stat **IM483SM_cards; /* initialize device support for IM483SM stepper motor */ -STATIC long IM483SM_init(void *arg) +STATIC long IM483SM_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &IM483SM_access; (drvtabptr->init)(); diff --git a/motorApp/ImsSrc/devMDrive.cc b/motorApp/ImsSrc/devMDrive.cc index 5178229..633a371 100644 --- a/motorApp/ImsSrc/devMDrive.cc +++ b/motorApp/ImsSrc/devMDrive.cc @@ -3,10 +3,6 @@ FILENAME... devMDrive.cc USAGE... Motor record device level support for Intelligent Motion Systems, Inc. MDrive series of controllers. -Version: $Revision: 16590 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2013-06-17 09:20:08 -0500 (Mon, 17 Jun 2013) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/ImsSrc/devMDrive.cc $ */ /* @@ -47,6 +43,7 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motor */ #include +#include #include "motorRecord.h" #include "motor.h" @@ -60,7 +57,7 @@ extern struct driver_table MDrive_access; /* ----------------Create the dsets for devMDrive----------------- */ STATIC struct driver_table *drvtabptr; -STATIC long MDrive_init(void *); +STATIC long MDrive_init(int); STATIC long MDrive_init_record(void *); STATIC long MDrive_start_trans(struct motorRecord *); STATIC RTN_STATUS MDrive_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -114,12 +111,11 @@ static struct board_stat **MDrive_cards; /* initialize device support for MDrive stepper motor */ -STATIC long MDrive_init(void *arg) +STATIC long MDrive_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &MDrive_access; (drvtabptr->init)(); diff --git a/motorApp/ImsSrc/drvIM483.h b/motorApp/ImsSrc/drvIM483.h index c838113..f971c56 100644 --- a/motorApp/ImsSrc/drvIM483.h +++ b/motorApp/ImsSrc/drvIM483.h @@ -3,10 +3,6 @@ FILENAME... drvIM483.h USAGE... This file contains driver "include" information that is specific to Intelligent Motion Systems, Inc. IM483(I/IE) and MDrive controllers. -Version: $Revision: 16590 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2013-06-17 09:20:08 -0500 (Mon, 17 Jun 2013) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/ImsSrc/drvIM483.h $ */ /* diff --git a/motorApp/ImsSrc/drvIM483PL.cc b/motorApp/ImsSrc/drvIM483PL.cc index 64b6745..c503ae6 100644 --- a/motorApp/ImsSrc/drvIM483PL.cc +++ b/motorApp/ImsSrc/drvIM483PL.cc @@ -3,10 +3,6 @@ FILENAME... drvIM483PL.cc USAGE... Motor record driver level support for Intelligent Motion Systems, Inc. IM483(I/IE). -Version: $Revision: 14155 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/ImsSrc/drvIM483PL.cc $ */ /***************************************************************** @@ -60,6 +56,8 @@ DESIGN LIMITATIONS... #include #include #include +#include +#include #include "motor.h" #include "drvIM483.h" #include "asynOctetSyncIO.h" diff --git a/motorApp/ImsSrc/drvIM483SM.cc b/motorApp/ImsSrc/drvIM483SM.cc index 30e329f..5d0157e 100644 --- a/motorApp/ImsSrc/drvIM483SM.cc +++ b/motorApp/ImsSrc/drvIM483SM.cc @@ -3,10 +3,6 @@ FILENAME... drvIM483SM.cc USAGE... Motor record driver level support for Intelligent Motion Systems, Inc. IM483(I/IE). -Version: $Revision: 14155 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/ImsSrc/drvIM483SM.cc $ */ /***************************************************************** @@ -59,6 +55,8 @@ DESIGN LIMITATIONS... #include #include #include +#include +#include #include "motor.h" #include "drvIM483.h" #include "asynOctetSyncIO.h" @@ -240,7 +238,7 @@ static int set_status(int card, int signal) nodeptr = motor_info->motor_motion; status.All = motor_info->status.All; - send_mess(card, "^", (char) NULL); + send_mess(card, "^", (char*) NULL); rtn_state = recv_mess(card, buff, 1); if (rtn_state > 0) { @@ -275,7 +273,7 @@ static int set_status(int card, int signal) * Skip to substring for this motor, convert to double */ - send_mess(card, "Z 0", (char) NULL); + send_mess(card, "Z 0", (char*) NULL); recv_mess(card, buff, 1); motorData = atof(&buff[5]); @@ -297,7 +295,7 @@ static int set_status(int card, int signal) plusdir = (status.Bits.RA_DIRECTION) ? true : false; - send_mess(card, "] 0", (char) NULL); + send_mess(card, "] 0", (char*) NULL); recv_mess(card, buff, 1); rtnval = atoi(&buff[5]); @@ -320,7 +318,7 @@ static int set_status(int card, int signal) else status.Bits.RA_MINUS_LS = 0; - send_mess(card, "] 1", (char) NULL); + send_mess(card, "] 1", (char*) NULL); recv_mess(card, buff, 1); rtnval = buff[5]; @@ -338,7 +336,7 @@ static int set_status(int card, int signal) motor_info->encoder_position = 0; else { - send_mess(card, "z 0", (char) NULL); + send_mess(card, "z 0", (char*) NULL); recv_mess(card, buff, 1); motorData = atof(&buff[5]); motor_info->encoder_position = (epicsInt32) motorData; @@ -361,7 +359,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -553,9 +551,9 @@ static int motor_init() /* flush any junk at input port - should not be any data available */ pasynOctetSyncIO->flush(cntrl->pasynUser); - send_mess(card_index, "\003", (char) NULL); /* Reset device. */ + send_mess(card_index, "\003", (char*) NULL); /* Reset device. */ epicsThreadSleep(1.0); - send_mess(card_index, " ", (char) NULL); + send_mess(card_index, " ", (char*) NULL); /* Save controller identification message. */ src = buff; diff --git a/motorApp/ImsSrc/drvMDrive.cc b/motorApp/ImsSrc/drvMDrive.cc index 93e1a1d..22ceabc 100644 --- a/motorApp/ImsSrc/drvMDrive.cc +++ b/motorApp/ImsSrc/drvMDrive.cc @@ -3,10 +3,6 @@ FILENAME... drvMDrive.cc USAGE... Motor record driver level support for Intelligent Motion Systems, Inc. MDrive series; M17, M23, M34. -Version: $Revision: 16385 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2013-04-24 11:01:47 -0500 (Wed, 24 Apr 2013) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/ImsSrc/drvMDrive.cc $ */ /* @@ -80,6 +76,8 @@ DESIGN LIMITATIONS... #include #include #include +#include +#include #include "motor.h" #include "drvIM483.h" #include "asynOctetSyncIO.h" diff --git a/motorApp/KohzuSrc/devSC800.cc b/motorApp/KohzuSrc/devSC800.cc index 9a2317e..4ca47bb 100644 --- a/motorApp/KohzuSrc/devSC800.cc +++ b/motorApp/KohzuSrc/devSC800.cc @@ -2,10 +2,6 @@ FILENAME... devSC800.cc USAGE... Motor record device level support for Kohzu SC800 motor controller. -Version: $Revision: 9857 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2009-12-09 10:21:24 -0600 (Wed, 09 Dec 2009) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/KohzuSrc/devSC800.cc $ */ @@ -42,6 +38,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include +#include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -52,7 +50,7 @@ extern struct driver_table SC800_access; /* ----------------Create the dsets for devSC800----------------- */ static struct driver_table *drvtabptr; -static long SC800_init(void *); +static long SC800_init(int); static long SC800_init_record(void *); static long SC800_start_trans(struct motorRecord *); static RTN_STATUS SC800_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -110,12 +108,11 @@ static struct board_stat **SC800_cards; /* initialize device support for SC800 stepper motor */ -static long SC800_init(void *arg) +static long SC800_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &SC800_access; (drvtabptr->init)(); diff --git a/motorApp/KohzuSrc/drvSC800.cc b/motorApp/KohzuSrc/drvSC800.cc index c61e88c..74999a7 100644 --- a/motorApp/KohzuSrc/drvSC800.cc +++ b/motorApp/KohzuSrc/drvSC800.cc @@ -2,10 +2,6 @@ FILENAME... drvSC800.cc USAGE... Motor record driver level support for Kohzu SC800 -Version: $Revision: 14155 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/KohzuSrc/drvSC800.cc $ */ @@ -49,6 +45,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#include +#include #include "motor.h" #include "motorRecord.h" #include "drvSC800.h" @@ -223,7 +221,7 @@ static int set_status(int card, int signal) charcnt = recv_mess(card, buff, FLUSH); sprintf(buff,"STR1/%d",(signal + 1)); - send_mess(card, buff, (char) NULL); /* Tell Status */ + send_mess(card, buff, (char*) NULL); /* Tell Status */ charcnt = recv_mess(card, buff, 1); convert_cnt = sscanf(buff, "C\tSTR%d\t1\t%d\t%d\t%d\t%d\t%d\t%d\t%d", &str_axis, &str_move, &str_norg, &str_orgg, @@ -258,7 +256,7 @@ static int set_status(int card, int signal) /* Parse motor position */ sprintf(buff,"RDP%d/0", (signal + 1)); - send_mess(card, buff, (char) NULL); /* Tell Position */ + send_mess(card, buff, (char*) NULL); /* Tell Position */ recv_mess(card, buff, 1); convert_cnt = sscanf(buff, "C\tRDP%d\t%d", &str_axis, &motorData); @@ -287,7 +285,7 @@ static int set_status(int card, int signal) /* Torque enabled? */ sprintf(buff,"RSY%d/21", (signal + 1)); - send_mess(card, buff, (char) NULL); /* Tell Position */ + send_mess(card, buff, (char*) NULL); /* Tell Position */ recv_mess(card, buff, 1); convert_cnt = sscanf(buff, "C\tRSY%d\t21\t%d", &str_axis, &str_move); status.Bits.EA_POSITION = (str_move == 0) ? 1 : 0; @@ -329,7 +327,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } diff --git a/motorApp/KohzuSrc/drvSC800.h b/motorApp/KohzuSrc/drvSC800.h index 4712cef..4089814 100644 --- a/motorApp/KohzuSrc/drvSC800.h +++ b/motorApp/KohzuSrc/drvSC800.h @@ -2,10 +2,6 @@ FILENAME... drvSC800.h USAGE... This file contains Kohzu SC800 motorRecord driver information. -Version: $Revision: 9857 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2009-12-09 10:21:24 -0600 (Wed, 09 Dec 2009) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/KohzuSrc/drvSC800.h $ */ /* diff --git a/motorApp/MXmotorSrc/MXRegister.cc b/motorApp/MXmotorSrc/MXRegister.cc index 84f2260..53b50de 100644 --- a/motorApp/MXmotorSrc/MXRegister.cc +++ b/motorApp/MXmotorSrc/MXRegister.cc @@ -2,9 +2,6 @@ FILENAME... MXRegister.cc USAGE... Register MX motor device driver shell commands. -Version: $Revision: 1.3 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2003-05-28 14:33:57 $ */ /***************************************************************** diff --git a/motorApp/MXmotorSrc/MXmotor.h b/motorApp/MXmotorSrc/MXmotor.h index 7a5402c..a4edd68 100644 --- a/motorApp/MXmotorSrc/MXmotor.h +++ b/motorApp/MXmotorSrc/MXmotor.h @@ -3,9 +3,6 @@ FILENAME... MXmotor.h USAGE... This file contains "include" information that is specific to MX motor device driver support. -Version: $Revision: 1.1 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2003-02-14 15:15:27 $ */ /* diff --git a/motorApp/MXmotorSrc/devMXmotor.cc b/motorApp/MXmotorSrc/devMXmotor.cc index de5fa0a..9f85208 100644 --- a/motorApp/MXmotorSrc/devMXmotor.cc +++ b/motorApp/MXmotorSrc/devMXmotor.cc @@ -2,9 +2,6 @@ FILENAME... devMXmotor.cc USAGE... Motor record device level support for MX device driver. -Version: $Revision: 1.6 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-03-14 20:12:06 $ */ /* @@ -39,7 +36,7 @@ extern int MXmotor_num_cards; extern struct driver_table MXmotor_access; /* ----------------Create the dsets for devMXmotor----------------- */ -static long MXmotor_init(void *); +static long MXmotor_init(int); static long MXmotor_init_record(void *); static long MXmotor_start_trans(struct motorRecord *); static RTN_STATUS MXmotor_build(motor_cmnd, double *, struct motorRecord *); @@ -89,17 +86,15 @@ static struct board_stat **MXmotor_cards; static const char errmsg[] = {"\n\n!!!ERROR!!! - MX driver uninitialized.\n"}; /* initialize device support for MX motor */ -static long MXmotor_init(void *after) +static long MXmotor_init(int after) { - int before_after = (after == 0) ? 0 : 1; - if (*(MXmotor_access.init_indicator) == NO) { errlogSevPrintf(errlogMinor, "%s", errmsg); return(ERROR); } else - return(motor_init_com(before_after, MXmotor_num_cards, &MXmotor_access, + return(motor_init_com(after, MXmotor_num_cards, &MXmotor_access, &MXmotor_cards)); } diff --git a/motorApp/MXmotorSrc/drvMXmotor.cc b/motorApp/MXmotorSrc/drvMXmotor.cc index f004e1e..342e58f 100644 --- a/motorApp/MXmotorSrc/drvMXmotor.cc +++ b/motorApp/MXmotorSrc/drvMXmotor.cc @@ -2,10 +2,6 @@ FILENAME... drvMXmotor.cc USAGE... Motor record driver level support for MX device driver. -Version: $Revision: 14155 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/MXmotorSrc/drvMXmotor.cc $ */ /* diff --git a/motorApp/Makefile b/motorApp/Makefile index 9f89a65..d3275a0 100644 --- a/motorApp/Makefile +++ b/motorApp/Makefile @@ -84,8 +84,11 @@ AttocubeSrc_DEPEND_DIRS = MotorSrc DIRS += AerotechSrc AerotechSrc_DEPEND_DIRS = MotorSrc +# The Hytec support requires ipac +ifdef IPAC DIRS += HytecSrc HytecSrc_DEPEND_DIRS = MotorSrc +endif DIRS += ACRSrc ACRSrc_DEPEND_DIRS = MotorSrc @@ -102,6 +105,15 @@ MicronixSrc_DEPEND_DIRS = MotorSrc DIRS += PhytronSrc PhytronSrc_DEPEND_DIRS = MotorSrc +DIRS += AMCISrc +AMCISrc_DEPEND_DIRS = MotorSrc + +# The Script motor support requires the lua scripting module +ifdef LUA +DIRS += ScriptMotorSrc +ScriptMotorSrc_DEPEND_DIRS = MotorSrc +endif + endif # Install the edl files diff --git a/motorApp/MclennanSrc/MclennanRegister.cc b/motorApp/MclennanSrc/MclennanRegister.cc index 1563bdf..225d586 100644 --- a/motorApp/MclennanSrc/MclennanRegister.cc +++ b/motorApp/MclennanSrc/MclennanRegister.cc @@ -2,9 +2,6 @@ FILENAME... MclennanRegister.cc USAGE... Register Mclennan motor device driver shell commands. -Version: $Revision: 1.3 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2004-07-16 19:17:22 $ */ /***************************************************************** diff --git a/motorApp/MclennanSrc/devPM304.cc b/motorApp/MclennanSrc/devPM304.cc index 2cfb2e5..320d125 100644 --- a/motorApp/MclennanSrc/devPM304.cc +++ b/motorApp/MclennanSrc/devPM304.cc @@ -61,7 +61,7 @@ static inline void Debug(int level, const char *format, ...) { /* ----------------Create the dsets for devPM304----------------- */ STATIC struct driver_table *drvtabptr; -STATIC long PM304_init(void *); +STATIC long PM304_init(int); STATIC long PM304_init_record(void *); STATIC long PM304_start_trans(struct motorRecord *); STATIC RTN_STATUS PM304_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -113,12 +113,11 @@ static struct board_stat **PM304_cards; /* initialize device support for PM304 stepper motor */ -STATIC long PM304_init(void *arg) +STATIC long PM304_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &PM304_access; (drvtabptr->init)(); diff --git a/motorApp/MclennanSrc/drvPM304.cc b/motorApp/MclennanSrc/drvPM304.cc index 273992c..29d1350 100644 --- a/motorApp/MclennanSrc/drvPM304.cc +++ b/motorApp/MclennanSrc/drvPM304.cc @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include "motor.h" #include "drvPM304.h" #include "asynOctetSyncIO.h" @@ -331,7 +333,7 @@ STATIC int set_status(int card, int signal) { strcpy(buff, nodeptr->postmsgptr); strcat(buff, "\r"); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } diff --git a/motorApp/MicosSrc/MicosRegister.cc b/motorApp/MicosSrc/MicosRegister.cc index 798ac68..8821555 100644 --- a/motorApp/MicosSrc/MicosRegister.cc +++ b/motorApp/MicosSrc/MicosRegister.cc @@ -2,9 +2,6 @@ FILENAME... MicosRegister.cc USAGE... Register Micos MoCo dc motor controller device driver shell commands. -Version: $Revision: 1.2 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2004-07-16 19:22:58 $ */ /***************************************************************** diff --git a/motorApp/MicosSrc/devMicos.cc b/motorApp/MicosSrc/devMicos.cc index d57f70e..c075d96 100644 --- a/motorApp/MicosSrc/devMicos.cc +++ b/motorApp/MicosSrc/devMicos.cc @@ -46,7 +46,7 @@ extern struct driver_table Micos_access; /* ----------------Create the dsets for devMicos----------------- */ static struct driver_table *drvtabptr; -static long Micos_init(void *); +static long Micos_init(int); static long Micos_init_record(void *); static long Micos_start_trans(struct motorRecord *); static RTN_STATUS Micos_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -97,13 +97,12 @@ static struct board_stat **Micos_cards; /* initialize device support for Micos DC motor */ -static long Micos_init(void *arg) +static long Micos_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; Debug(5, "Micos_init: entry\n"); - if (after == 0) + if (!after) { drvtabptr = &Micos_access; (drvtabptr->init)(); diff --git a/motorApp/MicosSrc/drvMicos.cc b/motorApp/MicosSrc/drvMicos.cc index 04c0c98..c6e7b2d 100644 --- a/motorApp/MicosSrc/drvMicos.cc +++ b/motorApp/MicosSrc/drvMicos.cc @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "motor.h" #include "drvMicos.h" #include "epicsExport.h" @@ -284,7 +286,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); /* The Micos will not send back a response for a 'set' command, don't need next line */ /* recv_mess(card, buff, WAIT); */ nodeptr->postmsgptr = NULL; diff --git a/motorApp/MicroMoSrc/MicroMoRegister.cc b/motorApp/MicroMoSrc/MicroMoRegister.cc index 99eee9f..00fb5a9 100644 --- a/motorApp/MicroMoSrc/MicroMoRegister.cc +++ b/motorApp/MicroMoSrc/MicroMoRegister.cc @@ -3,9 +3,6 @@ FILENAME... MicroMoRegister.cc USAGE... Register MicroMo MVP 2001 B02 motor controller device driver shell commands. -Version: $Revision: 1.3 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2004-07-16 19:25:09 $ */ /***************************************************************** diff --git a/motorApp/MicroMoSrc/devMVP2001.cc b/motorApp/MicroMoSrc/devMVP2001.cc index 43cc4de..0c7959d 100644 --- a/motorApp/MicroMoSrc/devMVP2001.cc +++ b/motorApp/MicroMoSrc/devMVP2001.cc @@ -3,9 +3,6 @@ FILENAME... devMVP2001.cc USAGE... Motor record device level support for MicroMo MVP 2001 B02 (Linear, RS-485). -Version: $Revision: 1.4 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-06-06 17:16:51 $ */ /* @@ -92,6 +89,8 @@ Last Modified: $Date: 2008-06-06 17:16:51 $ #include #include #include +#include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -105,7 +104,7 @@ extern struct driver_table MVP2001_access; /* ----------------Create the dsets for devMVP2001----------------- */ static struct driver_table *drvtabptr; -static long MVP2001_init(void *); +static long MVP2001_init(int); static long MVP2001_init_record(void *); static long MVP2001_start_trans(struct motorRecord *); static RTN_STATUS MVP2001_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -159,10 +158,9 @@ static struct board_stat **MVP2001_cards; /* initialize device support for MVP2001 DC motor */ -static long MVP2001_init(void *arg) +static long MVP2001_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; drvtabptr = &MVP2001_access; rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &MVP2001_cards); diff --git a/motorApp/MicroMoSrc/drvMVP2001.cc b/motorApp/MicroMoSrc/drvMVP2001.cc index 7566039..233cbb7 100644 --- a/motorApp/MicroMoSrc/drvMVP2001.cc +++ b/motorApp/MicroMoSrc/drvMVP2001.cc @@ -3,9 +3,6 @@ FILENAME... drvMVP2001.cc USAGE... Motor record driver level support for MicroMo MVP 2001 B02 (Linear, RS-485). -Version: $Revision: 14155 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ */ /* @@ -128,6 +125,8 @@ MORE DESIGN LIMITATIONS #include #include #include +#include +#include #include "motor.h" #include "drvMVP2001.h" #include "epicsExport.h" @@ -307,7 +306,7 @@ static int set_status(int card, int signal) statusStr[0] = positionStr[0] = buff[0] = '\0'; sprintf(buff, "%d ST", (signal + 1)); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); rtn_state = recv_mess(card, buff, 1); if (rtn_state > 0) { @@ -343,7 +342,7 @@ static int set_status(int card, int signal) status.Bits.RA_DONE = !mstat.Bits.inMotion; sprintf(buff, "%d POS", (signal + 1)); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); recv_mess(card, buff, 1); /* @@ -434,7 +433,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -645,7 +644,7 @@ static int motor_init() do { sprintf(buff, "%d ST", (total_axis + 1)); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); status = recv_mess(card_index, buff, 1); retry++; } while (status <= 0 && retry < 3); @@ -667,11 +666,11 @@ static int motor_init() /* stop and initialize the controller */ sprintf(buff, "%d V 0", (motor_index + 1)); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); sprintf(buff, "%d HO", (motor_index + 1)); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); sprintf(buff, "%d EN", (motor_index + 1)); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); motor_info->status.All = 0; motor_info->no_motion_count = 0; @@ -690,7 +689,7 @@ static int motor_init() limitStr[0] = '\0'; /* Determine low limit */ sprintf(buff, "%d LL -", (motor_index + 1)); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); strncat(limitStr, &buff[5], 8); motor_info->low_limit = (epicsInt32) strtoul(limitStr, NULL, 16); @@ -698,7 +697,7 @@ static int motor_init() limitStr[0] = '\0'; /* Determine high limit */ sprintf(buff, "%d LL", (motor_index + 1)); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); strncat(limitStr, &buff[5], 8); motor_info->high_limit = (epicsInt32) strtoul(limitStr, NULL, 16); @@ -716,7 +715,7 @@ static int motor_init() epicsThreadSleep(0.2); sprintf(buff, "%d HO", (motor_index + 1)); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); set_status(card_index, motor_index); /* Read status of each * motor */ diff --git a/motorApp/MicroMoSrc/drvMVP2001.h b/motorApp/MicroMoSrc/drvMVP2001.h index 3520731..610880c 100644 --- a/motorApp/MicroMoSrc/drvMVP2001.h +++ b/motorApp/MicroMoSrc/drvMVP2001.h @@ -3,9 +3,6 @@ FILENAME... drvMVP2001.h USAGE... This file contains driver "include" information that is specific to the MicroMo MVP 2001 B02 (Linear, RS-485). -Version: $Revision: 1.5 $ -Modified By: $Author: rivers $ -Last Modified: $Date: 2004-08-17 21:29:32 $ */ /* diff --git a/motorApp/MicronixSrc/MMC200Driver.cpp b/motorApp/MicronixSrc/MMC200Driver.cpp index d91a5f3..00bd317 100644 --- a/motorApp/MicronixSrc/MMC200Driver.cpp +++ b/motorApp/MicronixSrc/MMC200Driver.cpp @@ -136,6 +136,9 @@ MMC200Axis::MMC200Axis(MMC200Controller *pC, int axisNo) // controller axes are numbered from 1 axisIndex_ = axisNo + 1; + // Flush I/O in case there is lingering garbage + pC_->writeReadController(); + // Read the version string to determine controller model (200/100) sprintf(pC_->outString_, "%dVER?", axisIndex_); status = pC_->writeReadController(); diff --git a/motorApp/MotorSimSrc/devMotorSim.c b/motorApp/MotorSimSrc/devMotorSim.c index 1555241..f8889e3 100644 --- a/motorApp/MotorSimSrc/devMotorSim.c +++ b/motorApp/MotorSimSrc/devMotorSim.c @@ -6,6 +6,9 @@ #include #include +/* The following is needed to compile against Base R3.16.1 without a warning */ +#define USE_TYPED_RSET + #include "epicsFindSymbol.h" #include "dbAccess.h" #include "recGbl.h" diff --git a/motorApp/MotorSimSrc/drvMotorSim.c b/motorApp/MotorSimSrc/drvMotorSim.c index 0535181..d28abe7 100644 --- a/motorApp/MotorSimSrc/drvMotorSim.c +++ b/motorApp/MotorSimSrc/drvMotorSim.c @@ -2,9 +2,6 @@ FILENAME... drvMotorSim.c USAGE... Simulated Motor Support. -Version: $Revision: 1.10 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2009-06-18 19:38:20 $ */ /* diff --git a/motorApp/MotorSimSrc/motorSimDriver.cpp b/motorApp/MotorSimSrc/motorSimDriver.cpp index cb3d2f2..bc3e12a 100644 --- a/motorApp/MotorSimSrc/motorSimDriver.cpp +++ b/motorApp/MotorSimSrc/motorSimDriver.cpp @@ -390,6 +390,9 @@ void motorSimAxis::process(double delta ) { double lastpos; int done = 0; + double postMoveDelay = 0.0; + epicsTimeStamp nowTime; + double nowTimeSecs = 0.0; lastpos = nextpoint_.axis[0].p; nextpoint_.T += delta; @@ -430,12 +433,34 @@ void motorSimAxis::process(double delta ) if (nextpoint_.axis[0].v == 0) { if (!deferred_move_) { - done = 1; + if (!delayedDone_) { + done = 1; + } } } else { done = 0; } + //Post move delay + epicsTimeGetCurrent(&nowTime); + pC_->getDoubleParam(axisNo_, pC_->motorPostMoveDelay_, &postMoveDelay); + if ((lastDone_ == 0) && (done == 1)) { + if (postMoveDelay > 0) { + delayedDone_ = 1; + done = 0; + lastTimeSecs_ = nowTime.secPastEpoch + (nowTime.nsec / 1.e9); + } + } + if (delayedDone_ == 1) { + nowTimeSecs = nowTime.secPastEpoch + (nowTime.nsec / 1.e9); + if ((nowTimeSecs - lastTimeSecs_) >= postMoveDelay) { + done = 1; + delayedDone_ = 0; + } + } + + lastDone_ = done; + setDoubleParam (pC_->motorPosition_, (nextpoint_.axis[0].p+enc_offset_)); setDoubleParam (pC_->motorEncoderPosition_, (nextpoint_.axis[0].p+enc_offset_)); setIntegerParam(pC_->motorStatusDirection_, (nextpoint_.axis[0].v > 0)); diff --git a/motorApp/MotorSimSrc/motorSimDriver.h b/motorApp/MotorSimSrc/motorSimDriver.h index 9457c4a..2c9e814 100644 --- a/motorApp/MotorSimSrc/motorSimDriver.h +++ b/motorApp/MotorSimSrc/motorSimDriver.h @@ -52,6 +52,9 @@ class epicsShareClass motorSimAxis : public asynMotorAxis double deferred_position_; int deferred_move_; int deferred_relative_; + double lastTimeSecs_; + int delayedDone_; + int lastDone_; friend class motorSimController; }; diff --git a/motorApp/MotorSrc/README b/motorApp/MotorSrc/README index 9978185..034c35a 100644 --- a/motorApp/MotorSrc/README +++ b/motorApp/MotorSrc/README @@ -1,31 +1,32 @@ -Here's my best guess at what all this stuff is. TMM - Model 3 (asyn, C++) driver base classes --------------------------------- +--------------------------------------- asynMotorAxis.cpp asynMotorAxis.h asynMotorController.cpp asynMotorController.h Model 2 and Model 3 device support --------------------------------- +---------------------------------- devMotorAsyn.c +motor_interface.h Model 2 (asyn, C) --------------- +----------------- drvMotorAsyn.c -motor_interface.h paramLib.c paramLib.h +Definitions used in record, device support, and utilities +--------------------------------------------------------- +motor.h + motor record ------------ -motor.h motorRecord.cc motorRecord.dbd Model 1 (non-asyn) device/driver support ------------------------------- +---------------------------------------- motordevCom.cc motordevCom.h motordrvCom.cc diff --git a/motorApp/MotorSrc/asynMotorAxis.cpp b/motorApp/MotorSrc/asynMotorAxis.cpp index 5dc0b2d..29878b6 100644 --- a/motorApp/MotorSrc/asynMotorAxis.cpp +++ b/motorApp/MotorSrc/asynMotorAxis.cpp @@ -53,6 +53,10 @@ asynMotorAxis::asynMotorAxis(class asynMotorController *pC, int axisNo) /* Used to enable/disable move to home, and to tell driver how far to move.*/ referencingModeMove_ = 0; + wasMovingFlag_ = 0; + disableFlag_ = 0; + lastEndOfMoveTime_ = 0; + // Create the asynUser, connect to this axis pasynUser_ = pasynManager->createAsynUser(NULL, NULL); pasynManager->connectDevice(pasynUser_, pC->portName, axisNo); @@ -187,7 +191,6 @@ asynStatus asynMotorAxis::setEncoderRatio(double ratio) return asynSuccess; } - void asynMotorAxis::report(FILE *fp, int details) { } @@ -342,13 +345,13 @@ asynStatus asynMotorAxis::defineProfile(double *positions, size_t numPoints) asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s:%s: axis=%d, numPoints=%d, positions[0]=%f\n", - driverName, functionName, axisNo_, numPoints, positions[0]); + driverName, functionName, axisNo_, (int)numPoints, positions[0]); if (numPoints > pC_->maxProfilePoints_) return asynError; - status |= pC_->getDoubleParam(axisNo_, pC_->profileMotorResolution_, &resolution); - status |= pC_->getDoubleParam(axisNo_, pC_->profileMotorOffset_, &offset); - status |= pC_->getIntegerParam(axisNo_, pC_->profileMotorDirection_, &direction); + status |= pC_->getDoubleParam(axisNo_, pC_->motorRecResolution_, &resolution); + status |= pC_->getDoubleParam(axisNo_, pC_->motorRecOffset_, &offset); + status |= pC_->getIntegerParam(axisNo_, pC_->motorRecDirection_, &direction); asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s:%s: axis=%d, status=%d, offset=%f direction=%d, resolution=%f\n", driverName, functionName, axisNo_, status, offset, direction, resolution); @@ -415,9 +418,9 @@ asynStatus asynMotorAxis::readbackProfile() int status=0; //static const char *functionName = "readbackProfile"; - status |= pC_->getDoubleParam(axisNo_, pC_->profileMotorResolution_, &resolution); - status |= pC_->getDoubleParam(axisNo_, pC_->profileMotorOffset_, &offset); - status |= pC_->getIntegerParam(axisNo_, pC_->profileMotorDirection_, &direction); + status |= pC_->getDoubleParam(axisNo_, pC_->motorRecResolution_, &resolution); + status |= pC_->getDoubleParam(axisNo_, pC_->motorRecOffset_, &offset); + status |= pC_->getIntegerParam(axisNo_, pC_->motorRecDirection_, &direction); status |= pC_->getIntegerParam(0, pC_->profileNumReadbacks_, &numReadbacks); if (status) return asynError; @@ -431,3 +434,60 @@ asynStatus asynMotorAxis::readbackProfile() status |= pC_->doCallbacksFloat64Array(profileFollowingErrors_, numReadbacks, pC_->profileFollowingErrors_, axisNo_); return asynSuccess; } + +/****************************************************************************/ +/* The following functions are used by the automatic drive power control in the + base class poller in the asynMotorController class.*/ + +/** + * Read the flag that indicates if the last poll was moving. + */ +int asynMotorAxis::getWasMovingFlag(void) +{ + return wasMovingFlag_; +} + +/** + * Set this to 1 if the previous poll indicated moving state + */ +void asynMotorAxis::setWasMovingFlag(int wasMovingFlag) +{ + wasMovingFlag_ = wasMovingFlag; +} + +/** + * Read the flag that indicates if the drive should be automatically + * disabled. + */ +int asynMotorAxis::getDisableFlag(void) +{ + return disableFlag_; +} + +/** + * Set this to 1 if the drive should be automatically disabled. + */ +void asynMotorAxis::setDisableFlag(int disableFlag) +{ + disableFlag_ = disableFlag; +} + +/** + * Read the time in seconds of the last end of move. + */ +double asynMotorAxis::getLastEndOfMoveTime(void) +{ + return lastEndOfMoveTime_; +} + +/** + * Set this to the current time at the end of a move. + */ +void asynMotorAxis::setLastEndOfMoveTime(double time) +{ + lastEndOfMoveTime_ = time; +} + + +/********************************************************************/ + diff --git a/motorApp/MotorSrc/asynMotorAxis.h b/motorApp/MotorSrc/asynMotorAxis.h index 2904b7d..16cf044 100644 --- a/motorApp/MotorSrc/asynMotorAxis.h +++ b/motorApp/MotorSrc/asynMotorAxis.h @@ -1,78 +1,89 @@ -/* asynMotorAxis.h - * - * Mark Rivers - * - * This file defines the base class for an asynMotoAxis. It is the class - * from which real motor axes are derived. - */ -#ifndef asynMotorAxis_H -#define asynMotorAxis_H - -#include -#include - -#ifdef __cplusplus -#include - -#include "asynMotorController.h" - -/** Class from which motor axis objects are derived. */ -class epicsShareClass asynMotorAxis { - - public: - /* This is the constructor for the class. */ - asynMotorAxis(class asynMotorController *pController, int axisNumber); - virtual ~asynMotorAxis(); - - virtual asynStatus setIntegerParam(int index, int value); - virtual asynStatus setDoubleParam(int index, double value); - virtual asynStatus setStringParam(int index, const char *value); - virtual void report(FILE *fp, int details); - virtual asynStatus callParamCallbacks(); - - virtual asynStatus move(double position, int relative, double minVelocity, double maxVelocity, double acceleration); - virtual asynStatus moveVelocity(double minVelocity, double maxVelocity, double acceleration); - virtual asynStatus home(double minVelocity, double maxVelocity, double acceleration, int forwards); - virtual asynStatus stop(double acceleration); - virtual asynStatus poll(bool *moving); - virtual asynStatus setPosition(double position); - virtual asynStatus setEncoderPosition(double position); - virtual asynStatus setHighLimit(double highLimit); - virtual asynStatus setLowLimit(double lowLimit); - virtual asynStatus setPGain(double pGain); - virtual asynStatus setIGain(double iGain); - virtual asynStatus setDGain(double dGain); - virtual asynStatus setClosedLoop(bool closedLoop); - virtual asynStatus setEncoderRatio(double ratio); - virtual asynStatus doMoveToHome(); - - virtual asynStatus initializeProfile(size_t maxPoints); - virtual asynStatus defineProfile(double *positions, size_t numPoints); - virtual asynStatus buildProfile(); - virtual asynStatus executeProfile(); - virtual asynStatus abortProfile(); - virtual asynStatus readbackProfile(); - - void setReferencingModeMove(int distance); - int getReferencingModeMove(); - - protected: - class asynMotorController *pC_; /**< Pointer to the asynMotorController to which this axis belongs. - * Abbreviated because it is used very frequently */ - int axisNo_; /**< Index number of this axis (0 - pC_->numAxes_-1) */ - asynUser *pasynUser_; /**< asynUser connected to this axis for asynTrace debugging */ - double *profilePositions_; /**< Array of target positions for profile moves */ - double *profileReadbacks_; /**< Array of readback positions for profile moves */ - double *profileFollowingErrors_; /**< Array of following errors for profile moves */ - int referencingMode_; - - private: - MotorStatus status_; - int statusChanged_; - int referencingModeMove_; - - friend class asynMotorController; -}; - -#endif /* _cplusplus */ -#endif /* asynMotorAxis_H */ +/* asynMotorAxis.h + * + * Mark Rivers + * + * This file defines the base class for an asynMotorAxis. It is the class + * from which real motor axes are derived. + */ +#ifndef asynMotorAxis_H +#define asynMotorAxis_H + +#include +#include + +#ifdef __cplusplus +#include + +#include "asynMotorController.h" + +/** Class from which motor axis objects are derived. */ +class epicsShareClass asynMotorAxis { + + public: + /* This is the constructor for the class. */ + asynMotorAxis(class asynMotorController *pController, int axisNumber); + virtual ~asynMotorAxis(); + + virtual asynStatus setIntegerParam(int index, int value); + virtual asynStatus setDoubleParam(int index, double value); + virtual asynStatus setStringParam(int index, const char *value); + virtual void report(FILE *fp, int details); + virtual asynStatus callParamCallbacks(); + + virtual asynStatus move(double position, int relative, double minVelocity, double maxVelocity, double acceleration); + virtual asynStatus moveVelocity(double minVelocity, double maxVelocity, double acceleration); + virtual asynStatus home(double minVelocity, double maxVelocity, double acceleration, int forwards); + virtual asynStatus stop(double acceleration); + virtual asynStatus poll(bool *moving); + virtual asynStatus setPosition(double position); + virtual asynStatus setEncoderPosition(double position); + virtual asynStatus setHighLimit(double highLimit); + virtual asynStatus setLowLimit(double lowLimit); + virtual asynStatus setPGain(double pGain); + virtual asynStatus setIGain(double iGain); + virtual asynStatus setDGain(double dGain); + virtual asynStatus setClosedLoop(bool closedLoop); + virtual asynStatus setEncoderRatio(double ratio); + virtual asynStatus doMoveToHome(); + + virtual asynStatus initializeProfile(size_t maxPoints); + virtual asynStatus defineProfile(double *positions, size_t numPoints); + virtual asynStatus buildProfile(); + virtual asynStatus executeProfile(); + virtual asynStatus abortProfile(); + virtual asynStatus readbackProfile(); + + void setReferencingModeMove(int distance); + int getReferencingModeMove(); + + int getWasMovingFlag(); + void setWasMovingFlag(int wasMoving); + int getDisableFlag(); + void setDisableFlag(int disableFlag); + double getLastEndOfMoveTime(); + void setLastEndOfMoveTime(double time); + + protected: + class asynMotorController *pC_; /**< Pointer to the asynMotorController to which this axis belongs. + * Abbreviated because it is used very frequently */ + int axisNo_; /**< Index number of this axis (0 - pC_->numAxes_-1) */ + asynUser *pasynUser_; /**< asynUser connected to this axis for asynTrace debugging */ + double *profilePositions_; /**< Array of target positions for profile moves */ + double *profileReadbacks_; /**< Array of readback positions for profile moves */ + double *profileFollowingErrors_; /**< Array of following errors for profile moves */ + int referencingMode_; + + MotorStatus status_; + int statusChanged_; + + private: + int referencingModeMove_; + int wasMovingFlag_; + int disableFlag_; + double lastEndOfMoveTime_; + + friend class asynMotorController; +}; + +#endif /* _cplusplus */ +#endif /* asynMotorAxis_H */ diff --git a/motorApp/MotorSrc/asynMotorController.cpp b/motorApp/MotorSrc/asynMotorController.cpp index 9d0adb0..e5d069d 100644 --- a/motorApp/MotorSrc/asynMotorController.cpp +++ b/motorApp/MotorSrc/asynMotorController.cpp @@ -19,6 +19,14 @@ #include "asynMotorController.h" #include "asynMotorAxis.h" +#ifndef VERSION_INT +# define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P)) +#endif + +#define MOTOR_ASYN_VERSION_INT VERSION_INT(ASYN_VERSION,ASYN_REVISION,ASYN_MODIFICATION,0) + +#define VERSION_INT_4_32 VERSION_INT(4,32,0,0) + static const char *driverName = "asynMotorController"; static void asynMotorPollerC(void *drvPvt); static void asynMotorMoveToHomeC(void *drvPvt); @@ -34,12 +42,14 @@ asynMotorController::asynMotorController(const char *portName, int numAxes, int int interfaceMask, int interruptMask, int asynFlags, int autoConnect, int priority, int stackSize) - : asynPortDriver(portName, numAxes, NUM_MOTOR_DRIVER_PARAMS+numParams, + : asynPortDriver(portName, numAxes, +#if MOTOR_ASYN_VERSION_INT < VERSION_INT_4_32 + NUM_MOTOR_DRIVER_PARAMS+numParams, +#endif interfaceMask | asynOctetMask | asynInt32Mask | asynFloat64Mask | asynFloat64ArrayMask | asynGenericPointerMask | asynDrvUserMask, interruptMask | asynOctetMask | asynInt32Mask | asynFloat64Mask | asynFloat64ArrayMask | asynGenericPointerMask, asynFlags, autoConnect, priority, stackSize), shuttingDown_(0), numAxes_(numAxes) - { static const char *functionName = "asynMotorController"; @@ -64,6 +74,11 @@ asynMotorController::asynMotorController(const char *portName, int numAxes, int createParam(motorHighLimitString, asynParamFloat64, &motorHighLimit_); createParam(motorLowLimitString, asynParamFloat64, &motorLowLimit_); createParam(motorClosedLoopString, asynParamInt32, &motorClosedLoop_); + createParam(motorPowerAutoOnOffString, asynParamInt32, &motorPowerAutoOnOff_); + createParam(motorPowerOnDelayString, asynParamFloat64, &motorPowerOnDelay_); + createParam(motorPowerOffDelayString, asynParamFloat64, &motorPowerOffDelay_); + createParam(motorPowerOffFractionString, asynParamInt32, &motorPowerOffFraction_); + createParam(motorPostMoveDelayString, asynParamFloat64, &motorPostMoveDelay_); createParam(motorStatusString, asynParamInt32, &motorStatus_); createParam(motorUpdateStatusString, asynParamInt32, &motorUpdateStatus_); createParam(motorStatusDirectionString, asynParamInt32, &motorStatusDirection_); @@ -82,6 +97,11 @@ asynMotorController::asynMotorController(const char *portName, int numAxes, int createParam(motorStatusLowLimitString, asynParamInt32, &motorStatusLowLimit_); createParam(motorStatusHomedString, asynParamInt32, &motorStatusHomed_); + // These are per-axis parameters for passing additional motor record information to the driver + createParam(motorRecResolutionString, asynParamFloat64, &motorRecResolution_); + createParam(motorRecDirectionString, asynParamInt32, &motorRecDirection_); + createParam(motorRecOffsetString, asynParamFloat64, &motorRecOffset_); + // These are the per-controller parameters for profile moves createParam(profileNumAxesString, asynParamInt32, &profileNumAxes_); createParam(profileNumPointsString, asynParamInt32, &profileNumPoints_); @@ -115,9 +135,6 @@ asynMotorController::asynMotorController(const char *portName, int numAxes, int createParam(profilePositionsString, asynParamFloat64Array, &profilePositions_); createParam(profileReadbacksString, asynParamFloat64Array, &profileReadbacks_); createParam(profileFollowingErrorsString, asynParamFloat64Array, &profileFollowingErrors_); - createParam(profileMotorResolutionString, asynParamFloat64, &profileMotorResolution_); - createParam(profileMotorDirectionString, asynParamInt32, &profileMotorDirection_); - createParam(profileMotorOffsetString, asynParamFloat64, &profileMotorOffset_); pAxes_ = (asynMotorAxis**) calloc(numAxes, sizeof(asynMotorAxis*)); pollEventId_ = epicsEventMustCreate(epicsEventEmpty); @@ -255,6 +272,8 @@ asynStatus asynMotorController::writeFloat64(asynUser *pasynUser, epicsFloat64 v asynMotorAxis *pAxis; int axis; int forwards; + int autoPower = 0; + double autoPowerOnDelay = 0.0; asynStatus status = asynError; static const char *functionName = "writeFloat64"; @@ -262,14 +281,21 @@ asynStatus asynMotorController::writeFloat64(asynUser *pasynUser, epicsFloat64 v if (!pAxis) return asynError; axis = pAxis->axisNo_; + getIntegerParam(axis, motorPowerAutoOnOff_, &autoPower); + getDoubleParam(axis, motorPowerOnDelay_, &autoPowerOnDelay); + /* Set the parameter and readback in the parameter library. */ status = pAxis->setDoubleParam(function, value); - getDoubleParam(axis, motorVelBase_, &baseVelocity); - getDoubleParam(axis, motorVelocity_, &velocity); - getDoubleParam(axis, motorAccel_, &acceleration); - if (function == motorMoveRel_) { + if (autoPower == 1) { + status = pAxis->setClosedLoop(true); + pAxis->setWasMovingFlag(1); + epicsThreadSleep(autoPowerOnDelay); + } + getDoubleParam(axis, motorVelBase_, &baseVelocity); + getDoubleParam(axis, motorVelocity_, &velocity); + getDoubleParam(axis, motorAccel_, &acceleration); status = pAxis->move(value, 1, baseVelocity, velocity, acceleration); pAxis->setIntegerParam(motorStatusDone_, 0); pAxis->callParamCallbacks(); @@ -279,6 +305,14 @@ asynStatus asynMotorController::writeFloat64(asynUser *pasynUser, epicsFloat64 v driverName, functionName, portName, pAxis->axisNo_, value, baseVelocity, velocity, acceleration ); } else if (function == motorMoveAbs_) { + if (autoPower == 1) { + status = pAxis->setClosedLoop(true); + pAxis->setWasMovingFlag(1); + epicsThreadSleep(autoPowerOnDelay); + } + getDoubleParam(axis, motorVelBase_, &baseVelocity); + getDoubleParam(axis, motorVelocity_, &velocity); + getDoubleParam(axis, motorAccel_, &acceleration); status = pAxis->move(value, 0, baseVelocity, velocity, acceleration); pAxis->setIntegerParam(motorStatusDone_, 0); pAxis->callParamCallbacks(); @@ -288,6 +322,13 @@ asynStatus asynMotorController::writeFloat64(asynUser *pasynUser, epicsFloat64 v driverName, functionName, portName, pAxis->axisNo_, value, baseVelocity, velocity, acceleration ); } else if (function == motorMoveVel_) { + if (autoPower == 1) { + status = pAxis->setClosedLoop(true); + pAxis->setWasMovingFlag(1); + epicsThreadSleep(autoPowerOnDelay); + } + getDoubleParam(axis, motorVelBase_, &baseVelocity); + getDoubleParam(axis, motorAccel_, &acceleration); status = pAxis->moveVelocity(baseVelocity, value, acceleration); pAxis->setIntegerParam(motorStatusDone_, 0); pAxis->callParamCallbacks(); @@ -298,6 +339,14 @@ asynStatus asynMotorController::writeFloat64(asynUser *pasynUser, epicsFloat64 v // Note, the motorHome command happens on the asynFloat64 interface, even though the value (direction) is really integer } else if (function == motorHome_) { + if (autoPower == 1) { + status = pAxis->setClosedLoop(true); + pAxis->setWasMovingFlag(1); + epicsThreadSleep(autoPowerOnDelay); + } + getDoubleParam(axis, motorVelBase_, &baseVelocity); + getDoubleParam(axis, motorVelocity_, &velocity); + getDoubleParam(axis, motorAccel_, &acceleration); forwards = (value == 0) ? 0 : 1; status = pAxis->home(baseVelocity, velocity, acceleration, forwards); pAxis->setIntegerParam(motorStatusDone_, 0); @@ -569,7 +618,11 @@ void asynMotorController::asynMotorPoller() int forcedFastPolls=0; bool anyMoving; bool moving; + epicsTimeStamp nowTime; + double nowTimeSecs = 0.0; asynMotorAxis *pAxis; + int autoPower = 0; + double autoPowerOffDelay = 0.0; int status; timeout = idlePollPeriod_; @@ -592,12 +645,42 @@ void asynMotorController::asynMotorPoller() unlock(); break; } + poll(); for (i=0; ipoll(&moving); - if (moving) anyMoving = true;; + pAxis=getAxis(i); + if (!pAxis) continue; + + getIntegerParam(i, motorPowerAutoOnOff_, &autoPower); + getDoubleParam(i, motorPowerOffDelay_, &autoPowerOffDelay); + + pAxis->poll(&moving); + if (moving) { + anyMoving = true; + pAxis->setWasMovingFlag(1); + } else { + if ((pAxis->getWasMovingFlag() == 1) && (autoPower == 1)) { + pAxis->setDisableFlag(1); + pAxis->setWasMovingFlag(0); + epicsTimeGetCurrent(&nowTime); + pAxis->setLastEndOfMoveTime(nowTime.secPastEpoch + (nowTime.nsec / 1.e9)); + } + } + + //Auto power off drive, if: + // We have detected an end of move + // We are not moving again + // Auto power off is enabled + // Auto power off delay timer has expired + if ((!moving) && (autoPower == 1) && (pAxis->getDisableFlag() == 1)) { + epicsTimeGetCurrent(&nowTime); + nowTimeSecs = nowTime.secPastEpoch + (nowTime.nsec / 1.e9); + if ((nowTimeSecs - pAxis->getLastEndOfMoveTime()) >= autoPowerOffDelay) { + pAxis->setClosedLoop(0); + pAxis->setDisableFlag(0); + } + } + } if (forcedFastPolls > 0) { timeout = movingPollPeriod_; diff --git a/motorApp/MotorSrc/asynMotorController.h b/motorApp/MotorSrc/asynMotorController.h index e1ff986..56b44e9 100644 --- a/motorApp/MotorSrc/asynMotorController.h +++ b/motorApp/MotorSrc/asynMotorController.h @@ -1,301 +1,315 @@ -/* asynMotorController.h - * - * Mark Rivers - * - * This file defines the base class for an asynMotorController. It is the class - * from which real motor controllers are derived. It derives from asynPortDriver. - */ -#ifndef asynMotorController_H -#define asynMotorController_H - -#include -#include - -#define MAX_CONTROLLER_STRING_SIZE 256 -#define DEFAULT_CONTROLLER_TIMEOUT 2.0 - -/** Strings defining parameters for the driver. - * These are the values passed to drvUserCreate. - * The driver will place in pasynUser->reason an integer to be used when the - * standard asyn interface methods are called. */ -#define motorMoveRelString "MOTOR_MOVE_REL" -#define motorMoveAbsString "MOTOR_MOVE_ABS" -#define motorMoveVelString "MOTOR_MOVE_VEL" -#define motorHomeString "MOTOR_HOME" -#define motorStopString "MOTOR_STOP_AXIS" -#define motorVelocityString "MOTOR_VELOCITY" -#define motorVelBaseString "MOTOR_VEL_BASE" -#define motorAccelString "MOTOR_ACCEL" -#define motorPositionString "MOTOR_POSITION" -#define motorEncoderPositionString "MOTOR_ENCODER_POSITION" -#define motorDeferMovesString "MOTOR_DEFER_MOVES" -#define motorMoveToHomeString "MOTOR_MOVE_HOME" -#define motorResolutionString "MOTOR_RESOLUTION" -#define motorEncoderRatioString "MOTOR_ENCODER_RATIO" -#define motorPGainString "MOTOR_PGAIN" -#define motorIGainString "MOTOR_IGAIN" -#define motorDGainString "MOTOR_DGAIN" -#define motorHighLimitString "MOTOR_HIGH_LIMIT" -#define motorLowLimitString "MOTOR_LOW_LIMIT" -#define motorClosedLoopString "MOTOR_CLOSED_LOOP" -#define motorStatusString "MOTOR_STATUS" -#define motorUpdateStatusString "MOTOR_UPDATE_STATUS" -#define motorStatusDirectionString "MOTOR_STATUS_DIRECTION" -#define motorStatusDoneString "MOTOR_STATUS_DONE" -#define motorStatusHighLimitString "MOTOR_STATUS_HIGH_LIMIT" -#define motorStatusAtHomeString "MOTOR_STATUS_AT_HOME" -#define motorStatusSlipString "MOTOR_STATUS_SLIP" -#define motorStatusPowerOnString "MOTOR_STATUS_POWERED" -#define motorStatusFollowingErrorString "MOTOR_STATUS_FOLLOWING_ERROR" -#define motorStatusHomeString "MOTOR_STATUS_HOME" -#define motorStatusHasEncoderString "MOTOR_STATUS_HAS_ENCODER" -#define motorStatusProblemString "MOTOR_STATUS_PROBLEM" -#define motorStatusMovingString "MOTOR_STATUS_MOVING" -#define motorStatusGainSupportString "MOTOR_STATUS_GAIN_SUPPORT" -#define motorStatusCommsErrorString "MOTOR_STATUS_COMMS_ERROR" -#define motorStatusLowLimitString "MOTOR_STATUS_LOW_LIMIT" -#define motorStatusHomedString "MOTOR_STATUS_HOMED" - -/* These are the per-controller parameters for profile moves (coordinated motion) */ -#define profileNumAxesString "PROFILE_NUM_AXES" -#define profileNumPointsString "PROFILE_NUM_POINTS" -#define profileCurrentPointString "PROFILE_CURRENT_POINT" -#define profileNumPulsesString "PROFILE_NUM_PULSES" -#define profileStartPulsesString "PROFILE_START_PULSES" -#define profileEndPulsesString "PROFILE_END_PULSES" -#define profileActualPulsesString "PROFILE_ACTUAL_PULSES" -#define profileNumReadbacksString "PROFILE_NUM_READBACKS" -#define profileTimeModeString "PROFILE_TIME_MODE" -#define profileFixedTimeString "PROFILE_FIXED_TIME" -#define profileTimeArrayString "PROFILE_TIME_ARRAY" -#define profileAccelerationString "PROFILE_ACCELERATION" -#define profileMoveModeString "PROFILE_MOVE_MODE" -#define profileBuildString "PROFILE_BUILD" -#define profileBuildStateString "PROFILE_BUILD_STATE" -#define profileBuildStatusString "PROFILE_BUILD_STATUS" -#define profileBuildMessageString "PROFILE_BUILD_MESSAGE" -#define profileExecuteString "PROFILE_EXECUTE" -#define profileExecuteStateString "PROFILE_EXECUTE_STATE" -#define profileExecuteStatusString "PROFILE_EXECUTE_STATUS" -#define profileExecuteMessageString "PROFILE_EXECUTE_MESSAGE" -#define profileAbortString "PROFILE_ABORT" -#define profileReadbackString "PROFILE_READBACK" -#define profileReadbackStateString "PROFILE_READBACK_STATE" -#define profileReadbackStatusString "PROFILE_READBACK_STATUS" -#define profileReadbackMessageString "PROFILE_READBACK_MESSAGE" - -/* These are the per-axis parameters for profile moves */ -#define profileUseAxisString "PROFILE_USE_AXIS" -#define profilePositionsString "PROFILE_POSITIONS" -#define profileReadbacksString "PROFILE_READBACKS" -#define profileFollowingErrorsString "PROFILE_FOLLOWING_ERRORS" -#define profileMotorResolutionString "PROFILE_MOTOR_RESOLUTION" -#define profileMotorDirectionString "PROFILE_MOTOR_DIRECTION" -#define profileMotorOffsetString "PROFILE_MOTOR_OFFSET" - -/** The structure that is passed back to devMotorAsyn when the status changes. */ -typedef struct MotorStatus { - double position; /**< Commanded motor position */ - double encoderPosition; /**< Actual encoder position */ - double velocity; /**< Actual velocity */ - epicsUInt32 status; /**< Word containing status bits (motion done, limits, etc.) */ -} MotorStatus; - -enum ProfileTimeMode{ - PROFILE_TIME_MODE_FIXED, - PROFILE_TIME_MODE_ARRAY -}; - -enum ProfileMoveMode{ - PROFILE_MOVE_MODE_ABSOLUTE, - PROFILE_MOVE_MODE_RELATIVE -}; - -/* State codes for Build, Read and Execute. Careful, these must match the - * corresponding MBBI records, but there is no way to check this */ -enum ProfileBuildState{ - PROFILE_BUILD_DONE, - PROFILE_BUILD_BUSY -}; - -enum ProfileExecuteState{ - PROFILE_EXECUTE_DONE, - PROFILE_EXECUTE_MOVE_START, - PROFILE_EXECUTE_EXECUTING, - PROFILE_EXECUTE_FLYBACK -}; - -enum ProfileReadbackState{ - PROFILE_READBACK_DONE, - PROFILE_READBACK_BUSY -}; - - -/* Status codes for Build, Execute and Read */ -enum ProfileStatus { - PROFILE_STATUS_UNDEFINED, - PROFILE_STATUS_SUCCESS, - PROFILE_STATUS_FAILURE, - PROFILE_STATUS_ABORT, - PROFILE_STATUS_TIMEOUT -}; - -#ifdef __cplusplus -#include - -class asynMotorAxis; - -class epicsShareClass asynMotorController : public asynPortDriver { - - public: - /* This is the constructor for the class. */ - asynMotorController(const char *portName, int numAxes, int numParams, - int interfaceMask, int interruptMask, - int asynFlags, int autoConnect, int priority, int stackSize); - - virtual ~asynMotorController(); - - /* These are the methods that we override from asynPortDriver */ - virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); - virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value); - virtual asynStatus writeFloat64Array(asynUser *pasynUser, epicsFloat64 *value, size_t nElements); - virtual asynStatus readFloat64Array(asynUser *pasynUser, epicsFloat64 *value, size_t nElements, size_t *nRead); - virtual asynStatus readGenericPointer(asynUser *pasynUser, void *pointer); - virtual void report(FILE *fp, int details); - - /* These are the methods that are new to this class */ - virtual asynMotorAxis* getAxis(asynUser *pasynUser); - virtual asynMotorAxis* getAxis(int axisNo); - virtual asynStatus startPoller(double movingPollPeriod, double idlePollPeriod, int forcedFastPolls); - virtual asynStatus wakeupPoller(); - virtual asynStatus poll(); - virtual asynStatus setDeferredMoves(bool defer); - void asynMotorPoller(); // This should be private but is called from C function - - /* Functions to deal with moveToHome.*/ - virtual asynStatus startMoveToHomeThread(); - void asynMotorMoveToHome(); - - /* These are the functions for profile moves */ - virtual asynStatus initializeProfile(size_t maxPoints); - virtual asynStatus buildProfile(); - virtual asynStatus executeProfile(); - virtual asynStatus abortProfile(); - virtual asynStatus readbackProfile(); - - virtual asynStatus setMovingPollPeriod(double movingPollPeriod); - virtual asynStatus setIdlePollPeriod(double idlePollPeriod); - - int shuttingDown_; /**< Flag indicating that IOC is shutting down. Stops poller */ - - protected: - /** These are the index numbers for the parameters in the parameter library. - * They are the values of pasynUser->reason in calls from device support */ - // These are the motor commands - #define FIRST_MOTOR_PARAM motorMoveRel_ - int motorMoveRel_; - int motorMoveAbs_; - int motorMoveVel_; - int motorHome_; - int motorStop_; - int motorVelocity_; - int motorVelBase_; - int motorAccel_; - int motorPosition_; - int motorEncoderPosition_; - int motorDeferMoves_; - int motorMoveToHome_; - int motorResolution_; - int motorEncoderRatio_; - int motorPGain_; - int motorIGain_; - int motorDGain_; - int motorHighLimit_; - int motorLowLimit_; - int motorClosedLoop_; - int motorStatus_; - int motorUpdateStatus_; - - // These are the status bits - int motorStatusDirection_; - int motorStatusDone_; - int motorStatusHighLimit_; - int motorStatusAtHome_; - int motorStatusSlip_; - int motorStatusPowerOn_; - int motorStatusFollowingError_; - int motorStatusHome_; - int motorStatusHasEncoder_; - int motorStatusProblem_; - int motorStatusMoving_; - int motorStatusGainSupport_; - int motorStatusCommsError_; - int motorStatusLowLimit_; - int motorStatusHomed_; - - // These are the per-controller parameters for profile moves - int profileNumAxes_; - int profileNumPoints_; - int profileCurrentPoint_; - int profileNumPulses_; - int profileStartPulses_; - int profileEndPulses_; - int profileActualPulses_; - int profileNumReadbacks_; - int profileTimeMode_; - int profileFixedTime_; - int profileTimeArray_; - int profileAcceleration_; - int profileMoveMode_; - int profileBuild_; - int profileBuildState_; - int profileBuildStatus_; - int profileBuildMessage_; - int profileExecute_; - int profileExecuteState_; - int profileExecuteStatus_; - int profileExecuteMessage_; - int profileAbort_; - int profileReadback_; - int profileReadbackState_; - int profileReadbackStatus_; - int profileReadbackMessage_; - - // These are the per-axis parameters for profile moves - int profileUseAxis_; - int profilePositions_; - int profileReadbacks_; - int profileFollowingErrors_; - int profileMotorResolution_; - int profileMotorDirection_; - int profileMotorOffset_; - #define LAST_MOTOR_PARAM profileMotorOffset_ - - int numAxes_; /**< Number of axes this controller supports */ - asynMotorAxis **pAxes_; /**< Array of pointers to axis objects */ - epicsEventId pollEventId_; /**< Event ID to wake up poller */ - epicsEventId moveToHomeId_; /**< Event ID to wake up move to home thread */ - double idlePollPeriod_; /**< The time between polls when no axes are moving */ - double movingPollPeriod_; /**< The time between polls when any axis is moving */ - int forcedFastPolls_; /**< The number of forced fast polls when the poller wakes up */ - - size_t maxProfilePoints_; /**< Maximum number of profile points */ - double *profileTimes_; /**< Array of times per profile point */ - - int moveToHomeAxis_; - - /* These are convenience functions for controllers that use asynOctet interfaces to the hardware */ - asynStatus writeController(); - asynStatus writeController(const char *output, double timeout); - asynStatus writeReadController(); - asynStatus writeReadController(const char *output, char *response, size_t maxResponseLen, size_t *responseLen, double timeout); - asynUser *pasynUserController_; - char outString_[MAX_CONTROLLER_STRING_SIZE]; - char inString_[MAX_CONTROLLER_STRING_SIZE]; - - friend class asynMotorAxis; -}; -#define NUM_MOTOR_DRIVER_PARAMS (&LAST_MOTOR_PARAM - &FIRST_MOTOR_PARAM + 1) - -#endif /* _cplusplus */ -#endif /* asynMotorController_H */ +/* asynMotorController.h + * + * Mark Rivers + * + * This file defines the base class for an asynMotorController. It is the class + * from which real motor controllers are derived. It derives from asynPortDriver. + */ +#ifndef asynMotorController_H +#define asynMotorController_H + +#include +#include + +#define MAX_CONTROLLER_STRING_SIZE 256 +#define DEFAULT_CONTROLLER_TIMEOUT 2.0 + +/** Strings defining parameters for the driver. + * These are the values passed to drvUserCreate. + * The driver will place in pasynUser->reason an integer to be used when the + * standard asyn interface methods are called. */ +#define motorMoveRelString "MOTOR_MOVE_REL" +#define motorMoveAbsString "MOTOR_MOVE_ABS" +#define motorMoveVelString "MOTOR_MOVE_VEL" +#define motorHomeString "MOTOR_HOME" +#define motorStopString "MOTOR_STOP_AXIS" +#define motorVelocityString "MOTOR_VELOCITY" +#define motorVelBaseString "MOTOR_VEL_BASE" +#define motorAccelString "MOTOR_ACCEL" +#define motorPositionString "MOTOR_POSITION" +#define motorEncoderPositionString "MOTOR_ENCODER_POSITION" +#define motorDeferMovesString "MOTOR_DEFER_MOVES" +#define motorMoveToHomeString "MOTOR_MOVE_HOME" +#define motorResolutionString "MOTOR_RESOLUTION" +#define motorEncoderRatioString "MOTOR_ENCODER_RATIO" +#define motorPGainString "MOTOR_PGAIN" +#define motorIGainString "MOTOR_IGAIN" +#define motorDGainString "MOTOR_DGAIN" +#define motorHighLimitString "MOTOR_HIGH_LIMIT" +#define motorLowLimitString "MOTOR_LOW_LIMIT" +#define motorClosedLoopString "MOTOR_CLOSED_LOOP" +#define motorPowerAutoOnOffString "MOTOR_POWER_AUTO_ONOFF" +#define motorPowerOnDelayString "MOTOR_POWER_ON_DELAY" +#define motorPowerOffDelayString "MOTOR_POWER_OFF_DELAY" +#define motorPowerOffFractionString "MOTOR_POWER_OFF_FRACTION" +#define motorPostMoveDelayString "MOTOR_POST_MOVE_DELAY" +#define motorStatusString "MOTOR_STATUS" +#define motorUpdateStatusString "MOTOR_UPDATE_STATUS" +#define motorStatusDirectionString "MOTOR_STATUS_DIRECTION" +#define motorStatusDoneString "MOTOR_STATUS_DONE" +#define motorStatusHighLimitString "MOTOR_STATUS_HIGH_LIMIT" +#define motorStatusAtHomeString "MOTOR_STATUS_AT_HOME" +#define motorStatusSlipString "MOTOR_STATUS_SLIP" +#define motorStatusPowerOnString "MOTOR_STATUS_POWERED" +#define motorStatusFollowingErrorString "MOTOR_STATUS_FOLLOWING_ERROR" +#define motorStatusHomeString "MOTOR_STATUS_HOME" +#define motorStatusHasEncoderString "MOTOR_STATUS_HAS_ENCODER" +#define motorStatusProblemString "MOTOR_STATUS_PROBLEM" +#define motorStatusMovingString "MOTOR_STATUS_MOVING" +#define motorStatusGainSupportString "MOTOR_STATUS_GAIN_SUPPORT" +#define motorStatusCommsErrorString "MOTOR_STATUS_COMMS_ERROR" +#define motorStatusLowLimitString "MOTOR_STATUS_LOW_LIMIT" +#define motorStatusHomedString "MOTOR_STATUS_HOMED" + +/* These are per-axis parameters for passing additional motor record information to the driver */ +#define motorRecResolutionString "MOTOR_REC_RESOLUTION" +#define motorRecDirectionString "MOTOR_REC_DIRECTION" +#define motorRecOffsetString "MOTOR_REC_OFFSET" + +/* These are the per-controller parameters for profile moves (coordinated motion) */ +#define profileNumAxesString "PROFILE_NUM_AXES" +#define profileNumPointsString "PROFILE_NUM_POINTS" +#define profileCurrentPointString "PROFILE_CURRENT_POINT" +#define profileNumPulsesString "PROFILE_NUM_PULSES" +#define profileStartPulsesString "PROFILE_START_PULSES" +#define profileEndPulsesString "PROFILE_END_PULSES" +#define profileActualPulsesString "PROFILE_ACTUAL_PULSES" +#define profileNumReadbacksString "PROFILE_NUM_READBACKS" +#define profileTimeModeString "PROFILE_TIME_MODE" +#define profileFixedTimeString "PROFILE_FIXED_TIME" +#define profileTimeArrayString "PROFILE_TIME_ARRAY" +#define profileAccelerationString "PROFILE_ACCELERATION" +#define profileMoveModeString "PROFILE_MOVE_MODE" +#define profileBuildString "PROFILE_BUILD" +#define profileBuildStateString "PROFILE_BUILD_STATE" +#define profileBuildStatusString "PROFILE_BUILD_STATUS" +#define profileBuildMessageString "PROFILE_BUILD_MESSAGE" +#define profileExecuteString "PROFILE_EXECUTE" +#define profileExecuteStateString "PROFILE_EXECUTE_STATE" +#define profileExecuteStatusString "PROFILE_EXECUTE_STATUS" +#define profileExecuteMessageString "PROFILE_EXECUTE_MESSAGE" +#define profileAbortString "PROFILE_ABORT" +#define profileReadbackString "PROFILE_READBACK" +#define profileReadbackStateString "PROFILE_READBACK_STATE" +#define profileReadbackStatusString "PROFILE_READBACK_STATUS" +#define profileReadbackMessageString "PROFILE_READBACK_MESSAGE" + +/* These are the per-axis parameters for profile moves */ +#define profileUseAxisString "PROFILE_USE_AXIS" +#define profilePositionsString "PROFILE_POSITIONS" +#define profileReadbacksString "PROFILE_READBACKS" +#define profileFollowingErrorsString "PROFILE_FOLLOWING_ERRORS" + +/** The structure that is passed back to devMotorAsyn when the status changes. */ +typedef struct MotorStatus { + double position; /**< Commanded motor position */ + double encoderPosition; /**< Actual encoder position */ + double velocity; /**< Actual velocity */ + epicsUInt32 status; /**< Word containing status bits (motion done, limits, etc.) */ +} MotorStatus; + +enum ProfileTimeMode{ + PROFILE_TIME_MODE_FIXED, + PROFILE_TIME_MODE_ARRAY +}; + +enum ProfileMoveMode{ + PROFILE_MOVE_MODE_ABSOLUTE, + PROFILE_MOVE_MODE_RELATIVE +}; + +/* State codes for Build, Read and Execute. Careful, these must match the + * corresponding MBBI records, but there is no way to check this */ +enum ProfileBuildState{ + PROFILE_BUILD_DONE, + PROFILE_BUILD_BUSY +}; + +enum ProfileExecuteState{ + PROFILE_EXECUTE_DONE, + PROFILE_EXECUTE_MOVE_START, + PROFILE_EXECUTE_EXECUTING, + PROFILE_EXECUTE_FLYBACK +}; + +enum ProfileReadbackState{ + PROFILE_READBACK_DONE, + PROFILE_READBACK_BUSY +}; + + +/* Status codes for Build, Execute and Read */ +enum ProfileStatus { + PROFILE_STATUS_UNDEFINED, + PROFILE_STATUS_SUCCESS, + PROFILE_STATUS_FAILURE, + PROFILE_STATUS_ABORT, + PROFILE_STATUS_TIMEOUT +}; + +#ifdef __cplusplus +#include + +class asynMotorAxis; + +class epicsShareClass asynMotorController : public asynPortDriver { + + public: + /* This is the constructor for the class. */ + asynMotorController(const char *portName, int numAxes, int numParams, + int interfaceMask, int interruptMask, + int asynFlags, int autoConnect, int priority, int stackSize); + + virtual ~asynMotorController(); + + /* These are the methods that we override from asynPortDriver */ + virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); + virtual asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value); + virtual asynStatus writeFloat64Array(asynUser *pasynUser, epicsFloat64 *value, size_t nElements); + virtual asynStatus readFloat64Array(asynUser *pasynUser, epicsFloat64 *value, size_t nElements, size_t *nRead); + virtual asynStatus readGenericPointer(asynUser *pasynUser, void *pointer); + virtual void report(FILE *fp, int details); + + /* These are the methods that are new to this class */ + virtual asynMotorAxis* getAxis(asynUser *pasynUser); + virtual asynMotorAxis* getAxis(int axisNo); + virtual asynStatus startPoller(double movingPollPeriod, double idlePollPeriod, int forcedFastPolls); + virtual asynStatus wakeupPoller(); + virtual asynStatus poll(); + virtual asynStatus setDeferredMoves(bool defer); + void asynMotorPoller(); // This should be private but is called from C function + + /* Functions to deal with moveToHome.*/ + virtual asynStatus startMoveToHomeThread(); + void asynMotorMoveToHome(); + + /* These are the functions for profile moves */ + virtual asynStatus initializeProfile(size_t maxPoints); + virtual asynStatus buildProfile(); + virtual asynStatus executeProfile(); + virtual asynStatus abortProfile(); + virtual asynStatus readbackProfile(); + + virtual asynStatus setMovingPollPeriod(double movingPollPeriod); + virtual asynStatus setIdlePollPeriod(double idlePollPeriod); + + int shuttingDown_; /**< Flag indicating that IOC is shutting down. Stops poller */ + + protected: + /** These are the index numbers for the parameters in the parameter library. + * They are the values of pasynUser->reason in calls from device support */ + // These are the motor commands + #define FIRST_MOTOR_PARAM motorMoveRel_ + int motorMoveRel_; + int motorMoveAbs_; + int motorMoveVel_; + int motorHome_; + int motorStop_; + int motorVelocity_; + int motorVelBase_; + int motorAccel_; + int motorPosition_; + int motorEncoderPosition_; + int motorDeferMoves_; + int motorMoveToHome_; + int motorResolution_; + int motorEncoderRatio_; + int motorPGain_; + int motorIGain_; + int motorDGain_; + int motorHighLimit_; + int motorLowLimit_; + int motorClosedLoop_; + int motorPowerAutoOnOff_; + int motorPowerOnDelay_; + int motorPowerOffDelay_; + int motorPowerOffFraction_; + int motorPostMoveDelay_; + int motorStatus_; + int motorUpdateStatus_; + + // These are the status bits + int motorStatusDirection_; + int motorStatusDone_; + int motorStatusHighLimit_; + int motorStatusAtHome_; + int motorStatusSlip_; + int motorStatusPowerOn_; + int motorStatusFollowingError_; + int motorStatusHome_; + int motorStatusHasEncoder_; + int motorStatusProblem_; + int motorStatusMoving_; + int motorStatusGainSupport_; + int motorStatusCommsError_; + int motorStatusLowLimit_; + int motorStatusHomed_; + + // These are per-axis parameters for passing additional motor record information to the driver + int motorRecResolution_; + int motorRecDirection_; + int motorRecOffset_; + + // These are the per-controller parameters for profile moves + int profileNumAxes_; + int profileNumPoints_; + int profileCurrentPoint_; + int profileNumPulses_; + int profileStartPulses_; + int profileEndPulses_; + int profileActualPulses_; + int profileNumReadbacks_; + int profileTimeMode_; + int profileFixedTime_; + int profileTimeArray_; + int profileAcceleration_; + int profileMoveMode_; + int profileBuild_; + int profileBuildState_; + int profileBuildStatus_; + int profileBuildMessage_; + int profileExecute_; + int profileExecuteState_; + int profileExecuteStatus_; + int profileExecuteMessage_; + int profileAbort_; + int profileReadback_; + int profileReadbackState_; + int profileReadbackStatus_; + int profileReadbackMessage_; + + // These are the per-axis parameters for profile moves + int profileUseAxis_; + int profilePositions_; + int profileReadbacks_; + int profileFollowingErrors_; + #define LAST_MOTOR_PARAM profileFollowingErrors_ + + int numAxes_; /**< Number of axes this controller supports */ + asynMotorAxis **pAxes_; /**< Array of pointers to axis objects */ + epicsEventId pollEventId_; /**< Event ID to wake up poller */ + epicsEventId moveToHomeId_; /**< Event ID to wake up move to home thread */ + double idlePollPeriod_; /**< The time between polls when no axes are moving */ + double movingPollPeriod_; /**< The time between polls when any axis is moving */ + int forcedFastPolls_; /**< The number of forced fast polls when the poller wakes up */ + + size_t maxProfilePoints_; /**< Maximum number of profile points */ + double *profileTimes_; /**< Array of times per profile point */ + + int moveToHomeAxis_; + + /* These are convenience functions for controllers that use asynOctet interfaces to the hardware */ + asynStatus writeController(); + asynStatus writeController(const char *output, double timeout); + asynStatus writeReadController(); + asynStatus writeReadController(const char *output, char *response, size_t maxResponseLen, size_t *responseLen, double timeout); + asynUser *pasynUserController_; + char outString_[MAX_CONTROLLER_STRING_SIZE]; + char inString_[MAX_CONTROLLER_STRING_SIZE]; + + friend class asynMotorAxis; +}; +#define NUM_MOTOR_DRIVER_PARAMS (&LAST_MOTOR_PARAM - &FIRST_MOTOR_PARAM + 1) + +#endif /* _cplusplus */ +#endif /* asynMotorController_H */ diff --git a/motorApp/MotorSrc/devMotorAsyn.c b/motorApp/MotorSrc/devMotorAsyn.c index 00d6ef8..c09834e 100644 --- a/motorApp/MotorSrc/devMotorAsyn.c +++ b/motorApp/MotorSrc/devMotorAsyn.c @@ -11,9 +11,6 @@ * Notwithstanding the above, explicit permission is granted for APS to * redistribute this software. * - * Version: $Revision: 1.32 $ - * Modified by: $Author: rivers $ - * Last Modified: $Date: 2009-09-01 14:05:38 $ * * Original Author: Peter Denison * Current Author: Peter Denison @@ -41,6 +38,11 @@ * * .05 2014-09-11 RLS * Moved CA posting of changes to the RMP, REP and RVEL fields from motor record to update_values(). + * + * .06 2015-07-29 RLS + * Added "Use Relative" (use_rel) indicator to init_controller()'s "LOAD_POS" logic. + * See README R6-10 item #6 for details. + * */ #include @@ -49,15 +51,7 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include /* !! for callocMustSucceed() */ -#include +#include "motor_epics_inc.h" #include #include @@ -177,14 +171,16 @@ static void init_controller(struct motorRecord *pmr, asynUser *pasynUser ) double position = pPvt->status.position; double rdbd = (fabs(pmr->rdbd) < fabs(pmr->mres) ? fabs(pmr->mres) : fabs(pmr->rdbd) ); double encRatio[2] = {pmr->mres, pmr->eres}; + int use_rel = (pmr->rtry != 0 && pmr->rmod != motorRMOD_I && (pmr->ueip || pmr->urip)); /*Before setting position, set the correct encoder ratio.*/ start_trans(pmr); build_trans(SET_ENC_RATIO, encRatio, pmr); end_trans(pmr); - if ((fabs(pmr->dval) > rdbd && pmr->mres != 0) && - (fabs(position * pmr->mres) < rdbd)) + if ((use_rel != 0) || + ((fabs(pmr->dval) > rdbd) && (pmr->mres != 0) && (fabs(position * pmr->mres) < rdbd)) + ) { double setPos = pmr->dval / pmr->mres; epicsEventId initEvent = epicsEventCreate( epicsEventEmpty ); diff --git a/motorApp/MotorSrc/drvMotorAsyn.c b/motorApp/MotorSrc/drvMotorAsyn.c index f75e72a..311edb8 100644 --- a/motorApp/MotorSrc/drvMotorAsyn.c +++ b/motorApp/MotorSrc/drvMotorAsyn.c @@ -19,9 +19,6 @@ * of this distribution. * ************************************************************************ * - * Version: $Revision: 1.22 $ - * Modified by: $Author: rivers $ - * Last Modified: $Date: 2009-09-01 14:05:07 $ * * Original Author: Peter Denison * Current Author: Peter Denison diff --git a/motorApp/MotorSrc/motor.h b/motorApp/MotorSrc/motor.h index 4d30d92..b718684 100644 --- a/motorApp/MotorSrc/motor.h +++ b/motorApp/MotorSrc/motor.h @@ -3,9 +3,6 @@ FILENAME... motor.h USAGE... Definitions and structures common to all levels of motorRecord support (i.e., record, device and driver). -Version: $Revision: 1.21 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2009-04-27 14:28:42 $ */ /* @@ -66,7 +63,11 @@ Last Modified: $Date: 2009-04-27 14:28:42 $ #include /* Less than EPICS base version test.*/ -#define LT_EPICSBASE(v,r,l) ((EPICS_VERSION<=(v)) && (EPICS_REVISION<=(r)) && (EPICS_MODIFICATION<(l))) +#ifndef EPICS_VERSION_INT +#define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P)) +#define EPICS_VERSION_INT VERSION_INT(EPICS_VERSION, EPICS_REVISION, EPICS_MODIFICATION, EPICS_PATCH_LEVEL) +#endif +#define LT_EPICSBASE(V,R,M,P) (EPICS_VERSION_INT < VERSION_INT((V),(R),(M),(P))) /* Maximum message size of all supported devices; see drv[device].h for maximum message size for each device. */ diff --git a/motorApp/MotorSrc/motorRecord.cc b/motorApp/MotorSrc/motorRecord.cc index 1589c0c..3aaf1a3 100644 --- a/motorApp/MotorSrc/motorRecord.cc +++ b/motorApp/MotorSrc/motorRecord.cc @@ -2,10 +2,6 @@ FILENAME... motorRecord.cc USAGE... Motor Record Support. -Version: $Revision: 17843 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2014-09-11 10:37:22 -0500 (Thu, 11 Sep 2014) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/MotorSrc/motorRecord.cc $ */ /* @@ -183,24 +179,29 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- * - Fix for LOAD_POS not posting RVAL. * - Reversed order of issuing SET_VEL_BASE and SET_VELOCITY commands. Fixes MAXv * command errors. + * .71 02-25-15 rls - Fix for excessive motor record forward link processing. + * .72 03-13-15 rls - Changed RDBL to set RRBV rather than DRBV. + * .73 02-15-16 rls - JOGF/R soft limit error check was using the wrong coordinate sytem limits. + * Changed error checks from dial to user limits. + * .74 09-28-16 rls - Reverted .71 FLNK change. Except for the condition that DMOV == FALSE, FLNK + * processing was standard. If processing is needed on a DMOV false to true + * transition, a new motor record field should be added. + * .75 05-18-17 rls - Stop motor if URIP is Yes and RDBL read returns an error. + * .76 04-04-18 rls - If URIP is Yes and RDBL is inaccessible (e.g., CA server is down), do not start + * a new target position move (sans Home search or Jog). + * .78 08-21-18 kmp - Reverted .69 stop on RA_PROBLEM true. */ -#define VERSION 6.9 +#define VERSION 6.10 #include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include "motor_epics_inc.h" + #define GEN_SIZE_OFFSET #include "motorRecord.h" #undef GEN_SIZE_OFFSET @@ -242,38 +243,39 @@ static void syncTargetPosition(motorRecord *); /*** Record Support Entry Table (RSET) functions. ***/ -static long init_record(dbCommon *, int); -static long process(dbCommon *); +extern "C" { +static long init_record(struct dbCommon*, int); +static long process(struct dbCommon*); static long special(DBADDR *, int); -static long get_units(const DBADDR *, char *); -static long get_precision(const DBADDR *, long *); -static long get_graphic_double(const DBADDR *, struct dbr_grDouble *); -static long get_control_double(const DBADDR *, struct dbr_ctrlDouble *); -static long get_alarm_double(const DBADDR *, struct dbr_alDouble *); - +static long get_units(DBADDR *, char *); +static long get_precision(const struct dbAddr *, long *); +static long get_graphic_double(DBADDR *, struct dbr_grDouble *); +static long get_control_double(DBADDR *, struct dbr_ctrlDouble *); +static long get_alarm_double(DBADDR *, struct dbr_alDouble *); rset motorRSET = { RSETNUMBER, NULL, NULL, - (RECSUPFUN) init_record, - (RECSUPFUN) process, - (RECSUPFUN) special, + RECSUPFUN_CAST init_record, + RECSUPFUN_CAST process, + RECSUPFUN_CAST special, NULL, NULL, NULL, NULL, - (RECSUPFUN) get_units, - (RECSUPFUN) get_precision, + RECSUPFUN_CAST get_units, + RECSUPFUN_CAST get_precision, NULL, NULL, NULL, - (RECSUPFUN) get_graphic_double, - (RECSUPFUN) get_control_double, - (RECSUPFUN) get_alarm_double + RECSUPFUN_CAST get_graphic_double, + RECSUPFUN_CAST get_control_double, + RECSUPFUN_CAST get_alarm_double }; -extern "C" {epicsExportAddress(rset, motorRSET);} +epicsExportAddress(rset, motorRSET); +} /******************************************************************************* @@ -464,7 +466,7 @@ static void callbackFunc(struct callback *pcb) { pmr->mip &= ~MIP_DELAY_REQ; /* Turn off REQ. */ pmr->mip |= MIP_DELAY_ACK; /* Turn on ACK. */ -#if LT_EPICSBASE(3,14,10) +#if LT_EPICSBASE(3,14,10,0) scanOnce(pmr); #else scanOnce((struct dbCommon *) pmr); @@ -511,7 +513,8 @@ again. Initialize Limit violation field false. IF (Software Travel limits are NOT disabled), AND, (Dial readback violates dial high limit), OR, - (Dial readback violates dial low limit) + (Dial readback violates dial low limit), OR, + (Dial low limit is greater than dial high limit) Set Limit violation field true. ENDIF ... @@ -660,7 +663,8 @@ static long init_record(dbCommon* arg, int pass) if ((pmr->dhlm == pmr->dllm) && (pmr->dllm == 0.0)) ; - else if ((pmr->drbv > pmr->dhlm + pmr->mres) || (pmr->drbv < pmr->dllm - pmr->mres)) + else if ((pmr->drbv > pmr->dhlm + pmr->mres) || (pmr->drbv < pmr->dllm - pmr->mres) || + (pmr->dllm > pmr->dhlm)) { pmr->lvio = 1; MARK(M_LVIO); @@ -704,8 +708,7 @@ any of several reasons: ... ELSE IF done stopping after jog, OR, done with move. IF |backlash distance| > |motor resolution|. - IF Retry enabled, AND, [(encoder present, AND, use encoder true), - OR, use readback link true] + IF Retry enabled, AND, [use encoder true, OR, use readback link true] Set relative positioning indicator true. ELSE Set relative positioning indicator false. @@ -721,8 +724,7 @@ any of several reasons: ... ELSE IF done with 1st phase take out backlash after jog. Calculate backlash velocity, base velocity, backlash accel. and backlash position. - IF Retry enabled, AND, [(encoder present, AND, use encoder true), - OR, use readback link true] + IF Retry enabled, AND, [use encoder true, OR, use readback link true] Set relative positioning indicator true. ELSE Set relative positioning indicator false. @@ -785,7 +787,7 @@ static long postProcess(motorRecord * pmr) double vbase = pmr->vbas / fabs(pmr->mres); double hpos = 0; double hvel = pmr->hvel / fabs(pmr->mres); - double acc = (hvel - vbase) / pmr->accl; + double acc = (hvel - vbase) > 0 ? ((hvel - vbase)/ pmr->accl): (hvel / pmr->accl); motor_cmnd command; @@ -845,7 +847,7 @@ static long postProcess(motorRecord * pmr) /* Use if encoder or ReadbackLink is in use. */ msta.All = pmr->msta; - bool use_rel = (pmr->rtry != 0 && pmr->rmod != motorRMOD_I && ((msta.Bits.EA_PRESENT && pmr->ueip) || pmr->urip)); + bool use_rel = (pmr->rtry != 0 && pmr->rmod != motorRMOD_I && (pmr->ueip || pmr->urip)); double relpos = pmr->diff / pmr->mres; double relbpos = ((pmr->dval - pmr->bdst) - pmr->drbv) / pmr->mres; @@ -857,7 +859,7 @@ static long postProcess(motorRecord * pmr) if (pmr->mip & MIP_JOG_STOP) { - double acc = (vel - vbase) / pmr->accl; + double acc = (vel - vbase) > 0 ? ((vel - vbase)/ pmr->accl) : (vel / pmr->accl); if (vel <= vbase) vel = vbase + 1; @@ -874,7 +876,7 @@ static long postProcess(motorRecord * pmr) else { double bvel = pmr->bvel / fabs(pmr->mres); - double bacc = (bvel - vbase) / pmr->bacc; + double bacc = (bvel - vbase) > 0 ? ((bvel - vbase)/ pmr->bacc) : (bvel / pmr->bacc); if (bvel <= vbase) bvel = vbase + 1; @@ -910,12 +912,12 @@ static long postProcess(motorRecord * pmr) /* First part of jog done. Do backlash correction. */ double bvel = pmr->bvel / fabs(pmr->mres); double vbase = pmr->vbas / fabs(pmr->mres); - double bacc = (bvel - vbase) / pmr->bacc; + double bacc = (bvel - vbase) > 0 ? ((bvel - vbase)/ pmr->bacc) : (bvel / pmr->bacc); double bpos = (pmr->dval - pmr->bdst) / pmr->mres; /* Use if encoder or ReadbackLink is in use. */ msta.All = pmr->msta; - bool use_rel = (pmr->rtry != 0 && pmr->rmod != motorRMOD_I && ((msta.Bits.EA_PRESENT && pmr->ueip) || pmr->urip)); + bool use_rel = (pmr->rtry != 0 && pmr->rmod != motorRMOD_I && (pmr->ueip || pmr->urip)); double relpos = pmr->diff / pmr->mres; double relbpos = ((pmr->dval - pmr->bdst) - pmr->drbv) / pmr->mres; @@ -967,7 +969,12 @@ that it will happen when we return. ******************************************************************************/ static void maybeRetry(motorRecord * pmr) { - if ((fabs(pmr->diff) >= pmr->rdbd) && !pmr->hls && !pmr->lls) + bool user_cdir; + + /* Commanded direction in user coordinates. */ + user_cdir = ((pmr->dir == motorDIR_Pos) == (pmr->mres >= 0)) ? pmr->cdir : !pmr->cdir; + + if ((fabs(pmr->diff) >= pmr->rdbd) && !(pmr->hls && user_cdir) && !(pmr->lls && !user_cdir)) { /* No, we're not close enough. Try again. */ Debug(1, "maybeRetry: not close enough; diff = %f\n", pmr->diff); @@ -1118,8 +1125,9 @@ where the motor is in a sequence of movements that comprise a single motion. Call postProcess(). ENDIF ENDIF - IF the Done Moving field (DMOV) is TRUE. - Initialize delay ticks. + IF a limit switch is activated, OR, a load-position command is in progress (MIP = MIP_LOAD_P) + Set MIP to DONE and MARK it. + ELSE IF Done Moving (DMOV) is TRUE IF process delay acknowledged is true, OR, ticks <= 0. Clear process delay request and ack. indicators in MIP field. Mark MIP as changed. @@ -1139,7 +1147,7 @@ where the motor is in a sequence of movements that comprise a single motion. Clear Limit violation field. ELSE IF Jog indicator is true in MIP field. - Update Limit violation (LVIO) based on Jog direction (JOGF/JOGR) and velocity (JVEL). + Update Limit violation (LVIO) based on Jog direction (JOGF/JOGR) and velocity (JVEL) or DLLM > HLLM ELSE IF Homing indicator is true in MIP field. Set Limit violation (LVIO) FALSE. ENDIF @@ -1164,7 +1172,8 @@ where the motor is in a sequence of movements that comprise a single motion. Update record timestamp, call recGblGetTimeStamp(). Process alarms, call alarm_sub(). Monitor changes to record fields, call monitor(). - IF Done Moving field (DMOV) is TRUE. + + IF Done Moving field (DMOV) is TRUE Process the forward-scan-link record, call recGblFwdLink(). ENDIF Set Processing Active indicator field (PACT) false. @@ -1269,12 +1278,22 @@ static long process(dbCommon *arg) /* Assume we're done moving until we find out otherwise. */ if (pmr->dmov == FALSE) { + Debug(3, "%s:%d motor has stopped pp=%d mip=0x%0x\n", + __FILE__, __LINE__, pmr->pp, pmr->mip); pmr->dmov = TRUE; MARK(M_DMOV); + if (pmr->mip == MIP_JOGF || pmr->mip == MIP_JOGR) + { + /* Motor stopped while jogging and we didn't stop it */ + pmr->mip = MIP_DONE; + MARK(M_MIP); + clear_buttons(pmr); + pmr->pp = TRUE; + } } /* Do another update after LS error. */ - if (pmr->mip != MIP_DONE && (pmr->rhls || pmr->rlls)) + if (pmr->mip != MIP_DONE && ((pmr->rhls && pmr->cdir) || (pmr->rlls && !pmr->cdir))) { /* Restore DMOV to false and UNMARK it so it is not posted. */ pmr->dmov = FALSE; @@ -1303,8 +1322,13 @@ static long process(dbCommon *arg) status = postProcess(pmr); } - /* Are we "close enough" to desired position? */ - if (pmr->dmov == TRUE && !(pmr->rhls || pmr->rlls)) + /* Should we test for a retry? Consider limit only if in direction of move.*/ + if (((pmr->rhls && pmr->cdir) || (pmr->rlls && !pmr->cdir)) || (pmr->mip == MIP_LOAD_P)) + { + pmr->mip = MIP_DONE; + MARK(M_MIP); + } + else if (pmr->dmov == TRUE) { mmap_bits.All = pmr->mmap; /* Initialize for MARKED. */ @@ -1362,8 +1386,9 @@ static long process(dbCommon *arg) else { if (pmr->mip & MIP_JOG) - pmr->lvio = (pmr->jogf && (pmr->drbv > pmr->dhlm - pmr->jvel)) || - (pmr->jogr && (pmr->drbv < pmr->dllm + pmr->jvel)); + pmr->lvio = (pmr->jogf && (pmr->rbv > pmr->hlm - pmr->jvel)) || + (pmr->jogr && (pmr->rbv < pmr->llm + pmr->jvel)) || + (pmr->dllm > pmr->dhlm); else if (pmr->mip & MIP_HOME) pmr->lvio = false; /* Disable soft-limit error check during home search. */ } @@ -1371,7 +1396,7 @@ static long process(dbCommon *arg) if (pmr->lvio != old_lvio) { MARK(M_LVIO); - if (pmr->lvio && !pmr->set) + if (pmr->lvio && (!pmr->set && !pmr->igset)) { pmr->stop = 1; MARK(M_STOP); @@ -1402,9 +1427,9 @@ static long process(dbCommon *arg) alarm_sub(pmr); /* If we've violated alarm limits, yell. */ monitor(pmr); /* If values have changed, broadcast them. */ - if (pmr->dmov) - recGblFwdLink(pmr); /* Process the forward-scan-link record. */ - + if (pmr->dmov != 0) + recGblFwdLink(pmr); /* Process the forward-scan-link record. */ + pmr->pact = 0; Debug(4, "process:---------------------- end; motor \"%s\"\n", pmr->name); return (status); @@ -1590,8 +1615,7 @@ OFFset = userVAL - DialVAL * DIR ELSE Calculate.... - IF Retry enabled, AND, [(encoder present, AND, use encoder true), - OR, use readback link true] + IF Retry enabled, AND, Retry mode is Not "In-Position", AND, [use encoder true, OR, use readback link true] Set relative positioning indicator true. ELSE Set relative positioning indicator false. @@ -1621,6 +1645,8 @@ OFFset = userVAL - DialVAL * DIR IF this is not a retry. Reset retry counter and mark RCNT for dbposting. + ELSE + Process retry based on retry mode (RMOD). ENDIF IF (relative move indicator is OFF, AND, sign of absolute move @@ -1632,16 +1658,23 @@ OFFset = userVAL - DialVAL * DIR Set preferred direction indicator OFF. ENDIF - IF the dial DIFF is within the retry deadband. - IF MIP state is DONE. - Update last target positions. - Terminate move. Set DMOV TRUE. - ENDIF - NORMAL RETURN. + Process soft-travel limit. + + IF URIP is set to Yes + Test and set indicator on RDBL access in case it is a CA link that is down. + ENDIF + IF soft-travel limit error, OR, RDBL CA server disconnect error. + Restore previous target positions. + IF MIP indicates this is a retry. + Set MIP to Done. + ENDIF + IF MIP indicates Done Moving and DMOV is False + Set DMOV true. + ENDIF ENDIF .... .... - IF motion in progress indicator is false. + IF motion in progress indicator (MIP) is Done or Retry. Set MIP MOVE indicator ON and mark for posting. IF DMOV is TRUE. Set DMOV to FALSE and mark for posting. @@ -1786,9 +1819,13 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) /* Cancel any operations. */ if (pmr->mip & MIP_HOME) clear_buttons(pmr); - - pmr->mip = MIP_STOP; - MARK(M_MIP); + + if (!(pmr->mip & MIP_DELAY_REQ)) { + /* When we wait for DLY, keep it. */ + /* Otherwise the record may lock up */ + pmr->mip = MIP_STOP; + MARK(M_MIP); + } INIT_MSG(); WRITE_MSG(STOP_AXIS, NULL); SEND_MSG(); @@ -1844,8 +1881,8 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) /* Calculate encoder ratio. */ for (m = 10000000; (m > 1) && (fabs(m / pmr->eres) > 1.e6 || fabs(m / pmr->mres) > 1.e6); m /= 10); - ep_mp[0] = fabs(m / pmr->eres); - ep_mp[1] = fabs(m / pmr->mres); + ep_mp[0] = m / pmr->eres; + ep_mp[1] = m / pmr->mres; } else { @@ -1862,7 +1899,7 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) WRITE_MSG(SET_ENC_RATIO, ep_mp); SEND_MSG(); } - if (pmr->set) + if (pmr->set && !pmr->igset) { pmr->pp = TRUE; INIT_MSG(); @@ -1929,7 +1966,7 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) vbase = pmr->vbas / fabs(pmr->mres); hvel = pmr->hvel / fabs(pmr->mres); - acc = (hvel - vbase) / pmr->accl; + acc = (hvel - vbase) > 0 ? ((hvel - vbase) / pmr->accl) : (hvel / pmr->accl); hpos = 0; INIT_MSG(); @@ -1968,11 +2005,23 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) /* check for limit violation */ if ((pmr->dhlm == pmr->dllm) && (pmr->dllm == 0.0)) ; - else if ((pmr->jogf && (pmr->dval > pmr->dhlm - pmr->jvel)) || - (pmr->jogr && (pmr->dval < pmr->dllm + pmr->jvel))) + else if ((pmr->jogf && (pmr->val > pmr->hlm - pmr->jvel)) || + (pmr->jogr && (pmr->val < pmr->llm + pmr->jvel)) || + (pmr->dllm > pmr->dhlm)) { pmr->lvio = 1; MARK(M_LVIO); + /* Prevent record from locking up in mip=JOG_REQ */ + if (pmr->jogf) + { + pmr->jogf = 0; + MARK_AUX(M_JOGF); + } + if (pmr->jogr) + { + pmr->jogr = 0; + MARK_AUX(M_JOGR); + } return(OK); } pmr->mip = pmr->jogf ? MIP_JOGF : MIP_JOGR; @@ -2076,7 +2125,7 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) if (pmr->val != pmr->lval) { MARK(M_VAL); - if (set && !pmr->foff) + if ((set && !pmr->igset) && !pmr->foff) { /* * Act directly on .val. and return. User wants to redefine .val @@ -2126,7 +2175,7 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) pmr->rdif = NINT(pmr->diff / pmr->mres); MARK(M_RDIF); - if (set) + if (set && !pmr->igset) { if ((pmr->mip & MIP_LOAD_P) == 0) /* Test for LOAD_POS completion. */ load_pos(pmr); @@ -2141,24 +2190,24 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) double newpos = pmr->dval / pmr->mres; /* where to go */ double vbase = pmr->vbas / fabs(pmr->mres); /* base speed */ double vel = pmr->velo / fabs(pmr->mres); /* normal speed */ - double acc = (vel - vbase) / pmr->accl; /* normal accel. */ + double acc = (vel - vbase) > 0 ? ((vel - vbase) / pmr->accl) : (vel / pmr->accl); /* normal accel. */ /* * 'bpos' is one backlash distance away from 'newpos'. */ double bpos = (pmr->dval - pmr->bdst) / pmr->mres; double bvel = pmr->bvel / fabs(pmr->mres); /* backlash speed */ - double bacc = (bvel - vbase) / pmr->bacc; /* backlash accel. */ + double bacc = (bvel - vbase) > 0 ? ((bvel - vbase) / pmr->bacc) : (bvel / pmr->bacc); /* backlash accel. */ bool use_rel, preferred_dir, too_small; double relpos = pmr->diff / pmr->mres; double relbpos = ((pmr->dval - pmr->bdst) - pmr->drbv) / pmr->mres; double rbdst1 = 1.0 + (fabs(pmr->bdst) / fabs(pmr->mres)); long rdbdpos = NINT(pmr->rdbd / fabs(pmr->mres)); /* retry deadband steps */ - long rpos, npos; + long rpos, npos, rtnstat; msta_field msta; msta.All = pmr->msta; /*** Use if encoder or ReadbackLink is in use. ***/ - if (pmr->rtry != 0 && pmr->rmod != motorRMOD_I && ((msta.Bits.EA_PRESENT && pmr->ueip) || pmr->urip)) + if (pmr->rtry != 0 && pmr->rmod != motorRMOD_I && (pmr->ueip || pmr->urip)) use_rel = true; else use_rel = false; @@ -2185,6 +2234,18 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) { if (abs(npos - rpos) < 1) too_small = true; + if (!too_small) + { + double spdb = pmr->spdb; + if (spdb > 0) { + /* Don't move if new setpoint is within SPDB of DRBV */ + double drbv = pmr->drbv; + double dval = pmr->dval; + if (((dval - spdb) < drbv) && ((dval + spdb) > drbv)) { + too_small = true; + } + } + } } else if (abs(npos - rpos) < rdbdpos) too_small = true; @@ -2257,6 +2318,9 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) /* Check for soft-travel limit violation */ if ((pmr->dhlm == pmr->dllm) && (pmr->dllm == 0.0)) pmr->lvio = false; + /* At least one limit is violated when DLLM > DHLM */ + else if (pmr->dllm > pmr->dhlm) + pmr->lvio = true; /* LVIO = TRUE, AND, Move request towards valid travel limit range. */ else if (((pmr->dval > pmr->dhlm) && (pmr->dval < pmr->ldvl)) || ((pmr->dval < pmr->dllm) && (pmr->dval > pmr->ldvl))) @@ -2272,9 +2336,23 @@ static RTN_STATUS do_work(motorRecord * pmr, CALLBACK_VALUE proc_ind) } } + if (pmr->urip == motorUEIP_Yes) + { + double test_drbv; + rtnstat = dbGetLink(&(pmr->rdbl), DBR_DOUBLE, &test_drbv, 0, 0 ); + if (RTN_SUCCESS(rtnstat)) + rtnstat = TRUE; + else + rtnstat = FALSE; + } + else + rtnstat = TRUE; + if (pmr->lvio != old_lvio) MARK(M_LVIO); - if (pmr->lvio) + + /* Test for travel limit violation, OR, URIP is True, but CA server is disconnected.*/ + if (pmr->lvio || rtnstat == FALSE) { pmr->val = pmr->lval; MARK(M_VAL); @@ -2824,10 +2902,32 @@ static long special(DBADDR *paddr, int after) /* new ueip flag */ case motorRecordUEIP: - MARK(M_UEIP); - /* Ideally, we should be recalculating speeds, but at the moment */ - /* we don't know whether hardware even has an encoder. */ - break; + if (pmr->ueip == motorUEIP_Yes) + { + if (msta.Bits.EA_PRESENT) + { + if (pmr->urip == motorUEIP_Yes) + { + pmr->urip = motorUEIP_No; /* Set URIP = No, if UEIP = Yes. */ + db_post_events(pmr, &pmr->urip, DBE_VAL_LOG); + } + } + else + { + pmr->ueip = motorUEIP_No; /* Override UEIP = Yes if EA_PRESENT is false. */ + MARK(M_UEIP); + } + } + break; + + /* new urip flag */ + case motorRecordURIP: + if ((pmr->urip == motorUEIP_Yes) && (pmr->ueip == motorUEIP_Yes)) + { + pmr->ueip = motorUEIP_No; /* Set UEIP = No, if URIP = Yes. */ + MARK(M_UEIP); + } + break; /* Set to SET mode */ case motorRecordSSET: @@ -3023,7 +3123,7 @@ static long special(DBADDR *paddr, int after) /****************************************************************************** get_units() *******************************************************************************/ -static long get_units(const DBADDR *paddr, char *units) +static long get_units(DBADDR *paddr, char *units) { motorRecord *pmr = (motorRecord *) paddr->precord; int siz = dbr_units_size - 1; /* "dbr_units_size" from dbAccess.h */ @@ -3080,7 +3180,7 @@ static long get_units(const DBADDR *paddr, char *units) /****************************************************************************** get_graphic_double() *******************************************************************************/ -static long get_graphic_double(const DBADDR *paddr, struct dbr_grDouble * pgd) +static long get_graphic_double(DBADDR *paddr, struct dbr_grDouble * pgd) { motorRecord *pmr = (motorRecord *) paddr->precord; int fieldIndex = dbGetFieldIndex(paddr); @@ -3131,7 +3231,7 @@ static long get_graphic_double(const DBADDR *paddr, struct dbr_grDouble * pgd) get_control_double() *******************************************************************************/ static long - get_control_double(const DBADDR *paddr, struct dbr_ctrlDouble * pcd) + get_control_double(DBADDR *paddr, struct dbr_ctrlDouble * pcd) { motorRecord *pmr = (motorRecord *) paddr->precord; int fieldIndex = dbGetFieldIndex(paddr); @@ -3211,7 +3311,7 @@ static long get_precision(const DBADDR *paddr, long *precision) /****************************************************************************** get_alarm_double() *******************************************************************************/ -static long get_alarm_double(const DBADDR *paddr, struct dbr_alDouble * pad) +static long get_alarm_double(DBADDR *paddr, struct dbr_alDouble * pad) { motorRecord *pmr = (motorRecord *) paddr->precord; int fieldIndex = dbGetFieldIndex(paddr); @@ -3244,7 +3344,8 @@ static void alarm_sub(motorRecord * pmr) status = recGblSetSevr((dbCommon *) pmr, UDF_ALARM, INVALID_ALARM); return; } - /* limit-switch and soft-limit violations */ + /* Limit-switch and soft-limit violations. Consider limit switches also if not in + * direction of move (limit hit by externally triggered move)*/ if (pmr->hlsv && (pmr->hls || (pmr->dval > pmr->dhlm))) { status = recGblSetSevr((dbCommon *) pmr, HIGH_ALARM, pmr->hlsv); @@ -3514,8 +3615,7 @@ static void monitor(motorRecord * pmr) /****************************************************************************** process_motor_info() *******************************************************************************/ -static void - process_motor_info(motorRecord * pmr, bool initcall) +static void process_motor_info(motorRecord * pmr, bool initcall) { double old_drbv = pmr->drbv; double old_rbv = pmr->rbv; @@ -3533,17 +3633,39 @@ static void /* Calculate raw and dial readback values. */ msta.All = pmr->msta; - if (msta.Bits.EA_PRESENT && pmr->ueip) + if (pmr->ueip == motorUEIP_Yes) { /* An encoder is present and the user wants us to use it. */ pmr->rrbv = pmr->rep; pmr->drbv = pmr->rrbv * pmr->eres; } - else + else if (pmr->urip == motorUEIP_Yes && initcall == false) { - pmr->rrbv = pmr->rmp; - if (pmr->urip == motorUEIP_No || initcall == true) + double rdblvalue; + long rtnstat; + + rtnstat = dbGetLink(&(pmr->rdbl), DBR_DOUBLE, &rdblvalue, 0, 0 ); + if (!RTN_SUCCESS(rtnstat)) + { + Debug(3, "process_motor_info: error reading RDBL link.\n"); + if (pmr->mip != MIP_DONE) + { + /* Error reading RDBL - stop move. */ + clear_buttons(pmr); + pmr->stop = 1; + MARK(M_STOP); + } + } + else + { + pmr->rrbv = NINT((rdblvalue * pmr->rres) / pmr->mres); pmr->drbv = pmr->rrbv * pmr->mres; + } + } + else /* UEIP = URIP = No */ + { + pmr->rrbv = pmr->rmp; + pmr->drbv = pmr->rrbv * pmr->mres; } if (pmr->rrbv != old_rrbv) @@ -3561,11 +3683,12 @@ static void if (pmr->tdir != old_tdir) MARK(M_TDIR); - /* Get states of high, low limit switches. */ - pmr->rhls = (msta.Bits.RA_PLUS_LS) && pmr->cdir; - pmr->rlls = (msta.Bits.RA_MINUS_LS) && !pmr->cdir; + /* Get states of high, low limit switches. State is independent of direction. */ + pmr->rhls = (msta.Bits.RA_PLUS_LS); + pmr->rlls = (msta.Bits.RA_MINUS_LS); - ls_active = (pmr->rhls || pmr->rlls) ? true : false; + /* Treat limit switch active only when it is pressed and in direction of movement. */ + ls_active = ((pmr->rhls && pmr->cdir) || (pmr->rlls && !pmr->cdir)) ? true : false; pmr->hls = ((pmr->dir == motorDIR_Pos) == (pmr->mres >= 0)) ? pmr->rhls : pmr->rlls; pmr->lls = ((pmr->dir == motorDIR_Pos) == (pmr->mres >= 0)) ? pmr->rlls : pmr->rhls; @@ -3581,11 +3704,6 @@ static void if (ls_active == true || msta.Bits.RA_PROBLEM) { clear_buttons(pmr); - if (msta.Bits.RA_PROBLEM) - { - pmr->stop = 1; - MARK(M_STOP); - } } } else @@ -3595,7 +3713,7 @@ static void MARK(M_MOVN); /* Get state of motor's or encoder's home switch. */ - if (msta.Bits.EA_PRESENT && pmr->ueip) + if (pmr->ueip) pmr->athm = (msta.Bits.EA_HOME) ? 1 : 0; else pmr->athm = (msta.Bits.RA_HOME) ? 1 : 0; @@ -3603,32 +3721,6 @@ static void if (pmr->athm != old_athm) MARK(M_ATHM); - - /* - * If we've got an external readback device, get Dial readback from it, and - * propagate to User readback. We do this after motor and encoder readbacks - * have been read and propagated to .rbv in case .rdbl is a link involving - * that field. - */ - if (pmr->urip && initcall == false) - { - long rtnstat; - - old_drbv = pmr->drbv; - rtnstat = dbGetLink(&(pmr->rdbl), DBR_DOUBLE, &(pmr->drbv), 0, 0 ); - if (!RTN_SUCCESS(rtnstat)) - pmr->drbv = old_drbv; - else - { - pmr->drbv *= pmr->rres; - pmr->rbv = pmr->drbv * dir + pmr->off; - if (pmr->drbv != old_drbv) - { - MARK(M_DRBV); - MARK(M_RBV); - } - } - } pmr->diff = pmr->dval - pmr->drbv; MARK(M_DIFF); pmr->rdif = NINT(pmr->diff / pmr->mres); @@ -4029,22 +4121,39 @@ static void syncTargetPosition(motorRecord *pmr) { int dir = (pmr->dir == motorDIR_Pos) ? 1 : -1; msta_field msta; + double rdblvalue; + long rtnstat; msta.All = pmr->msta; - if (msta.Bits.EA_PRESENT && pmr->ueip) + if (pmr->ueip) { /* An encoder is present and the user wants us to use it. */ pmr->rrbv = pmr->rep; pmr->drbv = pmr->rrbv * pmr->eres; } + else if (pmr->urip) + { + /* user wants us to use the readback link */ + rtnstat = dbGetLink(&(pmr->rdbl), DBR_DOUBLE, &rdblvalue, 0, 0 ); + if (!RTN_SUCCESS(rtnstat)) + printf("%s: syncTargetPosition: error reading RDBL link.\n", pmr->name); + else + { + pmr->rrbv = NINT((rdblvalue * pmr->rres) / pmr->mres); + pmr->drbv = pmr->rrbv * pmr->mres; + } + } else { pmr->rrbv = pmr->rmp; pmr->drbv = pmr->rrbv * pmr->mres; } + MARK(M_RRBV); + MARK(M_DRBV); pmr->rbv = pmr->drbv * dir + pmr->off; - + MARK(M_RBV); + pmr->val = pmr->lval = pmr->rbv ; MARK(M_VAL); pmr->dval = pmr->ldvl = pmr->drbv; diff --git a/motorApp/MotorSrc/motorRecord.dbd b/motorApp/MotorSrc/motorRecord.dbd index 00c173f..0e2d11c 100644 --- a/motorApp/MotorSrc/motorRecord.dbd +++ b/motorApp/MotorSrc/motorRecord.dbd @@ -1,9 +1,5 @@ # FILENAME... motorRecord.dbd -# Version: $Revision: 16592 $ -# Modified By: $Author: sluiter $ -# Last Modified: $Date: 2013-06-17 09:31:34 -0500 (Mon, 17 Jun 2013) $ -# HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/MotorSrc/motorRecord.dbd $ # Experimental Physics and Industrial Control System (EPICS) @@ -290,6 +286,7 @@ recordtype(motor) { field(URIP,DBF_MENU) { prompt("Use RDBL Link If Presen") promptgroup(GUI_COMMON) + special(SPC_MOD) pp(TRUE) interest(1) menu(motorUEIP) @@ -418,6 +415,12 @@ recordtype(motor) { special(SPC_MOD) interest(1) } + field(SPDB,DBF_DOUBLE) { + prompt("Setpoint Deadband (EGU)") + promptgroup(GUI_COMMON) + special(SPC_MOD) + interest(1) + } field(RCNT,DBF_SHORT) { prompt("Retry count") special(SPC_NOMOD) @@ -791,4 +794,8 @@ recordtype(motor) { pp(TRUE) interest(1) } + field(IGSET,DBF_SHORT) { + prompt("Ignore SET field") + interest(2) + } } diff --git a/motorApp/MotorSrc/motorUtil.cc b/motorApp/MotorSrc/motorUtil.cc index 9cfc600..aa8bc6f 100644 --- a/motorApp/MotorSrc/motorUtil.cc +++ b/motorApp/MotorSrc/motorUtil.cc @@ -2,10 +2,6 @@ FILENAME... motorUtil.cc USAGE... Motor Record Utility Support. -Version: $Revision: 17100 $ -Modified By: $Author: kpetersn $ -Last Modified: $Date: 2013-11-13 15:43:36 -0600 (Wed, 13 Nov 2013) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/MotorSrc/motorUtil.cc $ */ diff --git a/motorApp/MotorSrc/motorUtilAux.cc b/motorApp/MotorSrc/motorUtilAux.cc index 20c9464..fef1690 100644 --- a/motorApp/MotorSrc/motorUtilAux.cc +++ b/motorApp/MotorSrc/motorUtilAux.cc @@ -2,10 +2,6 @@ FILENAME... motorUtilAux.cc USAGE... Motor Record Utility Support. -Version: $Revision: 15395 $ -Modified By: $Author: kpetersn $ -Last Modified: $Date: 2012-10-24 17:30:31 -0500 (Wed, 24 Oct 2012) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/MotorSrc/motorUtilAux.cc $ */ /* @@ -33,6 +29,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- */ #include +#include "motor_epics_inc.h" + #include #include diff --git a/motorApp/MotorSrc/motor_epics_inc.h b/motorApp/MotorSrc/motor_epics_inc.h new file mode 100644 index 0000000..0d4698c --- /dev/null +++ b/motorApp/MotorSrc/motor_epics_inc.h @@ -0,0 +1,33 @@ +#ifndef INCmotorepicsinc +#define INCmotorepicsinc 1 + +#include "epicsVersion.h" + +#ifndef VERSION_INT +# define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P)) +#endif + +#define VERSION_INT_3_16 VERSION_INT(3,16,0,0) +#if EPICS_VERSION_INT < VERSION_INT_3_16 +#define RECSUPFUN_CAST (RECSUPFUN) +#else +#define RECSUPFUN_CAST +#define REC_TYPE motorRecord +#define USE_TYPED_RSET +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* !! for callocMustSucceed() */ +#include +#include + +#endif diff --git a/motorApp/MotorSrc/motordevCom.cc b/motorApp/MotorSrc/motordevCom.cc index 291bff3..b82bc8f 100644 --- a/motorApp/MotorSrc/motordevCom.cc +++ b/motorApp/MotorSrc/motordevCom.cc @@ -3,10 +3,6 @@ FILENAME: motordevCom.cc USAGE... This file contains device functions that are common to all motor record device support modules. -Version: $Revision: 17842 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2014-09-11 10:28:26 -0500 (Thu, 11 Sep 2014) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/MotorSrc/motordevCom.cc $ */ /* @@ -59,18 +55,15 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- * .13 06/09/10 rls Set RA_PROBLEM instead of CNTRL_COMM_ERR when a NULL * motor_state[] ptr is detected in motor_end_trans_com(). * .14 08/19/14 rls Moved RMP and REP posting from record to here. + * .15 07/29/15 rls Added "Use Relative" (use_rel) indicator to "init_pos" logic in + * motor_init_record_com(). See README R6-10 item #6 for details. */ #include #include #include -#include -#include -#include -#include -#include -#include +#include "motor_epics_inc.h" #include "motorRecord.h" #include "motor.h" @@ -159,9 +152,9 @@ LOGIC... Set local encoder ratio to unity. ENDIF - Set Initialize position indicator based on (|DVAL| > RDBD, AND, MRES != 0, - AND, the above |"get_axis_info()" position| < RDBD) [NOTE: |controller - position| >= RDBD takes precedence over save/restore position]. + Set Initialize position indicator based on (Use Relative Moves indicator == TRUE, OR, + [|DVAL| > RDBD, AND, MRES != 0, AND, the above |"get_axis_info()" position| < RDBD)] + [NOTE: |controller position| >= RDBD takes precedence over save/restore position]. Set Command Primitive Initialization string indicator based on (non-NULL "init" pointer, AND, non-zero string length. @@ -203,6 +196,7 @@ motor_init_record_com(struct motorRecord *mr, int brdcnt, struct driver_table *t double ep_mp[2]; /* encoder pulses, motor pulses */ int rtnStat; msta_field msta; + bool use_rel = (mr->rtry != 0 && mr->rmod != motorRMOD_I && (mr->ueip || mr->urip)); /* allocate space for private field - an motor_trans structure */ mr->dpvt = (struct motor_trans *) malloc(sizeof(struct motor_trans)); @@ -294,9 +288,9 @@ motor_init_record_com(struct motorRecord *mr, int brdcnt, struct driver_table *t else ep_mp[0] = ep_mp[1] = 1.0; - initPos = (fabs(mr->dval) > mr->rdbd && mr->mres != 0 && - fabs(axis_query.position * mr->mres) < mr->rdbd) - ? true : false; + initPos = ((use_rel == true) || + (fabs(mr->dval) > mr->rdbd && mr->mres != 0 && fabs(axis_query.position * mr->mres) < mr->rdbd) + ) ? true : false; /* Test for command primitive initialization string. */ initString = (mr->init != NULL && strlen(mr->init)) ? true : false; /* Test for PID support. */ @@ -463,9 +457,9 @@ epicsShareFunc long motor_start_trans_com(struct motorRecord *mr, struct board_s motor_call->signal = axis; motor_call->type = UNDEFINED; motor_call->mrecord = (struct dbCommon *) mr; - motor_call->message[0] = (char) NULL; - motor_call->postmsgptr = (char) NULL; - motor_call->termstring = (char) NULL; + motor_call->message[0] = (char) NULL; + motor_call->postmsgptr = (char*) NULL; + motor_call->termstring = (char*) NULL; return (0); } diff --git a/motorApp/MotorSrc/motordevCom.h b/motorApp/MotorSrc/motordevCom.h index 72018dd..67c81a4 100644 --- a/motorApp/MotorSrc/motordevCom.h +++ b/motorApp/MotorSrc/motordevCom.h @@ -3,10 +3,6 @@ FILENAME... motordevCom.h USAGE... This file contains definitions and structures that are common to all motor record device support modules. -Version: $Revision: 16591 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2013-06-17 09:23:05 -0500 (Mon, 17 Jun 2013) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/MotorSrc/motordevCom.h $ */ /* diff --git a/motorApp/MotorSrc/motordrvCom.cc b/motorApp/MotorSrc/motordrvCom.cc index b6f18a0..b032382 100644 --- a/motorApp/MotorSrc/motordrvCom.cc +++ b/motorApp/MotorSrc/motordrvCom.cc @@ -3,10 +3,6 @@ FILENAME... motordrvCom.cc USAGE... This file contains driver functions that are common to all motor record driver modules. -Version: $Revision: 17309 $ -Modified By: $Author: mooney $ -Last Modified: $Date: 2014-04-02 12:52:06 -0500 (Wed, 02 Apr 2014) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/MotorSrc/motordrvCom.cc $ */ /* @@ -60,6 +56,7 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#include #include "motor.h" diff --git a/motorApp/MotorSrc/motordrvCom.h b/motorApp/MotorSrc/motordrvCom.h index 31f4c36..c2351f5 100644 --- a/motorApp/MotorSrc/motordrvCom.h +++ b/motorApp/MotorSrc/motordrvCom.h @@ -4,10 +4,6 @@ FILENAME... motordrvCom.h USAGE... This file contains definitions and structures that are common to all motor record driver support modules. -Version: $Revision: 16591 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2013-06-17 09:23:05 -0500 (Mon, 17 Jun 2013) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/MotorSrc/motordrvCom.h $ */ /* diff --git a/motorApp/MotorSrc/motordrvComCode.h b/motorApp/MotorSrc/motordrvComCode.h index 7641c7c..775d6f5 100644 --- a/motorApp/MotorSrc/motordrvComCode.h +++ b/motorApp/MotorSrc/motordrvComCode.h @@ -4,10 +4,6 @@ USAGE... This file contains local variables that are allocated in each motor record driver. The variables are allocated in each driver by including this file. -Version: $Revision: 16591 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2013-06-17 09:23:05 -0500 (Mon, 17 Jun 2013) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/MotorSrc/motordrvComCode.h $ */ /* diff --git a/motorApp/NewFocusSrc/874xMotorDriver.cpp b/motorApp/NewFocusSrc/874xMotorDriver.cpp new file mode 100644 index 0000000..c3130d9 --- /dev/null +++ b/motorApp/NewFocusSrc/874xMotorDriver.cpp @@ -0,0 +1,349 @@ +/* +FILENAME... 874xMotorDriver.cpp +USAGE... Motor driver support for the NewFocus 874x series motor controller + +Based on ACRMotorDriver.cpp by: +Mark Rivers +March 4, 2011 + +== Modifications == +2015-12-01 - Wayne Lewis - Modify for NewFocus 874x series +*/ + +/* + * TODO: Extend for 8743 closed loop functionality + */ + +#include +#include +#include + +#include +#include + +#include + +#include "asynMotorController.h" +#include "asynMotorAxis.h" + +#include +#include "874xMotorDriver.h" + +static const char *driverName = "nf874xMotorDriver"; + +/** Creates a new nf874xController object. + * \param[in] portName The name of the asyn port that will be created for this driver + * \param[in] nf874xPortName The name of the drvAsynIPPPort that was created previously to connect to the nf874x controller + * \param[in] numAxes The number of axes that this controller supports. Create one extra axis to allow for base 1 indexing of NewFocus controllers. + * \param[in] movingPollPeriod The time between polls when any axis is moving + * \param[in] idlePollPeriod The time between polls when no axis is moving + */ +nf874xController::nf874xController(const char *portName, const char *nf874xPortName, int numAxes, + double movingPollPeriod, double idlePollPeriod) + //: asynMotorController(portName, numAxes, NUM_nf874x_PARAMS, + : asynMotorController(portName, numAxes+1, 0, + asynUInt32DigitalMask, + asynUInt32DigitalMask, + ASYN_CANBLOCK | ASYN_MULTIDEVICE, + 1, // autoconnect + 0, 0) // Default priority and stack size +{ + int axis; + asynStatus status; + static const char *functionName = "nf874xController"; + + /* Connect to nf874x controller */ + status = pasynOctetSyncIO->connect(nf874xPortName, 0, &pasynUserController_, NULL); + if (status) { + asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, + "%s:%s: cannot connect to nf874x controller\n", + driverName, functionName); + } + epicsThreadSleep(0.5); + // Create the axis objects + // Axis 0 will remain unused. This allows consistent axis numbering with + // NewFocus convention. + for (axis=1; axis<=numAxes; axis++) { + new nf874xAxis(this, axis); + } + + startPoller(movingPollPeriod, idlePollPeriod, 2); +} + + +/** Creates a new nf874xController object. + * Configuration command, called directly or from iocsh + * \param[in] portName The name of the asyn port that will be created for this driver + * \param[in] nf874xPortName The name of the drvAsynIPPPort that was created previously to connect to the nf874x controller + * \param[in] numAxes The number of axes that this controller supports. + * \param[in] movingPollPeriod The time in ms between polls when any axis is moving + * \param[in] idlePollPeriod The time in ms between polls when no axis is moving + */ +extern "C" int nf874xCreateController(const char *portName, const char *nf874xPortName, int numAxes, + int movingPollPeriod, int idlePollPeriod) +{ + new nf874xController(portName, nf874xPortName, numAxes, movingPollPeriod/1000., idlePollPeriod/1000.); + return(asynSuccess); +} + +/** Reports on status of the driver + * \param[in] fp The file pointer on which report information will be written + * \param[in] level The level of report detail desired + * + * If details > 0 then information is printed about each axis. + * After printing controller-specific information calls asynMotorController::report() + */ +void nf874xController::report(FILE *fp, int level) +{ + fprintf(fp, "nf874x motor driver %s, numAxes=%d, moving poll period=%f, idle poll period=%f\n", + this->portName, numAxes_, movingPollPeriod_, idlePollPeriod_); + + // Call the base class method + asynMotorController::report(fp, level); +} + +/** Returns a pointer to an nf874xMotorAxis object. + * Returns NULL if the axis number encoded in pasynUser is invalid. + * \param[in] pasynUser asynUser structure that encodes the axis index number. */ +nf874xAxis* nf874xController::getAxis(asynUser *pasynUser) +{ + return static_cast(asynMotorController::getAxis(pasynUser)); +} + +/** Returns a pointer to an nf874xMotorAxis object. + * Returns NULL if the axis number encoded in pasynUser is invalid. + * \param[in] axisNo Axis index number. */ +nf874xAxis* nf874xController::getAxis(int axisNo) +{ + return static_cast(asynMotorController::getAxis(axisNo)); +} + + +/** Called when asyn clients call pasynInt32->write(). + * Extracts the function and axis number from pasynUser. + * Sets the value in the parameter library. + * For all other functions it calls asynMotorController::writeInt32. + * Calls any registered callbacks for this pasynUser->reason and address. + * \param[in] pasynUser asynUser structure that encodes the reason and address. + * \param[in] value Value to write. */ +asynStatus nf874xController::writeInt32(asynUser *pasynUser, epicsInt32 value) +{ + int function = pasynUser->reason; + asynStatus status = asynSuccess; + nf874xAxis *pAxis = getAxis(pasynUser); + static const char *functionName = "writeInt32"; + + /* Set the parameter and readback in the parameter library. This may be overwritten when we read back the + * status at the end, but that's OK */ + status = setIntegerParam(pAxis->axisNo_, function, value); + + status = asynMotorController::writeInt32(pasynUser, value); + + /* Do callbacks so higher layers see any changes */ + callParamCallbacks(pAxis->axisNo_); + if (status) + asynPrint(pasynUser, ASYN_TRACE_ERROR, + "%s:%s: error, status=%d function=%d, value=%d\n", + driverName, functionName, status, function, value); + else + asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, + "%s:%s: function=%d, value=%d\n", + driverName, functionName, function, value); + return status; +} + +/** Called when asyn clients call pasynFloat64->write(). + * Extracts the function and axis number from pasynUser. + * Sets the value in the parameter library. + * Calls any registered callbacks for this pasynUser->reason and address. + * For all other functions it calls asynMotorController::writeFloat64. + * \param[in] pasynUser asynUser structure that encodes the reason and address. + * \param[in] value Value to write. */ +asynStatus nf874xController::writeFloat64(asynUser *pasynUser, epicsFloat64 value) +{ + int function = pasynUser->reason; + asynStatus status = asynSuccess; + nf874xAxis *pAxis = getAxis(pasynUser); + static const char *functionName = "writeFloat64"; + + + /* Set the parameter and readback in the parameter library. */ + status = setDoubleParam(pAxis->axisNo_, function, value); + + status = asynMotorController::writeFloat64(pasynUser, value); + + /* Do callbacks so higher layers see any changes */ + pAxis->callParamCallbacks(); + if (status) + asynPrint(pasynUser, ASYN_TRACE_ERROR, + "%s:%s: error, status=%d function=%d, value=%f\n", + driverName, functionName, status, function, value); + else + asynPrint(pasynUser, ASYN_TRACEIO_DRIVER, + "%s:%s: function=%d, value=%f\n", + driverName, functionName, function, value); + return status; +} + +// These are the nf874xAxis methods + +/** Creates a new nf874xAxis object. + * \param[in] pC Pointer to the nf874xController to which this axis belongs. + * \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1. + * + * Initializes register numbers, etc. + */ +nf874xAxis::nf874xAxis(nf874xController *pC, int axisNo) + : asynMotorAxis(pC, axisNo), + pC_(pC) +{ + sprintf(axisName_, "%d", axisNo); +} + +/** Reports on status of the driver + * \param[in] fp The file pointer on which report information will be written + * \param[in] level The level of report detail desired + * + * If details > 0 then information is printed about each axis. + * After printing controller-specific information calls asynMotorController::report() + */ +void nf874xAxis::report(FILE *fp, int level) +{ + if (level > 0) { + fprintf(fp, " axis %d\n", axisNo_ ); + } + + // Call the base class method + asynMotorAxis::report(fp, level); +} + + +asynStatus nf874xAxis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration) +{ + asynStatus status; + + sprintf(pC_->outString_, "%s AC %f", axisName_, acceleration); + status = pC_->writeController(); + sprintf(pC_->outString_, "%s VA %f", axisName_, maxVelocity); + status = pC_->writeController(); + if (relative) { + sprintf(pC_->outString_, "%s PR %f", axisName_, position); + status = pC_->writeController(); + } else { + sprintf(pC_->outString_, "%s PA %f", axisName_, position); + status = pC_->writeController(); + } + return status; +} + +asynStatus nf874xAxis::home(double minVelocity, double maxVelocity, double acceleration, int forwards) +{ + asynStatus status; + + sprintf(pC_->outString_, "%s AC %f", axisName_, acceleration); + status = pC_->writeController(); + sprintf(pC_->outString_, "%s VA %f", axisName_, acceleration); + status = pC_->writeController(); + sprintf(pC_->outString_, "%s DH", axisName_); + status = pC_->writeController(); + return status; +} + +asynStatus nf874xAxis::moveVelocity(double minVelocity, double maxVelocity, double acceleration) +{ + asynStatus status; + double speed=maxVelocity; + int forwards=1; + + if (speed < 0) { + speed = -speed; + forwards = 0; + } + sprintf(pC_->outString_, "%s AC %f", axisName_, acceleration); + status = pC_->writeController(); + sprintf(pC_->outString_, "%s VA %f", axisName_, speed); + status = pC_->writeController(); + sprintf(pC_->outString_, "%s MV %s", axisName_, forwards ? "+" : "-"); + status = pC_->writeController(); + return status; +} + +asynStatus nf874xAxis::stop(double acceleration ) +{ + asynStatus status; + + sprintf(pC_->outString_, "%s ST", axisName_); + status = pC_->writeController(); + return status; +} + +asynStatus nf874xAxis::setPosition(double position) +{ + asynStatus status; + + sprintf(pC_->outString_, "%s DH %f", axisName_, position); + status = pC_->writeController(); + return status; +} + +/** Polls the axis. + * This function reads the controller position, encoder position, the limit status, the moving status, + * and the drive power-on status. It does not current detect following error, etc. but this could be + * added. + * It calls setIntegerParam() and setDoubleParam() for each item that it polls, + * and then calls callParamCallbacks() at the end. + * \param[out] moving A flag that is set indicating that the axis is moving (1) or done (0). */ +asynStatus nf874xAxis::poll(bool *moving) +{ + int done; + asynStatus comStatus; + + // Read the current encoder position + sprintf(pC_->outString_, "%s TP?", axisName_); + comStatus = pC_->writeReadController(); + if (comStatus) goto skip; + encoderPosition_ = atof(pC_->inString_); + setDoubleParam(pC_->motorEncoderPosition_,encoderPosition_); + + // Read the current theoretical position + setDoubleParam(pC_->motorPosition_, encoderPosition_); + + // Read the current moving status + sprintf(pC_->outString_, "%s MD?", axisName_); + comStatus = pC_->writeReadController(); + if (comStatus) goto skip; + done = atoi(pC_->inString_); + setIntegerParam(pC_->motorStatusDone_, done); + *moving = done ? false:true; + + skip: + setIntegerParam(pC_->motorStatusProblem_, comStatus ? 1:0); + callParamCallbacks(); + return comStatus ? asynError : asynSuccess; +} + +/** Code for iocsh registration */ +static const iocshArg nf874xCreateControllerArg0 = {"Port name", iocshArgString}; +static const iocshArg nf874xCreateControllerArg1 = {"nf874x port name", iocshArgString}; +static const iocshArg nf874xCreateControllerArg2 = {"Number of axes", iocshArgInt}; +static const iocshArg nf874xCreateControllerArg3 = {"Moving poll period (ms)", iocshArgInt}; +static const iocshArg nf874xCreateControllerArg4 = {"Idle poll period (ms)", iocshArgInt}; +static const iocshArg * const nf874xCreateControllerArgs[] = {&nf874xCreateControllerArg0, + &nf874xCreateControllerArg1, + &nf874xCreateControllerArg2, + &nf874xCreateControllerArg3, + &nf874xCreateControllerArg4}; +static const iocshFuncDef nf874xCreateControllerDef = {"nf874xCreateController", 5, nf874xCreateControllerArgs}; +static void nf874xCreateContollerCallFunc(const iocshArgBuf *args) +{ + nf874xCreateController(args[0].sval, args[1].sval, args[2].ival, args[3].ival, args[4].ival); +} + +static void nf874xMotorRegister(void) +{ + iocshRegister(&nf874xCreateControllerDef, nf874xCreateContollerCallFunc); +} + +extern "C" { +epicsExportRegistrar(nf874xMotorRegister); +} diff --git a/motorApp/NewFocusSrc/874xMotorDriver.h b/motorApp/NewFocusSrc/874xMotorDriver.h new file mode 100644 index 0000000..7692925 --- /dev/null +++ b/motorApp/NewFocusSrc/874xMotorDriver.h @@ -0,0 +1,50 @@ +/* +FILENAME... 874xMotorDriver.h +USAGE... Motor driver support for the NewFocus 874x series of controllers + +Based on ACRMotorDriver.h by: +Mark Rivers +March 28, 2011 + +== Modifications == +2015-12-01 - Wayne Lewis - Modify for NewFocus 874x controllers +*/ + +#include "asynMotorController.h" +#include "asynMotorAxis.h" + +class epicsShareClass nf874xAxis : public asynMotorAxis +{ +public: + /* These are the methods we override from the base class */ + nf874xAxis(class nf874xController *pC, int axis); + void report(FILE *fp, int level); + asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration); + asynStatus moveVelocity(double min_velocity, double max_velocity, double acceleration); + asynStatus home(double min_velocity, double max_velocity, double acceleration, int forwards); + asynStatus stop(double acceleration); + asynStatus poll(bool *moving); + asynStatus setPosition(double position); + +private: + nf874xController *pC_; /**< Pointer to the asynMotorController to which this axis belongs. + * Abbreviated because it is used very frequently */ + char axisName_[10]; /**< Name of each axis, used in commands to nf874x controller */ + double encoderPosition_; /**< Cached copy of the encoder position */ + +friend class nf874xController; +}; + +class epicsShareClass nf874xController : public asynMotorController { +public: + nf874xController(const char *portName, const char *nf874xPortName, int numAxes, double movingPollPeriod, double idlePollPeriod); + + /* These are the methods that we override from asynMotorDriver */ + asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); + asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value); + void report(FILE *fp, int level); + nf874xAxis* getAxis(asynUser *pasynUser); + nf874xAxis* getAxis(int axisNo); + +friend class nf874xAxis; +}; diff --git a/motorApp/NewFocusSrc/Makefile b/motorApp/NewFocusSrc/Makefile index f98bdf6..bc5cf8e 100644 --- a/motorApp/NewFocusSrc/Makefile +++ b/motorApp/NewFocusSrc/Makefile @@ -11,10 +11,13 @@ DBD += devNewFocus.dbd LIBRARY_IOC = NewFocus -SRCS += NewFocusRegister.cc +NewFocus_SRCS += NewFocusRegister.cc # PMNC87xx (i.e., PMNC87xx) device driver. -SRCS += devPMNC87xx.cc drvPMNC87xx.cc +NewFocus_SRCS += devPMNC87xx.cc drvPMNC87xx.cc + +# NewFocus 874x driver +NewFocus_SRCS += 874xMotorDriver.cpp NewFocus_LIBS += motor asyn NewFocus_LIBS += $(EPICS_BASE_IOC_LIBS) diff --git a/motorApp/NewFocusSrc/devNewFocus.dbd b/motorApp/NewFocusSrc/devNewFocus.dbd index e188256..d9c6e6e 100644 --- a/motorApp/NewFocusSrc/devNewFocus.dbd +++ b/motorApp/NewFocusSrc/devNewFocus.dbd @@ -4,3 +4,6 @@ driver(drvPMNC87xx) registrar(NewFocusRegister) variable(drvPMNC87xxdebug) +# NewFocus 874x controller support +registrar(nf874xMotorRegister) + diff --git a/motorApp/NewFocusSrc/devPMNC87xx.cc b/motorApp/NewFocusSrc/devPMNC87xx.cc index 25430bf..b293e8c 100644 --- a/motorApp/NewFocusSrc/devPMNC87xx.cc +++ b/motorApp/NewFocusSrc/devPMNC87xx.cc @@ -44,6 +44,8 @@ Last Modified: 2004/12/20 21:10:53 #include +#include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -57,7 +59,7 @@ extern struct driver_table PMNC87xx_access; /* ----------------Create the dsets for devPMNC87xx----------------- */ /* static long report(); */ STATIC struct driver_table *drvtabptr; -STATIC long PMNC87xx_init(void *); +STATIC long PMNC87xx_init(int); STATIC long PMNC87xx_init_record(void *); STATIC long PMNC87xx_start_trans(struct motorRecord *); STATIC RTN_STATUS PMNC87xx_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -111,12 +113,11 @@ static struct board_stat **PMNC87xx_cards; /* initialize device support for PMNC87xx stepper motor */ -STATIC long PMNC87xx_init(void *arg) +STATIC long PMNC87xx_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &PMNC87xx_access; (drvtabptr->init)(); diff --git a/motorApp/NewFocusSrc/drvPMNC87xx.cc b/motorApp/NewFocusSrc/drvPMNC87xx.cc index 800d51c..fb5c45f 100644 --- a/motorApp/NewFocusSrc/drvPMNC87xx.cc +++ b/motorApp/NewFocusSrc/drvPMNC87xx.cc @@ -66,6 +66,8 @@ Last Modified: 2005/03/30 19:10:48 #include #include #include +#include +#include #include "NewFocusRegister.h" #include "drvPMNCCom.h" #include "asynOctetSyncIO.h" diff --git a/motorApp/NewportSrc/AG_CONEX.cpp b/motorApp/NewportSrc/AG_CONEX.cpp index 8f016a2..04af446 100644 --- a/motorApp/NewportSrc/AG_CONEX.cpp +++ b/motorApp/NewportSrc/AG_CONEX.cpp @@ -1,6 +1,6 @@ /* FILENAME... AG_CONEX.cpp -USAGE... Motor driver support for the Newport CONEX-AGP and CONEX-CC series controllers. +USAGE... Motor driver support for the Newport CONEX-AGP, CONEX-CC and CONEX-PP series controllers. Mark Rivers April 11, 2013 @@ -29,6 +29,9 @@ April 11, 2013 #define CONEX_TIMEOUT 2.0 #define LINUX_WRITE_DELAY 0.1 +// We force minus end-of-run home type for Conex-PP for now +#define HOME_TYPE_MINUS_EOR 4 + /** Creates a new AG_CONEXController object. * \param[in] portName The name of the asyn port that will be created for this driver * \param[in] serialPortName The name of the drvAsynSerialPort that was created previously to connect to the CONEX controller @@ -169,7 +172,7 @@ AG_CONEXAxis* AG_CONEXController::getAxis(int axisNo) AG_CONEXAxis::AG_CONEXAxis(AG_CONEXController *pC) : asynMotorAxis(pC, 0), pC_(pC), - currentPosition_(0.), positionOffset_(0.) + currentPosition_(0.) { static const char *functionName = "AG_CONEXAxis::AG_CONEXAxis"; @@ -186,6 +189,9 @@ AG_CONEXAxis::AG_CONEXAxis(AG_CONEXController *pC) KIMax_ = 1.e6; KDMax_ = 1.e6; } + else if (strstr(pC->controllerVersion_, "Conex PP")) { + conexModel_ = ModelConexPP; + } else { asynPrint(pC->pasynUserSelf, ASYN_TRACE_ERROR, "%s: unknown model, firmware string=%s\n", @@ -196,12 +202,16 @@ AG_CONEXAxis::AG_CONEXAxis(AG_CONEXController *pC) // Read the stage ID sprintf(pC_->outString_, "%dID?", pC->controllerID_); pC_->writeReadController(); - strcpy(stageID_, &pC_->inString_[4]); + strcpy(stageID_, &pC_->inString_[3]); - // Read the encoder increment - sprintf(pC_->outString_, "%dSU?", pC->controllerID_); - pC_->writeReadController(); - encoderIncrement_ = atof(&pC_->inString_[3]); + // Read the encoder increment (CC and AGP only) + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + sprintf(pC_->outString_, "%dSU?", pC->controllerID_); + pC_->writeReadController(); + encoderIncrement_ = atof(&pC_->inString_[3]); + } else { + encoderIncrement_ = 1.; + } // Read the interpolation factor (AGP only) if (conexModel_ == ModelConexAGP) { @@ -212,8 +222,21 @@ AG_CONEXAxis::AG_CONEXAxis(AG_CONEXController *pC) interpolationFactor_ = 1.; } + if (conexModel_ == ModelConexPP) { + sprintf(pC_->outString_, "%dFRM?", pC->controllerID_); + pC_->writeReadController(); + microStepsPerFullStep_ = atoi(&pC_->inString_[4]); + sprintf(pC_->outString_, "%dFRS?", pC->controllerID_); + pC_->writeReadController(); + fullStepSize_ = atof(&pC_->inString_[4]); + } + // Compute the minimum step size - stepSize_ = encoderIncrement_ / interpolationFactor_; + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + stepSize_ = encoderIncrement_ / interpolationFactor_; + } else { + stepSize_ = fullStepSize_ / microStepsPerFullStep_ / 1000.; + } // Read the low and high software limits sprintf(pC_->outString_, "%dSL?", pC->controllerID_); @@ -223,8 +246,10 @@ AG_CONEXAxis::AG_CONEXAxis(AG_CONEXController *pC) pC_->writeReadController(); highLimit_ = atof(&pC_->inString_[3]); - // Tell the motor record that we have an gain supprt - setIntegerParam(pC_->motorStatusGainSupport_, 1); + // Tell the motor record that we have an gain support (CC and AGP only) + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + setIntegerParam(pC_->motorStatusGainSupport_, 1); + } } /** Reports on status of the axis @@ -236,32 +261,36 @@ AG_CONEXAxis::AG_CONEXAxis(AG_CONEXController *pC) void AG_CONEXAxis::report(FILE *fp, int level) { if (level > 0) { - // Read KOP, KI, LF - sprintf(pC_->outString_, "%dKP?", pC_->controllerID_); - pC_->writeReadController(); - KP_ = atof(&pC_->inString_[3]); - sprintf(pC_->outString_, "%dKI?", pC_->controllerID_); - pC_->writeReadController(); - KI_ = atof(&pC_->inString_[3]); - if (conexModel_ == ModelConexAGP) { - sprintf(pC_->outString_, "%dLF?", pC_->controllerID_); + // Read KOP, KI, LF (CC and AGP only) + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + sprintf(pC_->outString_, "%dKP?", pC_->controllerID_); pC_->writeReadController(); - LF_ = atof(&pC_->inString_[3]); - } else if (conexModel_ == ModelConexCC) { - sprintf(pC_->outString_, "%dKD?", pC_->controllerID_); + KP_ = atof(&pC_->inString_[3]); + sprintf(pC_->outString_, "%dKI?", pC_->controllerID_); pC_->writeReadController(); - KD_ = atof(&pC_->inString_[3]); - LF_ = KD_; // For printout below + KI_ = atof(&pC_->inString_[3]); + if (conexModel_ == ModelConexAGP) { + sprintf(pC_->outString_, "%dLF?", pC_->controllerID_); + pC_->writeReadController(); + LF_ = atof(&pC_->inString_[3]); + } else if (conexModel_ == ModelConexCC) { + sprintf(pC_->outString_, "%dKD?", pC_->controllerID_); + pC_->writeReadController(); + KD_ = atof(&pC_->inString_[3]); + LF_ = KD_; // For printout below + } } fprintf(fp, " stageID=%s\n" - " currentPosition=%f, positionOffset=%f, encoderIncrement=%f\n" + " currentPosition=%f, encoderIncrement=%f\n" " interpolationFactor=%f, stepSize=%f, lowLimit=%f, highLimit=%f\n" - " KP=%f, KI=%f, KD/LF=%f\n", + " KP=%f, KI=%f, KD/LF=%f\n" + " fullStepSize=%f, microStepsPerFullStep=%d\n", stageID_, - currentPosition_, positionOffset_, encoderIncrement_, + currentPosition_, encoderIncrement_, interpolationFactor_, stepSize_, lowLimit_, highLimit_, - KP_, KI_, LF_); + KP_, KI_, LF_, + fullStepSize_, microStepsPerFullStep_); } // Call the base class method @@ -273,8 +302,8 @@ asynStatus AG_CONEXAxis::move(double position, int relative, double minVelocity, asynStatus status; // static const char *functionName = "AG_CONEXAxis::move"; - // The CONEX-CC supports velocity and acceleration, the CONEX-AGP does not - if (conexModel_ == ModelConexCC) { + // The CONEX-CC and CONEX-PP support velocity and acceleration, the CONEX-AGP does not + if ((conexModel_ == ModelConexCC) || (conexModel_ == ModelConexPP)) { sprintf(pC_->outString_, "%dAC%f", pC_->controllerID_, acceleration*stepSize_); status = pC_->writeCONEX(); sprintf(pC_->outString_, "%dVA%f", pC_->controllerID_, maxVelocity*stepSize_); @@ -284,7 +313,7 @@ asynStatus AG_CONEXAxis::move(double position, int relative, double minVelocity, if (relative) { sprintf(pC_->outString_, "%dPR%f", pC_->controllerID_, position*stepSize_); } else { - sprintf(pC_->outString_, "%dPA%f", pC_->controllerID_, (position-positionOffset_)*stepSize_); + sprintf(pC_->outString_, "%dPA%f", pC_->controllerID_, position*stepSize_); } status = pC_->writeCONEX(); return status; @@ -304,6 +333,14 @@ asynStatus AG_CONEXAxis::home(double minVelocity, double maxVelocity, double acc // and writing to non-volatile memory with the OH command. // This is time-consuming and can only be done a limited number of times so we don't do it here. + // The CONEX-PP supports home velocity and home type. We force negative limit switch home type. + if (conexModel_ == ModelConexPP) { + sprintf(pC_->outString_, "%dOH%f", pC_->controllerID_, maxVelocity); + status = pC_->writeCONEX(); + sprintf(pC_->outString_, "%dHT%d", pC_->controllerID_, HOME_TYPE_MINUS_EOR); + status = pC_->writeCONEX(); + } + sprintf(pC_->outString_, "%dOR", pC_->controllerID_); status = pC_->writeCONEX(); return status; @@ -338,7 +375,6 @@ asynStatus AG_CONEXAxis::setPosition(double position) { //static const char *functionName = "AG_CONEXAxis::setPosition"; - positionOffset_ = position - currentPosition_; return asynSuccess; } @@ -368,52 +404,58 @@ asynStatus AG_CONEXAxis::getClosedLoop(bool *closedLoop) asynStatus AG_CONEXAxis::setPGain(double pGain) { - asynStatus status; + asynStatus status = asynSuccess; bool closedLoop; //static const char *functionName = "AG_CONEXAxis::setPGain"; - getClosedLoop(&closedLoop); - setClosedLoop(false); - // The pGain value from the motor record is between 0 and 1. - sprintf(pC_->outString_, "%dKP%f", pC_->controllerID_, pGain*KPMax_); - status = pC_->writeCONEX(); - if (closedLoop) setClosedLoop(true); + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + getClosedLoop(&closedLoop); + setClosedLoop(false); + // The pGain value from the motor record is between 0 and 1. + sprintf(pC_->outString_, "%dKP%f", pC_->controllerID_, pGain*KPMax_); + status = pC_->writeCONEX(); + if (closedLoop) setClosedLoop(true); + } return status; } asynStatus AG_CONEXAxis::setIGain(double iGain) { - asynStatus status; + asynStatus status = asynSuccess; bool closedLoop; //static const char *functionName = "AG_CONEXAxis::setIGain"; - getClosedLoop(&closedLoop); - setClosedLoop(false); - // The iGain value from the motor record is between 0 and 1. - sprintf(pC_->outString_, "%dKI%f", pC_->controllerID_, iGain*KIMax_); - status = pC_->writeCONEX(); - if (closedLoop) setClosedLoop(true); + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + getClosedLoop(&closedLoop); + setClosedLoop(false); + // The iGain value from the motor record is between 0 and 1. + sprintf(pC_->outString_, "%dKI%f", pC_->controllerID_, iGain*KIMax_); + status = pC_->writeCONEX(); + if (closedLoop) setClosedLoop(true); + } return status; } asynStatus AG_CONEXAxis::setDGain(double dGain) { - asynStatus status; + asynStatus status = asynSuccess; bool closedLoop; //static const char *functionName = "AG_CONEXAxis::setPGain"; - getClosedLoop(&closedLoop); - setClosedLoop(false); - if (conexModel_ == ModelConexCC) { - // The dGain value from the motor record is between 0 and 1. - sprintf(pC_->outString_, "%dKI%f", pC_->controllerID_, dGain*KDMax_); - } else if (conexModel_ == ModelConexAGP) { - // We are using the DGain for the Low pass filter frequency. - // DGain value is between 0 and 1 - sprintf(pC_->outString_, "%dLF%f", pC_->controllerID_, dGain*LFMax_); + if ((conexModel_ == ModelConexAGP) || (conexModel_ == ModelConexCC)) { + getClosedLoop(&closedLoop); + setClosedLoop(false); + if (conexModel_ == ModelConexCC) { + // The dGain value from the motor record is between 0 and 1. + sprintf(pC_->outString_, "%dKI%f", pC_->controllerID_, dGain*KDMax_); + } else if (conexModel_ == ModelConexAGP) { + // We are using the DGain for the Low pass filter frequency. + // DGain value is between 0 and 1 + sprintf(pC_->outString_, "%dLF%f", pC_->controllerID_, dGain*LFMax_); + } + status = pC_->writeCONEX(); + if (closedLoop) setClosedLoop(true); } - status = pC_->writeCONEX(); - if (closedLoop) setClosedLoop(true); return status; } @@ -440,7 +482,7 @@ asynStatus AG_CONEXAxis::poll(bool *moving) if (comStatus) goto skip; // The response string is of the form "1TPxxx" position = atof(&pC_->inString_[3]); - currentPosition_ = (position + positionOffset_)/stepSize_; + currentPosition_ = position /stepSize_; setDoubleParam(pC_->motorPosition_, currentPosition_); // Read the moving status of this motor @@ -456,10 +498,10 @@ asynStatus AG_CONEXAxis::poll(bool *moving) setIntegerParam(pC_->motorStatusDone_, done); *moving = done ? false:true; - // The meaning of the error bits is different for the CC and AGP - if (conexModel_ == ModelConexCC) { - if (status & 0x100) lowLimit = 1; - if (status & 0x200) highLimit = 1; + // The meaning of the error bits is different for the CC, AGP, and PP + if ((conexModel_ == ModelConexCC) || (conexModel_ == ModelConexPP)) { + if (status & 0x100) lowLimit = 1; + if (status & 0x200) highLimit = 1; } setIntegerParam(pC_->motorStatusLowLimit_, lowLimit); diff --git a/motorApp/NewportSrc/AG_CONEX.h b/motorApp/NewportSrc/AG_CONEX.h index fba951f..f5ffbdf 100644 --- a/motorApp/NewportSrc/AG_CONEX.h +++ b/motorApp/NewportSrc/AG_CONEX.h @@ -12,7 +12,8 @@ April 11, 2013 typedef enum { ModelConexAGP, - ModelConexCC + ModelConexCC, + ModelConexPP } ConexModel_t; // No controller-specific parameters yet @@ -40,10 +41,11 @@ class epicsShareClass AG_CONEXAxis : public asynMotorAxis * Abbreviated because it is used very frequently */ asynStatus getClosedLoop(bool *closedLoop); double currentPosition_; - double positionOffset_; double encoderIncrement_; double interpolationFactor_; double stepSize_; + double fullStepSize_; + int microStepsPerFullStep_; double highLimit_; double lowLimit_; double KP_; diff --git a/motorApp/NewportSrc/HXPDriver.cpp b/motorApp/NewportSrc/HXPDriver.cpp index 418944e..a6f5646 100644 --- a/motorApp/NewportSrc/HXPDriver.cpp +++ b/motorApp/NewportSrc/HXPDriver.cpp @@ -20,9 +20,9 @@ Note: This driver was tested with the v1.3.x of the firmware #include "asynMotorController.h" #include "asynMotorAxis.h" -#include "hxp_drivers.h" #include +#include "hxp_drivers.h" #include "HXPDriver.h" #define NINT(f) (int)((f)>0 ? (f)+0.5 : (f)-0.5) diff --git a/motorApp/NewportSrc/Makefile b/motorApp/NewportSrc/Makefile index 211ea12..87aca9a 100644 --- a/motorApp/NewportSrc/Makefile +++ b/motorApp/NewportSrc/Makefile @@ -14,6 +14,9 @@ USR_CPPFLAGS_Linux += -Wno-write-strings INC += XPS_C8_drivers.h DBD += devNewport.dbd +ifdef SNCSEQ +DBD += devNewportSeq.dbd +endif LIBRARY_IOC = Newport diff --git a/motorApp/NewportSrc/NewportRegister.cc b/motorApp/NewportSrc/NewportRegister.cc index 7fc41f2..92390af 100644 --- a/motorApp/NewportSrc/NewportRegister.cc +++ b/motorApp/NewportSrc/NewportRegister.cc @@ -2,9 +2,6 @@ FILENAME... NewportRegister.cc USAGE... Register Newport motor device driver shell commands. -Version: $Revision: 1.13 $ -Modified By: $Author: rivers $ -Last Modified: $Date: 2006-06-15 19:02:59 $ */ /***************************************************************** diff --git a/motorApp/NewportSrc/NewportRegister.h b/motorApp/NewportSrc/NewportRegister.h index f781060..d3d36a5 100644 --- a/motorApp/NewportSrc/NewportRegister.h +++ b/motorApp/NewportSrc/NewportRegister.h @@ -2,9 +2,6 @@ FILENAME... NewportRegister.h USAGE... This file contains function prototypes for Newport IOC shell commands. -Version: $Revision: 1.11 $ -Modified By: $Author: rivers $ -Last Modified: $Date: 2006-06-15 19:04:58 $ */ /* diff --git a/motorApp/NewportSrc/SMC100Driver.cpp b/motorApp/NewportSrc/SMC100Driver.cpp index 4fdcb22..05e9ef0 100644 --- a/motorApp/NewportSrc/SMC100Driver.cpp +++ b/motorApp/NewportSrc/SMC100Driver.cpp @@ -23,6 +23,9 @@ K. Goetze 2012-03-23 Initial version #include +#include +#include + #include #include "SMC100Driver.h" diff --git a/motorApp/NewportSrc/SMC100Register.cc b/motorApp/NewportSrc/SMC100Register.cc index 3796d68..103d1fd 100644 --- a/motorApp/NewportSrc/SMC100Register.cc +++ b/motorApp/NewportSrc/SMC100Register.cc @@ -2,9 +2,6 @@ FILENAME... SMC100Register.cc USAGE... Register SMC100 motor device driver shell commands. -Version: $Revision: 1.4 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2004-07-16 19:06:58 $ */ /***************************************************************** diff --git a/motorApp/NewportSrc/SMC100Register.h b/motorApp/NewportSrc/SMC100Register.h index 9c0e506..e0f6bab 100644 --- a/motorApp/NewportSrc/SMC100Register.h +++ b/motorApp/NewportSrc/SMC100Register.h @@ -2,9 +2,6 @@ FILENAME... SMC100Register.h USAGE... This file contains function prototypes for SMC100 IOC shell commands. -Version: $Revision: 1.3 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2004-07-16 19:06:58 $ */ /* diff --git a/motorApp/NewportSrc/XPSAxis.cpp b/motorApp/NewportSrc/XPSAxis.cpp index e1b0edb..4eb3bcb 100644 --- a/motorApp/NewportSrc/XPSAxis.cpp +++ b/motorApp/NewportSrc/XPSAxis.cpp @@ -2,10 +2,6 @@ FILENAME... XPSMotorDriver.cpp USAGE... Newport XPS EPICS asyn motor device driver -Version: $Revision: 19717 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2009-12-09 10:21:24 -0600 (Wed, 09 Dec 2009) $ -HeadURL: $URL: https://subversion.xor.aps.anl.gov/synApps/trunk/support/motor/vstub/motorApp/NewportSrc/XPSMotorDriver.cpp $ */ /* @@ -96,10 +92,10 @@ using std::endl; #include "asynMotorController.h" #include "asynMotorAxis.h" +#include #include "XPSController.h" #include "XPS_C8_drivers.h" #include "asynOctetSocket.h" -#include #include "XPSAxis.h" #define XPSC8_END_OF_RUN_MINUS 0x80000100 @@ -360,6 +356,8 @@ asynStatus XPSAxis::home(double min_velocity, double max_velocity, double accele } moving_ = true; + setIntegerParam(pC_->motorStatusProblem_, 0); + return asynSuccess; } @@ -567,8 +565,8 @@ asynStatus XPSAxis::poll(bool *moving) &axisStatus_); if (!status) { status = GroupStatusStringGet(pollSocket_, - axisStatus_, - statusString); + axisStatus_, + statusString); } if (status) { asynPrint(pasynUser_, ASYN_TRACE_ERROR, @@ -606,17 +604,17 @@ asynStatus XPSAxis::poll(bool *moving) if (moving_) { status = ReadXPSSocket(moveSocket_, readResponse, sizeof(readResponse), 0); if (status < 0) { - asynPrint(pasynUser_, ASYN_TRACE_ERROR, - "%s:%s: [%s,%d]: error calling ReadXPSSocket status=%d\n", - driverName, functionName, pC_->portName, axisNo_, status); - goto done; + asynPrint(pasynUser_, ASYN_TRACE_ERROR, + "%s:%s: [%s,%d]: error calling ReadXPSSocket status=%d\n", + driverName, functionName, pC_->portName, axisNo_, status); + goto done; } if (status > 0) { - asynPrint(pasynUser_, ASYN_TRACE_FLOW, - "%s:%s: [%s,%d]: readXPSSocket returned nRead=%d, [%s]\n", - driverName, functionName, pC_->portName, axisNo_, status, readResponse); - status = 0; - moving_ = false; + asynPrint(pasynUser_, ASYN_TRACE_FLOW, + "%s:%s: [%s,%d]: readXPSSocket returned nRead=%d, [%s]\n", + driverName, functionName, pC_->portName, axisNo_, status, readResponse); + status = 0; + moving_ = false; } } } @@ -870,6 +868,227 @@ asynStatus XPSAxis::setClosedLoop(bool closedLoop) return (asynStatus)status; } +double XPSAxis::motorRecPositionToXPSPosition(double motorRecPosition) +{ + int direction; + double offset, resolution, XPSPosition; + + pC_->getDoubleParam (axisNo_, pC_->motorRecResolution_, &resolution); + pC_->getDoubleParam (axisNo_, pC_->motorRecOffset_, &offset); + pC_->getIntegerParam(axisNo_, pC_->motorRecDirection_, &direction); + + if (direction != 0) resolution = -resolution; + if (resolution == 0) resolution = 1; + XPSPosition = (motorRecPosition - offset) / resolution * stepSize_; + return XPSPosition; +} + +double XPSAxis::XPSPositionToMotorRecPosition(double XPSPosition) +{ + int direction; + double offset, resolution, motorRecPosition; + + pC_->getDoubleParam (axisNo_, pC_->motorRecResolution_, &resolution); + pC_->getDoubleParam (axisNo_, pC_->motorRecOffset_, &offset); + pC_->getIntegerParam(axisNo_, pC_->motorRecDirection_, &direction); + + if (direction != 0) resolution = -resolution; + if (stepSize_ == 0) stepSize_ = 1; + motorRecPosition = XPSPosition * resolution / stepSize_ + offset; + return motorRecPosition; +} + +double XPSAxis::motorRecStepToXPSStep(double motorRecStep) +{ + int direction; + double resolution, XPSStep; + + pC_->getDoubleParam (axisNo_, pC_->motorRecResolution_, &resolution); + pC_->getIntegerParam(axisNo_, pC_->motorRecDirection_, &direction); + + if (direction != 0) resolution = -resolution; + if (resolution == 0) resolution = 1; + XPSStep = motorRecStep / resolution * stepSize_; + return XPSStep; +} + +double XPSAxis::XPSStepToMotorRecStep(double XPSStep) +{ + int direction; + double resolution, motorRecStep; + + pC_->getDoubleParam (axisNo_, pC_->motorRecResolution_, &resolution); + pC_->getIntegerParam(axisNo_, pC_->motorRecDirection_, &direction); + + if (direction != 0) resolution = -resolution; + if (stepSize_ == 0) stepSize_ = 1; + motorRecStep = XPSStep * resolution / stepSize_; + return motorRecStep; +} + +asynStatus XPSAxis::setPositionCompare() +{ + int mode; + double minPosition, maxPosition, stepSize, pulseWidth, settlingTime; + int itemp; + int direction; + int status; + static const char *functionName = "setPositionCompare"; + + pC_->getIntegerParam(axisNo_, pC_->XPSPositionCompareMode_, &mode); + pC_->getDoubleParam (axisNo_, pC_->XPSPositionCompareMinPosition_, &minPosition); + pC_->getDoubleParam (axisNo_, pC_->XPSPositionCompareMaxPosition_, &maxPosition); + pC_->getDoubleParam (axisNo_, pC_->XPSPositionCompareStepSize_, &stepSize); + pC_->getIntegerParam(axisNo_, pC_->XPSPositionComparePulseWidth_, &itemp); + pulseWidth = positionComparePulseWidths[itemp]; + pC_->getIntegerParam(axisNo_, pC_->XPSPositionCompareSettlingTime_, &itemp); + settlingTime = positionCompareSettlingTimes[itemp]; + + // minPosition and maxPosition are in motor record units. Convert to XPS units + minPosition = motorRecPositionToXPSPosition(minPosition); + maxPosition = motorRecPositionToXPSPosition(maxPosition); + stepSize = fabs(motorRecStepToXPSStep(stepSize)); + + // Swap max and min positions if needed + pC_->getIntegerParam(axisNo_, pC_->motorRecDirection_, &direction); + if (direction != 0) { + double temp=maxPosition; + maxPosition = minPosition; + minPosition = temp; + } + + // Disable the position compare so we can set parameters + status = PositionerPositionCompareDisable(pollSocket_, positionerName_); + if (status) { + asynPrint(pasynUser_, ASYN_TRACE_ERROR, + "%s:%s: [%s,%d]: error calling PositionerPositionCompareDisable status=%d\n", + driverName, functionName, pC_->portName, axisNo_, status); + return asynError; + } + status = PositionerPositionComparePulseParametersSet(pollSocket_, positionerName_, pulseWidth, settlingTime); + if (status) { + asynPrint(pasynUser_, ASYN_TRACE_ERROR, + "%s:%s: [%s,%d]: error calling PositionerPositionComparePulseParametersSet" + " status=%d, pulseWidth=%f, settlingTime=%f\n", + driverName, functionName, pC_->portName, axisNo_, status, pulseWidth, settlingTime); + return asynError; + } + switch (mode) { + case XPSPositionCompareModeDisable: + break; + + case XPSPositionCompareModePulse: + status = PositionerPositionCompareSet(pollSocket_, positionerName_, minPosition, maxPosition, stepSize); + if (status) { + asynPrint(pasynUser_, ASYN_TRACE_ERROR, + "%s:%s: [%s,%d]: error calling PositionerPositionCompareSet" + " status=%d, minPosition=%f, maxPosition=%f, stepSize=%f\n", + driverName, functionName, pC_->portName, axisNo_, status, minPosition, maxPosition, stepSize); + return asynError; + } + status = PositionerPositionCompareEnable(pollSocket_, positionerName_); + if (status) { + asynPrint(pasynUser_, ASYN_TRACE_ERROR, + "%s:%s: [%s,%d]: error calling PositionerPositionCompareEnable status=%d\n", + driverName, functionName, pC_->portName, axisNo_, status); + return asynError; + } + break; + + case XPSPositionCompareModeAquadBWindowed: + status = PositionerPositionCompareAquadBWindowedSet(pollSocket_, positionerName_, minPosition, maxPosition); + if (status) { + asynPrint(pasynUser_, ASYN_TRACE_ERROR, + "%s:%s: [%s,%d]: error calling PositionerPositionCompareAquadBWindowedSet" + " status=%d, minPosition=%f, maxPosition=%f\n", + driverName, functionName, pC_->portName, axisNo_, status, minPosition, maxPosition); + return asynError; + } + status = PositionerPositionCompareEnable(pollSocket_, positionerName_); + if (status) { + asynPrint(pasynUser_, ASYN_TRACE_ERROR, + "%s:%s: [%s,%d]: error calling PositionerPositionCompareEnable status=%d\n", + driverName, functionName, pC_->portName, axisNo_, status); + return asynError; + } + break; + + case XPSPositionCompareModeAquadBAlways: + status = PositionerPositionCompareAquadBAlwaysEnable(pollSocket_, positionerName_); + if (status) { + asynPrint(pasynUser_, ASYN_TRACE_ERROR, + "%s:%s: [%s,%d]: error calling PositionerPositionCompareAquadBAlwaysEnable status=%d\n", + driverName, functionName, pC_->portName, axisNo_, status); + return asynError; + } + break; + } + + asynPrint(pasynUser_, ASYN_TRACE_FLOW, + "%s:%s: set XPS %s, axis %d positionCompare set and enable\n", + driverName, functionName, pC_->portName, axisNo_); + + return asynSuccess; +} + +asynStatus XPSAxis::getPositionCompare() +{ + bool enable; + int status; + int i; + int direction; + double minPosition=0, maxPosition=0, stepSize=0, pulseWidth, settlingTime; + static const char *functionName = "getPositionCompare"; + + pC_->getIntegerParam(axisNo_, pC_->motorRecDirection_, &direction); + + status = PositionerPositionComparePulseParametersGet(pollSocket_, positionerName_, &pulseWidth, &settlingTime); + if (status) { + asynPrint(pasynUser_, ASYN_TRACE_ERROR, + "%s:%s: [%s,%d]: error calling PositionerPositionComparePulseParametersGet status=%d\n", + driverName, functionName, pC_->portName, axisNo_, status); + return asynError; + } + status = PositionerPositionCompareGet(pollSocket_, positionerName_, &minPosition, &maxPosition, &stepSize, &enable); + if (status == 0) { + // Swap max and min positions if needed + if (direction != 0) { + double temp=maxPosition; + maxPosition = minPosition; + minPosition = temp; + } +// setDoubleParam(pC_->XPSPositionCompareMinPosition_, XPSPositionToMotorRecPosition(minPosition)); +// setDoubleParam(pC_->XPSPositionCompareMaxPosition_, XPSPositionToMotorRecPosition(maxPosition)); + setDoubleParam(pC_->XPSPositionCompareStepSize_, fabs(XPSStepToMotorRecStep(stepSize))); + } + status = PositionerPositionCompareAquadBWindowedGet(pollSocket_, positionerName_, &minPosition, &maxPosition, &enable); + if (status == 0) { + // Swap max and min positions if needed + if (direction != 0) { + double temp=maxPosition; + maxPosition = minPosition; + minPosition = temp; + } +// setDoubleParam(pC_->XPSPositionCompareMinPosition_, XPSPositionToMotorRecPosition(minPosition)); +// setDoubleParam(pC_->XPSPositionCompareMaxPosition_, XPSPositionToMotorRecPosition(maxPosition)); + } + asynPrint(pasynUser_, ASYN_TRACE_FLOW, + "%s:%s: set XPS %s, axis %d " + " enable=%d, minPosition=%f, maxPosition=%f, stepSize=%f, pulseWidth=%f, settlingTime=%f\n", + driverName, functionName, pC_->portName, axisNo_, + enable, minPosition, maxPosition, stepSize, pulseWidth, settlingTime); + + for (i=0; iXPSPositionComparePulseWidth_, i); + for (i=0; iXPSPositionCompareSettlingTime_, i); + return asynSuccess; +} + char *XPSAxis::getXPSError(int status, char *buffer) { status = ErrorStringGet(pollSocket_, status, buffer); diff --git a/motorApp/NewportSrc/XPSAxis.h b/motorApp/NewportSrc/XPSAxis.h index 44a684f..2a04fd5 100644 --- a/motorApp/NewportSrc/XPSAxis.h +++ b/motorApp/NewportSrc/XPSAxis.h @@ -48,6 +48,8 @@ class epicsShareClass XPSAxis : public asynMotorAxis asynStatus setIGain(double gain); asynStatus setDGain(double gain); asynStatus setClosedLoop(bool closedLoop); + asynStatus setPositionCompare(); + asynStatus getPositionCompare(); virtual asynStatus defineProfile(double *positions, size_t numPoints); virtual asynStatus readbackProfile(); @@ -58,7 +60,11 @@ class epicsShareClass XPSAxis : public asynMotorAxis int isInGroup(); asynStatus setPID(const double * value, int pidoption); asynStatus getPID(); - asynStatus setPIDValue(const double * value, int pidoption); + asynStatus setPIDValue(const double * value, int pidoption); + double motorRecPositionToXPSPosition(double motorRecPosition); + double XPSPositionToMotorRecPosition(double XPSPosition); + double motorRecStepToXPSStep(double motorRecStep); + double XPSStepToMotorRecStep(double XPSStep); /* Wrapper functions for the verbose PositionerCorrector functions. */ asynStatus PositionerCorrectorPIPositionGet(); diff --git a/motorApp/NewportSrc/XPSController.cpp b/motorApp/NewportSrc/XPSController.cpp index 9e67142..4ab26be 100644 --- a/motorApp/NewportSrc/XPSController.cpp +++ b/motorApp/NewportSrc/XPSController.cpp @@ -2,10 +2,6 @@ FILENAME... XPSMotorDriver.cpp USAGE... Newport XPS EPICS asyn motor device driver -Version: $Revision: 19717 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2009-12-09 10:21:24 -0600 (Wed, 09 Dec 2009) $ -HeadURL: $URL: https://subversion.xor.aps.anl.gov/synApps/trunk/support/motor/vstub/motorApp/NewportSrc/XPSMotorDriver.cpp $ */ /* @@ -91,14 +87,14 @@ Versions: Release 4-5 and higher. #include #include -#include "XPS_C8_drivers.h" -#include "xps_ftp.h" #include "asynMotorController.h" #include "asynMotorAxis.h" -#include "XPSAxis.h" #include #include "XPSController.h" +#include "XPS_C8_drivers.h" +#include "xps_ftp.h" +#include "XPSAxis.h" static const char *driverName = "XPSController"; @@ -159,18 +155,24 @@ XPSController::XPSController(const char *portName, const char *IPAddress, int IP movesDeferred_ = false; // Create controller-specific parameters - createParam(XPSMinJerkString, asynParamFloat64, &XPSMinJerk_); - createParam(XPSMaxJerkString, asynParamFloat64, &XPSMaxJerk_); - createParam(XPSProfileMaxVelocityString, asynParamFloat64, &XPSProfileMaxVelocity_); - createParam(XPSProfileMaxAccelerationString, asynParamFloat64, &XPSProfileMaxAcceleration_); - createParam(XPSProfileMinPositionString, asynParamFloat64, &XPSProfileMinPosition_); - createParam(XPSProfileMaxPositionString, asynParamFloat64, &XPSProfileMaxPosition_); - createParam(XPSProfileGroupNameString, asynParamOctet, &XPSProfileGroupName_); - createParam(XPSTrajectoryFileString, asynParamOctet, &XPSTrajectoryFile_); - createParam(XPSStatusString, asynParamInt32, &XPSStatus_); - createParam(XPSStatusStringString, asynParamOctet, &XPSStatusString_); - createParam(XPSTclScriptString, asynParamOctet, &XPSTclScript_); - createParam(XPSTclScriptExecuteString, asynParamInt32, &XPSTclScriptExecute_); + createParam(XPSMinJerkString, asynParamFloat64, &XPSMinJerk_); + createParam(XPSMaxJerkString, asynParamFloat64, &XPSMaxJerk_); + createParam(XPSPositionCompareModeString, asynParamInt32, &XPSPositionCompareMode_); + createParam(XPSPositionCompareMinPositionString, asynParamFloat64, &XPSPositionCompareMinPosition_); + createParam(XPSPositionCompareMaxPositionString, asynParamFloat64, &XPSPositionCompareMaxPosition_); + createParam(XPSPositionCompareStepSizeString, asynParamFloat64, &XPSPositionCompareStepSize_); + createParam(XPSPositionComparePulseWidthString, asynParamInt32, &XPSPositionComparePulseWidth_); + createParam(XPSPositionCompareSettlingTimeString, asynParamInt32, &XPSPositionCompareSettlingTime_); + createParam(XPSProfileMaxVelocityString, asynParamFloat64, &XPSProfileMaxVelocity_); + createParam(XPSProfileMaxAccelerationString, asynParamFloat64, &XPSProfileMaxAcceleration_); + createParam(XPSProfileMinPositionString, asynParamFloat64, &XPSProfileMinPosition_); + createParam(XPSProfileMaxPositionString, asynParamFloat64, &XPSProfileMaxPosition_); + createParam(XPSProfileGroupNameString, asynParamOctet, &XPSProfileGroupName_); + createParam(XPSTrajectoryFileString, asynParamOctet, &XPSTrajectoryFile_); + createParam(XPSStatusString, asynParamInt32, &XPSStatus_); + createParam(XPSStatusStringString, asynParamOctet, &XPSStatusString_); + createParam(XPSTclScriptString, asynParamOctet, &XPSTclScript_); + createParam(XPSTclScriptExecuteString, asynParamInt32, &XPSTclScriptExecute_); // This socket is used for polling by the controller and all axes pollSocket_ = TCP_ConnectToServer((char *)IPAddress, IPPort, XPS_POLL_TIMEOUT); @@ -261,31 +263,75 @@ asynStatus XPSController::writeInt32(asynUser *pasynUser, epicsInt32 value) getStringParam(XPSTclScript_, (int)sizeof(fileName), fileName); if (fileName != NULL) { asynPrint(this->pasynUserSelf, ASYN_TRACE_FLOW, - "Executing TCL script %s on XPS: %s\n", - fileName, this->portName); + "Executing TCL script %s on XPS: %s\n", + fileName, this->portName); status = TCLScriptExecute(pAxis->moveSocket_, - fileName,"0","0"); + fileName,"0","0"); if (status != 0) { - asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, - "TCLScriptExecute returned error %d, on XPS: %s\n", - status, this->portName); - status = asynError; + asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, + "TCLScriptExecute returned error %d, on XPS: %s\n", + status, this->portName); + status = asynError; } } else { asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR, - "TCL script name has not been set on XPS: %s\n", - this->portName); + "TCL script name has not been set on XPS: %s\n", + this->portName); status = asynError; } + + } else if ((function == XPSPositionCompareMode_) || + (function == XPSPositionComparePulseWidth_) || + (function == XPSPositionCompareStepSize_)) { + status = pAxis->setPositionCompare(); + status = pAxis->getPositionCompare(); + } else { /* Call base class method */ status = asynMotorController::writeInt32(pasynUser, value); } + /* Do callbacks so higher layers see any changes */ + pAxis->callParamCallbacks(); + return (asynStatus)status; } +/** Called when asyn clients call pasynFloat64->write(). + * \param[in] pasynUser asynUser structure that encodes the reason and address. + * \param[in] value Value to write. */ +asynStatus XPSController::writeFloat64(asynUser *pasynUser, epicsFloat64 value) +{ + int function = pasynUser->reason; + XPSAxis *pAxis; + asynStatus status = asynError; + //static const char *functionName = "writeFloat64"; + + pAxis = getAxis(pasynUser); + if (!pAxis) return asynError; + + /* Set the parameter and readback in the parameter library. */ + status = pAxis->setDoubleParam(function, value); + + if ((function == XPSPositionCompareMinPosition_) || + (function == XPSPositionCompareMaxPosition_) || + (function == XPSPositionCompareStepSize_)) { + status = pAxis->setPositionCompare(); + status = pAxis->getPositionCompare(); + + } else { + /* Call base class method */ + status = asynMotorController::writeFloat64(pasynUser, value); + + } + /* Do callbacks so higher layers see any changes */ + pAxis->callParamCallbacks(); + + return status; + +} + /** * Perform a deferred move (a coordinated group move) on all the axes in a group. * @param groupName Pointer to string naming the group on which to perform the group move. @@ -484,6 +530,7 @@ asynStatus XPSController::initializeProfile(size_t maxPoints, const char* ftpUse asynStatus XPSController::buildProfile() { FILE *trajFile; + char *trajectoryDirectory; int i, j; int status; bool buildOK=true; @@ -641,6 +688,7 @@ asynStatus XPSController::buildProfile() if (!inGroup[j]) continue; fprintf(trajFile,", %f, %f", pAxes_[j]->profilePostDistance_, 0.); } + fprintf(trajFile,"\n"); fclose (trajFile); /* FTP the trajectory file from the local directory to the XPS */ @@ -650,7 +698,16 @@ asynStatus XPSController::buildProfile() sprintf(message, "Error calling ftpConnect, status=%d\n", status); goto done; } - status = ftpChangeDir(ftpSocket, TRAJECTORY_DIRECTORY); + if (strstr(firmwareVersion_, "C8")) { + trajectoryDirectory = XPS_C8_TRAJECTORY_DIRECTORY; + } else if (strstr(firmwareVersion_, "Q8")) { + trajectoryDirectory = XPS_Q8_TRAJECTORY_DIRECTORY; + } else { + buildOK = false; + sprintf(message, "Firmware version does not contain C8 or Q8=%s\n", firmwareVersion_); + goto done; + } + status = ftpChangeDir(ftpSocket, trajectoryDirectory); if (status) { buildOK = false; sprintf(message, "Error calling ftpChangeDir, status=%d\n", status); diff --git a/motorApp/NewportSrc/XPSController.h b/motorApp/NewportSrc/XPSController.h index fab77d0..9451192 100644 --- a/motorApp/NewportSrc/XPSController.h +++ b/motorApp/NewportSrc/XPSController.h @@ -16,24 +16,42 @@ USAGE... Newport XPS EPICS asyn motor device driver #define XPS_MIN_PROFILE_ACCEL_TIME 0.25 /* Constants used for FTP to the XPS */ -#define TRAJECTORY_DIRECTORY "/Admin/Public/Trajectories" +#define XPS_C8_TRAJECTORY_DIRECTORY "/Admin/Public/Trajectories" +#define XPS_Q8_TRAJECTORY_DIRECTORY "/Public/Trajectories" #define MAX_FILENAME_LEN 256 #define MAX_MESSAGE_LEN 256 #define MAX_GROUPNAME_LEN 64 +#define MAX_PULSE_WIDTHS 4 +#define MAX_SETTLING_TIMES 4 +static const double positionComparePulseWidths[MAX_PULSE_WIDTHS] = {0.2, 1.0, 2.5, 10.0}; +static const double positionCompareSettlingTimes[MAX_SETTLING_TIMES] = {0.075, 1.0, 4.0, 12.0}; +typedef enum { + XPSPositionCompareModeDisable, + XPSPositionCompareModePulse, + XPSPositionCompareModeAquadBWindowed, + XPSPositionCompareModeAquadBAlways +} XPSPositionCompareMode_t; + // drvInfo strings for extra parameters that the XPS controller supports -#define XPSMinJerkString "XPS_MIN_JERK" -#define XPSMaxJerkString "XPS_MAX_JERK" -#define XPSProfileMaxVelocityString "XPS_PROFILE_MAX_VELOCITY" -#define XPSProfileMaxAccelerationString "XPS_PROFILE_MAX_ACCELERATION" -#define XPSProfileMinPositionString "XPS_PROFILE_MIN_POSITION" -#define XPSProfileMaxPositionString "XPS_PROFILE_MAX_POSITION" -#define XPSProfileGroupNameString "XPS_PROFILE_GROUP_NAME" -#define XPSTrajectoryFileString "XPS_TRAJECTORY_FILE" -#define XPSStatusString "XPS_STATUS" -#define XPSStatusStringString "XPS_STATUS_STRING" -#define XPSTclScriptString "XPS_TCL_SCRIPT" -#define XPSTclScriptExecuteString "XPS_TCL_SCRIPT_EXECUTE" +#define XPSMinJerkString "XPS_MIN_JERK" +#define XPSMaxJerkString "XPS_MAX_JERK" +#define XPSPositionCompareModeString "XPS_POSITION_COMPARE_MODE" +#define XPSPositionCompareMinPositionString "XPS_POSITION_COMPARE_MIN_POSITION" +#define XPSPositionCompareMaxPositionString "XPS_POSITION_COMPARE_MAX_POSITION" +#define XPSPositionCompareStepSizeString "XPS_POSITION_COMPARE_STEP_SIZE" +#define XPSPositionComparePulseWidthString "XPS_POSITION_COMPARE_PULSE_WIDTH" +#define XPSPositionCompareSettlingTimeString "XPS_POSITION_COMPARE_SETTLING_TIME" +#define XPSProfileMaxVelocityString "XPS_PROFILE_MAX_VELOCITY" +#define XPSProfileMaxAccelerationString "XPS_PROFILE_MAX_ACCELERATION" +#define XPSProfileMinPositionString "XPS_PROFILE_MIN_POSITION" +#define XPSProfileMaxPositionString "XPS_PROFILE_MAX_POSITION" +#define XPSProfileGroupNameString "XPS_PROFILE_GROUP_NAME" +#define XPSTrajectoryFileString "XPS_TRAJECTORY_FILE" +#define XPSStatusString "XPS_STATUS" +#define XPSStatusStringString "XPS_STATUS_STRING" +#define XPSTclScriptString "XPS_TCL_SCRIPT" +#define XPSTclScriptExecuteString "XPS_TCL_SCRIPT_EXECUTE" class epicsShareClass XPSController : public asynMotorController { @@ -44,6 +62,7 @@ class epicsShareClass XPSController : public asynMotorController { /* These are the methods that we override from asynMotorDriver */ asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); + asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value); void report(FILE *fp, int level); XPSAxis* getAxis(asynUser *pasynUser); XPSAxis* getAxis(int axisNo); @@ -81,6 +100,12 @@ class epicsShareClass XPSController : public asynMotorController { #define FIRST_XPS_PARAM XPSMinJerk_ int XPSMinJerk_; int XPSMaxJerk_; + int XPSPositionCompareMode_; + int XPSPositionCompareMinPosition_; + int XPSPositionCompareMaxPosition_; + int XPSPositionCompareStepSize_; + int XPSPositionComparePulseWidth_; + int XPSPositionCompareSettlingTime_; int XPSProfileMaxVelocity_; int XPSProfileMaxAcceleration_; int XPSProfileMinPosition_; diff --git a/motorApp/NewportSrc/XPSGathering2.c b/motorApp/NewportSrc/XPSGathering2.c index 030c881..1c258db 100644 --- a/motorApp/NewportSrc/XPSGathering2.c +++ b/motorApp/NewportSrc/XPSGathering2.c @@ -2,11 +2,11 @@ /**/ #include #include +#define epicsExportSharedSymbols +#include #include "XPS_C8_drivers.h" #include "Socket.h" #include "xps_ftp.h" -#define epicsExportSharedSymbols -#include #define XPS_ADDRESS "164.54.160.124" #define NUM_TRAJECTORY_ELEMENTS 6 diff --git a/motorApp/NewportSrc/XPS_C8_drivers.cpp b/motorApp/NewportSrc/XPS_C8_drivers.cpp index 8bc8270..3f21743 100644 --- a/motorApp/NewportSrc/XPS_C8_drivers.cpp +++ b/motorApp/NewportSrc/XPS_C8_drivers.cpp @@ -9,15 +9,13 @@ #include #include "Socket.h" +#define epicsExportSharedSymbols +#include +#include "XPS_C8_drivers.h" #ifdef _WIN32 - #define DLL _declspec(dllexport) - #include "strtok_r.h" -#else - #define DLL +#include "strtok_r.h" #endif -#include "XPS_C8_drivers.h" - #define SIZE_SMALL 1024 #define SIZE_NOMINAL 1024 #define SIZE_BIG 2048 diff --git a/motorApp/NewportSrc/XPS_C8_drivers.h b/motorApp/NewportSrc/XPS_C8_drivers.h index 458a91a..de5ecdd 100644 --- a/motorApp/NewportSrc/XPS_C8_drivers.h +++ b/motorApp/NewportSrc/XPS_C8_drivers.h @@ -5,18 +5,10 @@ * XPS functions * *************************************************/ +#define DLL epicsShareFunc -#ifdef _WIN32 - #ifndef DLL - #ifdef _DLL /* _DLL is defined by EPICS if we are being compiled to call DLLs */ - #define DLL _declspec(dllimport) - #else - #define DLL - #endif - #endif -#else - #define DLL - #define __stdcall +#if !defined(_WIN32) && !defined(CYGWIN32) +#define __stdcall #endif #ifdef __rtems__ diff --git a/motorApp/NewportSrc/XPS_C8_errors.h b/motorApp/NewportSrc/XPS_C8_errors.h index cd70875..2098187 100644 --- a/motorApp/NewportSrc/XPS_C8_errors.h +++ b/motorApp/NewportSrc/XPS_C8_errors.h @@ -1,107 +1,107 @@ -/*/////////////////////////////////////////////////////////////////// - * Created header file XPS_C8_errors.h for XPS function errors - */ - -/* TCL interpretor error */ -#define ERR_TCL_INTERPRETOR_ERROR 1 - -/* No error */ -#define SUCCESS 0 - -/* XPS errors */ -#define ERR_BUSY_SOCKET -1 -#define ERR_TCP_TIMEOUT -2 -#define ERR_STRING_TOO_LONG -3 -#define ERR_UNKNOWN_COMMAND -4 -#define ERR_POSITIONER_ERROR -5 -#define ERR_WRONG_FORMAT -7 -#define ERR_WRONG_OBJECT_TYPE -8 -#define ERR_WRONG_PARAMETERS_NUMBER -9 -#define ERR_WRONG_TYPE -10 -#define ERR_WRONG_TYPE_BIT_WORD -11 -#define ERR_WRONG_TYPE_BOOL -12 -#define ERR_WRONG_TYPE_CHAR -13 -#define ERR_WRONG_TYPE_DOUBLE -14 -#define ERR_WRONG_TYPE_INT -15 -#define ERR_WRONG_TYPE_UNSIGNEDINT -16 -#define ERR_PARAMETER_OUT_OF_RANGE -17 -#define ERR_POSITIONER_NAME -18 -#define ERR_GROUP_NAME -19 -#define ERR_FATAL_INIT -20 -#define ERR_IN_INITIALIZATION -21 -#define ERR_NOT_ALLOWED_ACTION -22 -#define ERR_POSITION_COMPARE_NOT_SET -23 -#define ERR_UNCOMPATIBLE -24 -#define ERR_FOLLOWING_ERROR -25 -#define ERR_EMERGENCY_SIGNAL -26 -#define ERR_GROUP_ABORT_MOTION -27 -#define ERR_GROUP_HOME_SEARCH_TIMEOUT -28 -#define ERR_MNEMOTYPEGATHERING -29 -#define ERR_GATHERING_NOT_STARTED -30 -#define ERR_HOME_OUT_RANGE -31 -#define ERR_GATHERING_NOT_CONFIGURED -32 -#define ERR_GROUP_MOTION_DONE_TIMEOUT -33 -#define ERR_TRAVEL_LIMITS -35 -#define ERR_UNKNOWN_TCL_FILE -36 -#define ERR_TCL_SCRIPT_KILL -38 -#define ERR_TCL_INTERPRETOR -37 -#define ERR_MNEMO_ACTION -39 -#define ERR_MNEMO_EVENT -40 -#define ERR_SLAVE_CONFIGURATION -41 -#define ERR_JOG_OUT_OF_RANGE -42 -#define ERR_GATHERING_RUNNING -43 -#define ERR_SLAVE -44 -#define ERR_END_OF_RUN -45 -#define ERR_NOT_ALLOWED_BACKLASH -46 -#define ERR_WRONG_TCL_TASKNAME -47 -#define ERR_BASE_VELOCITY -48 -#define ERR_GROUP_HOME_SEARCH_ZM_ERROR -49 -#define ERR_MOTOR_INITIALIZATION_ERROR -50 -#define ERR_SPIN_OUT_OF_RANGE -51 -#define ERR_WRITE_FILE -60 -#define ERR_READ_FILE -61 -#define ERR_TRAJ_ELEM_TYPE -62 -#define ERR_TRAJ_ELEM_RADIUS -63 -#define ERR_TRAJ_ELEM_SWEEP -64 -#define ERR_TRAJ_ELEM_LINE -65 -#define ERR_TRAJ_EMPTY -66 -#define ERR_TRAJ_VEL_LIMIT -68 -#define ERR_TRAJ_ACC_LIMIT -69 -#define ERR_TRAJ_FINAL_VELOCITY -70 -#define ERR_MSG_QUEUE -71 -#define ERR_TRAJ_INITIALIZATION -72 -#define ERR_END_OF_FILE -73 -#define ERR_READ_FILE_PARAMETER_KEY -74 -#define ERR_TRAJ_TIME -75 -#define ERR_EVENTS_NOT_CONFIGURED -80 -#define ERR_ACTIONS_NOT_CONFIGURED -81 -#define ERR_EVENT_BUFFER_FULL -82 -#define ERR_EVENT_ID_UNDEFINED -83 -#define ERR_HOME_SEARCH_GANTRY_TOLERANCE_ERROR -85 -#define ERR_FOCUS_RESERVED_SOCKET -90 -#define ERR_FOCUS_BUSY_EVENT_SCHEDULER -91 -#define ERR_OPTIONAL_EXTERNAL_MODULE_FILE -94 -#define ERR_OPTIONAL_EXTERNAL_MODULE_EXECUTE -95 -#define ERR_OPTIONAL_EXTERNAL_MODULE_KILL -96 -#define ERR_OPTIONAL_EXTERNAL_MODULE_LOAD -97 -#define ERR_OPTIONAL_EXTERNAL_MODULE_UNLOAD -98 -#define ERR_FATAL_EXTERNAL_MODULE_LOAD -99 -#define ERR_INTERNAL_ERROR -100 -#define ERR_RELAY_FEEDBACK_TEST_NO_OSCILLATION -101 -#define ERR_RELAY_FEEDBACK_TEST_SIGNAL_NOISY -102 -#define ERR_SIGNAL_POINTS_NOT_ENOUGH -103 -#define ERR_PID_TUNING_INITIALIZATION -104 -#define ERR_SCALING_CALIBRATION -105 -#define ERR_WRONG_USERNAME_OR_PASSWORD -106 -#define ERR_NEED_ADMINISTRATOR_RIGHTS -107 -#define ERR_SOCKET_CLOSED_BY_ADMIN -108 -#define ERR_NEED_TO_BE_HOMED_AT_LEAST_ONCE -109 -#define ERR_NOT_ALLOWED_FOR_GANTRY -110 -#define ERR_GATHERING_BUFFER_FULL -111 -#define ERR_EXCITATION_SIGNAL_INITIALIZATION -112 -#define ERR_BOTH_ENDS_OF_RUNS_ACTIVATED -113 -#define ERR_GROUP_CLAMPING_TIMEOUT -114 -#define ERR_HARDWARE_FUNCTION_NOT_SUPPORTED -115 -#define ERR_EXTERNAL_DRIVER_INIT -116 -#define ERR_FUNCTION_ONLY_ALLOWED_IN_DISABLED_STATE -117 -#define ERR_NOT_ALLOWED_DRIVER_NOT_INITIALIZED -118 +/*/////////////////////////////////////////////////////////////////// + * Created header file XPS_C8_errors.h for XPS function errors + */ + +/* TCL interpretor error */ +#define ERR_TCL_INTERPRETOR_ERROR 1 + +/* No error */ +#define SUCCESS 0 + +/* XPS errors */ +#define ERR_BUSY_SOCKET -1 +#define ERR_TCP_TIMEOUT -2 +#define ERR_STRING_TOO_LONG -3 +#define ERR_UNKNOWN_COMMAND -4 +#define ERR_POSITIONER_ERROR -5 +#define ERR_WRONG_FORMAT -7 +#define ERR_WRONG_OBJECT_TYPE -8 +#define ERR_WRONG_PARAMETERS_NUMBER -9 +#define ERR_WRONG_TYPE -10 +#define ERR_WRONG_TYPE_BIT_WORD -11 +#define ERR_WRONG_TYPE_BOOL -12 +#define ERR_WRONG_TYPE_CHAR -13 +#define ERR_WRONG_TYPE_DOUBLE -14 +#define ERR_WRONG_TYPE_INT -15 +#define ERR_WRONG_TYPE_UNSIGNEDINT -16 +#define ERR_PARAMETER_OUT_OF_RANGE -17 +#define ERR_POSITIONER_NAME -18 +#define ERR_GROUP_NAME -19 +#define ERR_FATAL_INIT -20 +#define ERR_IN_INITIALIZATION -21 +#define ERR_NOT_ALLOWED_ACTION -22 +#define ERR_POSITION_COMPARE_NOT_SET -23 +#define ERR_UNCOMPATIBLE -24 +#define ERR_FOLLOWING_ERROR -25 +#define ERR_EMERGENCY_SIGNAL -26 +#define ERR_GROUP_ABORT_MOTION -27 +#define ERR_GROUP_HOME_SEARCH_TIMEOUT -28 +#define ERR_MNEMOTYPEGATHERING -29 +#define ERR_GATHERING_NOT_STARTED -30 +#define ERR_HOME_OUT_RANGE -31 +#define ERR_GATHERING_NOT_CONFIGURED -32 +#define ERR_GROUP_MOTION_DONE_TIMEOUT -33 +#define ERR_TRAVEL_LIMITS -35 +#define ERR_UNKNOWN_TCL_FILE -36 +#define ERR_TCL_SCRIPT_KILL -38 +#define ERR_TCL_INTERPRETOR -37 +#define ERR_MNEMO_ACTION -39 +#define ERR_MNEMO_EVENT -40 +#define ERR_SLAVE_CONFIGURATION -41 +#define ERR_JOG_OUT_OF_RANGE -42 +#define ERR_GATHERING_RUNNING -43 +#define ERR_SLAVE -44 +#define ERR_END_OF_RUN -45 +#define ERR_NOT_ALLOWED_BACKLASH -46 +#define ERR_WRONG_TCL_TASKNAME -47 +#define ERR_BASE_VELOCITY -48 +#define ERR_GROUP_HOME_SEARCH_ZM_ERROR -49 +#define ERR_MOTOR_INITIALIZATION_ERROR -50 +#define ERR_SPIN_OUT_OF_RANGE -51 +#define ERR_WRITE_FILE -60 +#define ERR_READ_FILE -61 +#define ERR_TRAJ_ELEM_TYPE -62 +#define ERR_TRAJ_ELEM_RADIUS -63 +#define ERR_TRAJ_ELEM_SWEEP -64 +#define ERR_TRAJ_ELEM_LINE -65 +#define ERR_TRAJ_EMPTY -66 +#define ERR_TRAJ_VEL_LIMIT -68 +#define ERR_TRAJ_ACC_LIMIT -69 +#define ERR_TRAJ_FINAL_VELOCITY -70 +#define ERR_MSG_QUEUE -71 +#define ERR_TRAJ_INITIALIZATION -72 +#define ERR_END_OF_FILE -73 +#define ERR_READ_FILE_PARAMETER_KEY -74 +#define ERR_TRAJ_TIME -75 +#define ERR_EVENTS_NOT_CONFIGURED -80 +#define ERR_ACTIONS_NOT_CONFIGURED -81 +#define ERR_EVENT_BUFFER_FULL -82 +#define ERR_EVENT_ID_UNDEFINED -83 +#define ERR_HOME_SEARCH_GANTRY_TOLERANCE_ERROR -85 +#define ERR_FOCUS_RESERVED_SOCKET -90 +#define ERR_FOCUS_BUSY_EVENT_SCHEDULER -91 +#define ERR_OPTIONAL_EXTERNAL_MODULE_FILE -94 +#define ERR_OPTIONAL_EXTERNAL_MODULE_EXECUTE -95 +#define ERR_OPTIONAL_EXTERNAL_MODULE_KILL -96 +#define ERR_OPTIONAL_EXTERNAL_MODULE_LOAD -97 +#define ERR_OPTIONAL_EXTERNAL_MODULE_UNLOAD -98 +#define ERR_FATAL_EXTERNAL_MODULE_LOAD -99 +#define ERR_INTERNAL_ERROR -100 +#define ERR_RELAY_FEEDBACK_TEST_NO_OSCILLATION -101 +#define ERR_RELAY_FEEDBACK_TEST_SIGNAL_NOISY -102 +#define ERR_SIGNAL_POINTS_NOT_ENOUGH -103 +#define ERR_PID_TUNING_INITIALIZATION -104 +#define ERR_SCALING_CALIBRATION -105 +#define ERR_WRONG_USERNAME_OR_PASSWORD -106 +#define ERR_NEED_ADMINISTRATOR_RIGHTS -107 +#define ERR_SOCKET_CLOSED_BY_ADMIN -108 +#define ERR_NEED_TO_BE_HOMED_AT_LEAST_ONCE -109 +#define ERR_NOT_ALLOWED_FOR_GANTRY -110 +#define ERR_GATHERING_BUFFER_FULL -111 +#define ERR_EXCITATION_SIGNAL_INITIALIZATION -112 +#define ERR_BOTH_ENDS_OF_RUNS_ACTIVATED -113 +#define ERR_GROUP_CLAMPING_TIMEOUT -114 +#define ERR_HARDWARE_FUNCTION_NOT_SUPPORTED -115 +#define ERR_EXTERNAL_DRIVER_INIT -116 +#define ERR_FUNCTION_ONLY_ALLOWED_IN_DISABLED_STATE -117 +#define ERR_NOT_ALLOWED_DRIVER_NOT_INITIALIZED -118 diff --git a/motorApp/NewportSrc/XPS_trajectoryScan.st b/motorApp/NewportSrc/XPS_trajectoryScan.st index d3082e2..2c8a871 100644 --- a/motorApp/NewportSrc/XPS_trajectoryScan.st +++ b/motorApp/NewportSrc/XPS_trajectoryScan.st @@ -20,6 +20,8 @@ program XPS_trajectoryScan("P=13BMC:,R=traj1,IPADDR=164.54.160.34,PORT=5001," %% #include %% #include %% #include +%% #define epicsExportSharedSymbols +%% #include %% #include "XPS_C8_drivers.h" %% #include "XPS_C8_errors.h" %% #include "Socket.h" diff --git a/motorApp/NewportSrc/devESP300.cc b/motorApp/NewportSrc/devESP300.cc index b50fc5a..ec26a08 100644 --- a/motorApp/NewportSrc/devESP300.cc +++ b/motorApp/NewportSrc/devESP300.cc @@ -2,10 +2,6 @@ FILENAME... devESP300.cc USAGE... Motor record device level support for Newport ESP300. -Version: $Revision$ -Modified By: $Author$ -Last Modified: $Date$ -HeadURL: $URL$ */ /* @@ -42,6 +38,7 @@ HeadURL: $URL$ #include #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -53,7 +50,7 @@ extern struct driver_table ESP300_access; /* ----------------Create the dsets for devESP300----------------- */ /* static long report(); */ static struct driver_table *drvtabptr; -static long ESP300_init(void *); +static long ESP300_init(int); static long ESP300_init_record(void *); static long ESP300_start_trans(struct motorRecord *); static RTN_STATUS ESP300_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -107,12 +104,11 @@ static struct board_stat **ESP300_cards; /* initialize device support for ESP300 stepper motor */ -static long ESP300_init(void *arg) +static long ESP300_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &ESP300_access; (drvtabptr->init)(); @@ -243,7 +239,7 @@ static RTN_STATUS ESP300_build_trans(motor_cmnd command, double *parms, struct m sprintf(buff, "%.2dVA%f;", axis, cntrl_units); break; case SET_ACCEL: - sprintf(buff, "%.2dAC%f;", axis, cntrl_units); + sprintf(buff, "%.2dAC%f;%.2dAG%f;", axis, cntrl_units, axis, cntrl_units); break; case GO: /* diff --git a/motorApp/NewportSrc/devMM3000.cc b/motorApp/NewportSrc/devMM3000.cc index 1e5edb3..1f9cd99 100644 --- a/motorApp/NewportSrc/devMM3000.cc +++ b/motorApp/NewportSrc/devMM3000.cc @@ -2,9 +2,6 @@ FILENAME... devMM3000.cc USAGE... Motor record device level support for Newport MM3000. -Version: $Revision: 1.4 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-03-14 20:17:14 $ */ /* @@ -43,6 +40,9 @@ Last Modified: $Date: 2008-03-14 20:17:14 $ #include +#include +#include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -56,7 +56,7 @@ extern struct driver_table MM3000_access; /* ----------------Create the dsets for devMM3000----------------- */ /* static long report(); */ STATIC struct driver_table *drvtabptr; -STATIC long MM3000_init(void *); +STATIC long MM3000_init(int); STATIC long MM3000_init_record(void *); STATIC long MM3000_start_trans(struct motorRecord *); STATIC RTN_STATUS MM3000_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -110,12 +110,11 @@ static struct board_stat **MM3000_cards; /* initialize device support for MM3000 stepper motor */ -STATIC long MM3000_init(void *arg) +STATIC long MM3000_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &MM3000_access; (drvtabptr->init)(); @@ -277,6 +276,10 @@ STATIC RTN_STATUS MM3000_build_trans(motor_cmnd command, double *parms, struct m */ break; case SET_ENC_RATIO: + /* The motor record no longer passes unsigned values */ + parms[0] = fabs(parms[0]); + parms[1] = fabs(parms[1]); + /* MM3000 valid encoder ratio values < 10,000. */ while (parms[0] > 10000.0 || parms[1] > 10000.0) { diff --git a/motorApp/NewportSrc/devMM4000.cc b/motorApp/NewportSrc/devMM4000.cc index 5a606bb..f84acf3 100644 --- a/motorApp/NewportSrc/devMM4000.cc +++ b/motorApp/NewportSrc/devMM4000.cc @@ -2,10 +2,6 @@ FILENAME... devMM4000.cc USAGE... Motor record device level support for Newport MM4000. -Version: $Revision: 15620 $ -Modified By: $Author: rivers $ -Last Modified: $Date: 2012-12-06 16:20:02 -0600 (Thu, 06 Dec 2012) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/NewportSrc/devMM4000.cc $ */ /* @@ -48,6 +44,7 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -60,7 +57,7 @@ extern struct driver_table MM4000_access; /* ----------------Create the dsets for devMM4000----------------- */ STATIC struct driver_table *drvtabptr; -STATIC long MM4000_init(void *); +STATIC long MM4000_init(int); STATIC long MM4000_init_record(void *); STATIC long MM4000_start_trans(struct motorRecord *); STATIC RTN_STATUS MM4000_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -114,12 +111,11 @@ static struct board_stat **MM4000_cards; /* initialize device support for MM4000 stepper motor */ -STATIC long MM4000_init(void *arg) +STATIC long MM4000_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &MM4000_access; (drvtabptr->init)(); diff --git a/motorApp/NewportSrc/devNewport.dbd b/motorApp/NewportSrc/devNewport.dbd index fc31f1d..73ebaee 100644 --- a/motorApp/NewportSrc/devNewport.dbd +++ b/motorApp/NewportSrc/devNewport.dbd @@ -18,9 +18,6 @@ registrar(XPSInterposeRegister) registrar(drvXPSAsynAuxRegister) registrar(AG_UCRegister) registrar(AG_CONEXRegister) -registrar(MM4005_trajectoryScanRegistrar) -registrar(XPS_trajectoryScanRegistrar) -registrar(xpsSlaveRegistrar) registrar(SMC100Register) #variable(devXPSC8Debug) #variable(drvXPSC8Debug) diff --git a/motorApp/NewportSrc/devNewportSeq.dbd b/motorApp/NewportSrc/devNewportSeq.dbd new file mode 100644 index 0000000..48aa842 --- /dev/null +++ b/motorApp/NewportSrc/devNewportSeq.dbd @@ -0,0 +1,4 @@ +# Newport SNL programs +registrar(MM4005_trajectoryScanRegistrar) +registrar(XPS_trajectoryScanRegistrar) +registrar(xpsSlaveRegistrar) diff --git a/motorApp/NewportSrc/devPM500.cc b/motorApp/NewportSrc/devPM500.cc index b077d58..ca052c8 100644 --- a/motorApp/NewportSrc/devPM500.cc +++ b/motorApp/NewportSrc/devPM500.cc @@ -3,9 +3,6 @@ FILENAME... devPM500.cc USAGE... Motor record device level support for the Newport PM500 motor controller. -Version: $Revision: 1.4 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2009-08-25 18:24:24 $ */ /* @@ -45,6 +42,7 @@ Last Modified: $Date: 2009-08-25 18:24:24 $ #include #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -57,7 +55,7 @@ extern struct driver_table PM500_access; /* ----------------Create the dsets for devPM500----------------- */ STATIC struct driver_table *drvtabptr; -STATIC long PM500_init(void *); +STATIC long PM500_init(int); STATIC long PM500_init_record(void *); STATIC long PM500_start_trans(struct motorRecord *); STATIC RTN_STATUS PM500_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -113,12 +111,11 @@ static struct board_stat **PM500_cards; /* Initialize device support for PM500 controller. */ -STATIC long PM500_init(void *arg) +STATIC long PM500_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &PM500_access; (drvtabptr->init)(); diff --git a/motorApp/NewportSrc/drvESP300.cc b/motorApp/NewportSrc/drvESP300.cc index 84b7a11..ef899e8 100644 --- a/motorApp/NewportSrc/drvESP300.cc +++ b/motorApp/NewportSrc/drvESP300.cc @@ -2,10 +2,6 @@ FILENAME... drvESP300.cc USAGE... Motor record driver level support for Newport ESP300/100. -Version: $Revision: 17447 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2014-05-23 10:33:19 -0500 (Fri, 23 May 2014) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/NewportSrc/drvESP300.cc $ */ /* @@ -60,6 +56,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#include +#include #include "motor.h" #include "NewportRegister.h" #include "drvMMCom.h" @@ -227,7 +225,7 @@ static int set_status(int card, int signal) status.All = motor_info->status.All; sprintf(outbuff, "%.2dMD", signal + 1); - send_mess(card, outbuff, (char) NULL); + send_mess(card, outbuff, (char*) NULL); charcnt = recv_mess(card, inbuff, 1); if (charcnt == 1 && (inbuff[0] == '0' || inbuff[0] == '1')) @@ -257,7 +255,7 @@ static int set_status(int card, int signal) /* Get motor position. */ sprintf(outbuff, READ_POSITION, signal + 1); - send_mess(card, outbuff, (char) NULL); + send_mess(card, outbuff, (char*) NULL); charcnt = recv_mess(card, inbuff, 1); motorData = atof(inbuff) / cntrl->drive_resolution[signal]; @@ -281,7 +279,7 @@ static int set_status(int card, int signal) /* Get travel limit switch status. */ sprintf(outbuff, "%.2dPH", signal + 1); - send_mess(card, outbuff, (char) NULL); + send_mess(card, outbuff, (char*) NULL); charcnt = recv_mess(card, inbuff, 1); cptr = strchr(inbuff, 'H'); if (cptr == NULL) @@ -320,7 +318,7 @@ static int set_status(int card, int signal) /* Get motor power on/off status. */ sprintf(outbuff, "%.2dMO?", signal + 1); - send_mess(card, outbuff, (char) NULL); + send_mess(card, outbuff, (char*) NULL); charcnt = recv_mess(card, inbuff, 1); power = atoi(inbuff) ? true : false; @@ -333,7 +331,7 @@ static int set_status(int card, int signal) /* Get error code. */ sprintf(outbuff, "%.2dTE?", signal + 1); - send_mess(card, outbuff, (char) NULL); + send_mess(card, outbuff, (char*) NULL); charcnt = recv_mess(card, inbuff, 1); errcode = atoi(inbuff); if (errcode != 0) @@ -360,7 +358,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(outbuff, nodeptr->postmsgptr); - send_mess(card, outbuff, (char) NULL); + send_mess(card, outbuff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -640,7 +638,7 @@ static int motor_init() do { - send_mess(card_index, GET_IDENT, (char) NULL); + send_mess(card_index, GET_IDENT, (char*) NULL); status = recv_mess(card_index, buff, 1); retry++; /* Return value is length of response string */ @@ -654,7 +652,7 @@ static int motor_init() brdptr->motor_in_motion = 0; strcpy(brdptr->ident, &buff[1]); /* Skip "\n" */ - send_mess(card_index, "ZU", (char) NULL); + send_mess(card_index, "ZU", (char*) NULL); recv_mess(card_index, buff, 1); total_axis = buff[0] >> 4; if (total_axis > 4) @@ -666,7 +664,7 @@ static int motor_init() for (motor_index = 0; motor_index < total_axis; motor_index++) { sprintf(buff, STOP_AXIS, motor_index + 1); /* Stop motor */ - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); /* Initialize. */ brdptr->motor_info[motor_index].motor_motion = NULL; } @@ -676,6 +674,9 @@ static int motor_init() for (motor_index = 0; motor_index < total_axis; motor_index++) { struct mess_info *motor_info = &brdptr->motor_info[motor_index]; + int feedback; + double fullStep; + int microStep; /* Get controller's EGU for the user (see README). */ sprintf(buff, "%.2dSN?", motor_index + 1); @@ -683,11 +684,30 @@ static int motor_init() recv_mess(card_index, buff, 1); /* Set axis resolution. */ - sprintf(buff, "%.2dSU?", motor_index + 1); + /* Read the feedback status */ + sprintf(buff, "%.2dZB?", motor_index + 1); send_mess(card_index, buff, 0); recv_mess(card_index, buff, 1); - cntrl->drive_resolution[motor_index] = atof(&buff[0]); - + feedback = strtol(buff,0,16); + /* If stepper closed loop positioning is enabled (bit 9=1) and encoder feedback is disabled (bit 8=0) + * then use the full-step resolution (FR) and microstepping (QS) to determine drive_resolution. + * If not then use SU (encoder resolution) for drive_resolution. */ + if ((feedback & 0x300) == 0x200) { + sprintf(buff, "%.2dFR?", motor_index + 1); + send_mess(card_index, buff, 0); + recv_mess(card_index, buff, 1); + fullStep = atof(buff); + sprintf(buff, "%.2dQS?", motor_index + 1); + send_mess(card_index, buff, 0); + recv_mess(card_index, buff, 1); + microStep = strtol(buff, 0, 10); + cntrl->drive_resolution[motor_index] = fullStep / microStep; + } else { + sprintf(buff, "%.2dSU?", motor_index + 1); + send_mess(card_index, buff, 0); + recv_mess(card_index, buff, 1); + cntrl->drive_resolution[motor_index] = atof(&buff[0]); + } motor_info->status.All = 0; motor_info->no_motion_count = 0; motor_info->encoder_position = 0; diff --git a/motorApp/NewportSrc/drvMM3000.cc b/motorApp/NewportSrc/drvMM3000.cc index fe7268b..7131ed0 100644 --- a/motorApp/NewportSrc/drvMM3000.cc +++ b/motorApp/NewportSrc/drvMM3000.cc @@ -2,10 +2,6 @@ FILENAME... drvMM3000.cc USAGE... Motor record driver level support for Newport MM3000. -Version: $Revision: 15621 $ -Modified By: $Author: rivers $ -Last Modified: $Date: 2012-12-06 16:20:48 -0600 (Thu, 06 Dec 2012) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/NewportSrc/drvMM3000.cc $ */ /* @@ -72,6 +68,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#include +#include #include "motor.h" #include "NewportRegister.h" #include "drvMMCom.h" @@ -247,7 +245,7 @@ STATIC int set_status(int card, int signal) status.All = motor_info->status.All; sprintf(outbuff, "%dMS", signal + 1); - send_mess(card, outbuff, (char) NULL); + send_mess(card, outbuff, (char*) NULL); charcnt = recv_mess(card, inbuff, 1); if (charcnt > 0) { @@ -312,7 +310,7 @@ STATIC int set_status(int card, int signal) status.Bits.EA_HOME = 0; sprintf(outbuff, "%dTP", signal + 1); - send_mess(card, outbuff, (char) NULL); + send_mess(card, outbuff, (char*) NULL); charcnt = recv_mess(card, inbuff, 1); if (charcnt > 0) { @@ -375,7 +373,7 @@ STATIC int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(outbuff, nodeptr->postmsgptr); - send_mess(card, outbuff, (char) NULL); + send_mess(card, outbuff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -633,7 +631,7 @@ STATIC int motor_init() /* flush any junk at input port - should not be any data available */ pasynOctetSyncIO->flush(cntrl->pasynUser); - send_mess(card_index, GET_IDENT, (char) NULL); + send_mess(card_index, GET_IDENT, (char*) NULL); status = recv_mess(card_index, axis_pos, 1); /* Return value is length of response string */ } @@ -642,12 +640,12 @@ STATIC int motor_init() { brdptr->localaddr = (char *) NULL; brdptr->motor_in_motion = 0; - send_mess(card_index, STOP_ALL, (char) NULL); /* Stop all motors */ - send_mess(card_index, GET_IDENT, (char) NULL); /* Read controller ID string */ + send_mess(card_index, STOP_ALL, (char*) NULL); /* Stop all motors */ + send_mess(card_index, GET_IDENT, (char*) NULL); /* Read controller ID string */ recv_mess(card_index, buff, 1); strncpy(brdptr->ident, &buff[0], MAX_IDENT_LEN); /* Skip "VE" */ - send_mess(card_index, "RC", (char) NULL); + send_mess(card_index, "RC", (char*) NULL); recv_mess(card_index, buff, 1); bufptr = epicsStrtok_r(buff, "=", &tok_save); bufptr = epicsStrtok_r(NULL, " ", &tok_save); @@ -694,7 +692,7 @@ STATIC int motor_init() else { sprintf(buff, "%dTPE", motor_index + 1); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); if (strcmp(buff, "E01") == 0) diff --git a/motorApp/NewportSrc/drvMM4000.cc b/motorApp/NewportSrc/drvMM4000.cc index 74b32f5..66a9bad 100644 --- a/motorApp/NewportSrc/drvMM4000.cc +++ b/motorApp/NewportSrc/drvMM4000.cc @@ -2,10 +2,6 @@ FILENAME... drvMM4000.cc USAGE... Motor record driver level support for Newport MM4000. -Version: $Revision: 15620 $ -Modified By: $Author: rivers $ -Last Modified: $Date: 2012-12-06 16:20:02 -0600 (Thu, 06 Dec 2012) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/NewportSrc/drvMM4000.cc $ */ /* @@ -88,6 +84,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#include +#include #include "motor.h" #include "NewportRegister.h" #include "drvMMCom.h" @@ -261,14 +259,14 @@ static void start_status(int card) if (card >= 0) { cntrl = (struct MMcontroller *) motor_state[card]->DevicePrivate; - send_mess(card, READ_STATUS, (char) NULL); + send_mess(card, READ_STATUS, (char*) NULL); status = recv_mess(card, cntrl->status_string, 1); if (status > 0) { cntrl->status = NORMAL; - send_mess(card, READ_POSITION, (char) NULL); + send_mess(card, READ_POSITION, (char*) NULL); recv_mess(card, cntrl->position_string, 1); - send_mess(card, READ_FEEDBACK, (char) NULL); + send_mess(card, READ_FEEDBACK, (char*) NULL); recv_mess(card, cntrl->feedback_string, 1); } else @@ -286,7 +284,7 @@ static void start_status(int card) * responses. This minimizes the latency due to processing on each card */ for (itera = 0; (itera < total_cards) && motor_state[itera]; itera++) - send_mess(itera, READ_STATUS, (char) NULL); + send_mess(itera, READ_STATUS, (char*) NULL); for (itera = 0; (itera < total_cards) && motor_state[itera]; itera++) { cntrl = (struct MMcontroller *) motor_state[itera]->DevicePrivate; @@ -294,7 +292,7 @@ static void start_status(int card) if (status > 0) { cntrl->status = NORMAL; - send_mess(itera, READ_FEEDBACK, (char) NULL); + send_mess(itera, READ_FEEDBACK, (char*) NULL); recv_mess(itera, cntrl->feedback_string, 1); } else @@ -306,7 +304,7 @@ static void start_status(int card) } } for (itera = 0; (itera < total_cards) && motor_state[itera]; itera++) - send_mess(itera, READ_POSITION, (char) NULL); + send_mess(itera, READ_POSITION, (char*) NULL); for (itera = 0; (itera < total_cards) && motor_state[itera]; itera++) { cntrl = (struct MMcontroller *) motor_state[itera]->DevicePrivate; @@ -390,7 +388,7 @@ static int set_status(int card, int signal) if (motor_info->pid_present == YES && drvMM4000ReadbackDelay != 0) { epicsThreadSleep((double) drvMM4000ReadbackDelay/1000.0); - send_mess(card, READ_STATUS, (char) NULL); + send_mess(card, READ_STATUS, (char*) NULL); recv_mess(card, cntrl->status_string, 1); pos = signal*5 + 3; /* Offset in status string */ mstat.All = cntrl->status_string[pos]; @@ -471,7 +469,7 @@ static int set_status(int card, int signal) /* Check for controller error. */ - send_mess(card, "TE;", (char) NULL); + send_mess(card, "TE;", (char*) NULL); recv_mess(card, buff, 1); if (buff[2] == '@') status.Bits.RA_PROBLEM = 0; @@ -498,7 +496,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -710,7 +708,7 @@ static int motor_init() do { - send_mess(card_index, READ_POSITION, (char) NULL); + send_mess(card_index, READ_POSITION, (char*) NULL); status = recv_mess(card_index, axis_pos, 1); retry++; /* Return value is length of response string */ @@ -721,8 +719,8 @@ static int motor_init() { brdptr->localaddr = (char *) NULL; brdptr->motor_in_motion = 0; - send_mess(card_index, STOP_ALL, (char) NULL); /* Stop all motors */ - send_mess(card_index, GET_IDENT, (char) NULL); /* Read controller ID string */ + send_mess(card_index, STOP_ALL, (char*) NULL); /* Stop all motors */ + send_mess(card_index, GET_IDENT, (char*) NULL); /* Read controller ID string */ recv_mess(card_index, buff, 1); strcpy(brdptr->ident, &buff[2]); /* Skip "VE" */ @@ -746,7 +744,7 @@ static int motor_init() continue; } - send_mess(card_index, READ_POSITION, (char) NULL); + send_mess(card_index, READ_POSITION, (char*) NULL); recv_mess(card_index, axis_pos, 1); /* The return string will tell us how many axes this controller has */ @@ -771,7 +769,7 @@ static int motor_init() /* Determine if encoder present based on open/closed loop mode. */ sprintf(buff, "%dTC", motor_index + 1); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); loop_state = atoi(&buff[3]); /* Skip first 3 characters */ if (loop_state != 0) @@ -783,7 +781,7 @@ static int motor_init() /* Determine drive resolution. */ sprintf(buff, "%dTU", motor_index + 1); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); cntrl->drive_resolution[motor_index] = atof(&buff[3]); @@ -794,19 +792,19 @@ static int motor_init() /* Save home preset position. */ sprintf(buff, "%dXH", motor_index + 1); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); cntrl->home_preset[motor_index] = atof(&buff[3]); /* Determine low limit */ sprintf(buff, "%dTL", motor_index + 1); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); motor_info->low_limit = atof(&buff[3]); /* Determine high limit */ sprintf(buff, "%dTR", motor_index + 1); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); motor_info->high_limit = atof(&buff[3]); diff --git a/motorApp/NewportSrc/drvMM4000Asyn.c b/motorApp/NewportSrc/drvMM4000Asyn.c index 1e34802..16b39c8 100644 --- a/motorApp/NewportSrc/drvMM4000Asyn.c +++ b/motorApp/NewportSrc/drvMM4000Asyn.c @@ -2,10 +2,6 @@ FILENAME... drvMM4000Asyn.cc USAGE... Motor record asyn driver level support for Newport MM4000. -Version: $Revision: 15950 $ -Modified By: $Author: rivers $ -Last Modified: $Date: 2013-02-18 14:53:20 -0600 (Mon, 18 Feb 2013) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/NewportSrc/drvMM4000Asyn.c $ */ /* diff --git a/motorApp/NewportSrc/drvMMCom.h b/motorApp/NewportSrc/drvMMCom.h index 1799756..44949ea 100644 --- a/motorApp/NewportSrc/drvMMCom.h +++ b/motorApp/NewportSrc/drvMMCom.h @@ -3,9 +3,6 @@ FILENAME... drvMMCom.h USAGE... This file contains Newport Motion Master (MM) driver "include" information that is specific to Motion Master models 3000/4000. -Version: $Revision: 1.10 $ -Modified By: $Author: rivers $ -Last Modified: $Date: 2004-08-17 21:28:22 $ */ /* diff --git a/motorApp/NewportSrc/drvPM500.cc b/motorApp/NewportSrc/drvPM500.cc index a757314..8dc213a 100644 --- a/motorApp/NewportSrc/drvPM500.cc +++ b/motorApp/NewportSrc/drvPM500.cc @@ -2,10 +2,6 @@ FILENAME... drvPM500.cc USAGE... Motor record driver level support for Newport PM500. -Version: $Revision: 15617 $ -Modified By: $Author: rivers $ -Last Modified: $Date: 2012-12-06 16:17:36 -0600 (Thu, 06 Dec 2012) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/NewportSrc/drvPM500.cc $ */ /* Device Driver Support routines for PM500 motor controller */ @@ -59,6 +55,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#include +#include #include "motor.h" #include "NewportRegister.h" #include "drvMMCom.h" @@ -238,7 +236,7 @@ static int set_status(int card, int signal) /* Request the status and position of this motor */ sprintf(buff, "%sR", axis_name); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); rtnval = recv_mess(card, response, 1); if (rtnval > 0) { @@ -288,7 +286,7 @@ static int set_status(int card, int signal) /* Set Motor On/Off status */ sprintf(buff, "%sM?", axis_name); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); rtnval = recv_mess(card, response, 1); status.Bits.EA_POSITION = (int) atof(&response[2]); @@ -338,7 +336,7 @@ static int set_status(int card, int signal) { strcpy(buff, nodeptr->postmsgptr); strcat(buff, "\r"); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -545,7 +543,7 @@ static int motor_init() pasynOctetSyncIO->flush(cntrl->pasynUser); /* Send a SCUM 1 command to put device in this mode. */ - send_mess(card_index, "SCUM 1", (char) NULL); + send_mess(card_index, "SCUM 1", (char*) NULL); recv_mess(card_index, buff, 1); /* Set up basic controller parameters @@ -566,12 +564,12 @@ static int motor_init() * Bit 13=0, Eearly serial poll mapping * Bit 14=0, No SRQ assertion */ - send_mess(card_index, "SENAINT $AF", (char) NULL); + send_mess(card_index, "SENAINT $AF", (char*) NULL); recv_mess(card_index, buff, 1); /* Send a message and read response from controller to see if * it exists */ - send_mess(card_index, GET_IDENT, (char) NULL); + send_mess(card_index, GET_IDENT, (char*) NULL); status = recv_mess(card_index, buff, 1); /* Return value is length of response string */ } @@ -580,7 +578,7 @@ static int motor_init() { brdptr->localaddr = (char *) NULL; brdptr->motor_in_motion = 0; - send_mess(card_index, GET_IDENT, (char) NULL); /* Read controller ID string */ + send_mess(card_index, GET_IDENT, (char*) NULL); /* Read controller ID string */ recv_mess(card_index, buff, 1); strncpy(brdptr->ident, &buff[2], 50); /* Skip "XD" */ @@ -591,7 +589,7 @@ static int motor_init() int axis_name = (int) *PM500_axis_names[total_axis]; brdptr->motor_info[total_axis].motor_motion = NULL; sprintf(buff, "%cSTAT?", axis_name); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); if (buff[1] == 'E') break; @@ -616,7 +614,7 @@ static int motor_init() double res = 0.0; sprintf(buff, "%sCONFIG?", axis_name); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); recv_mess(card_index, buff, 1); firmware = &buff[8]; Debug(3, "motor_init: firmware = %s\n", firmware); diff --git a/motorApp/NewportSrc/drvXPSAsyn.c b/motorApp/NewportSrc/drvXPSAsyn.c index 0c4fa7b..eb1e865 100644 --- a/motorApp/NewportSrc/drvXPSAsyn.c +++ b/motorApp/NewportSrc/drvXPSAsyn.c @@ -2,10 +2,6 @@ FILENAME... drvXPSasyn.c USAGE... Newport XPS EPICS asyn motor device driver -Version: $Revision: 15944 $ -Modified By: $Author: rivers $ -Last Modified: $Date: 2013-02-18 14:50:16 -0600 (Mon, 18 Feb 2013) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/NewportSrc/drvXPSAsyn.c $ */ /* @@ -616,6 +612,10 @@ static int motorAxisSetDouble(AXIS_HDL pAxis, motorAxisParam_t function, double double positions[XPS_MAX_AXES] = {0.0}; if (pAxis == NULL) return MOTOR_AXIS_ERROR; + if (!pAxis->mutexId) { + PRINT(pAxis->logParam, MOTOR_ERROR, "motorAxisSetDouble[%d,%d]: invalid mutex ID. Call XPSConfigAxis first for initialization.\n", pAxis->card, pAxis->axis); + return MOTOR_AXIS_ERROR; + } else { if (epicsMutexLock( pAxis->mutexId ) == epicsMutexLockOK) @@ -941,6 +941,11 @@ static int motorAxisMove(AXIS_HDL pAxis, double position, int relative, if (pAxis == NULL) return MOTOR_AXIS_ERROR; + if (!pAxis->mutexId) { + PRINT(pAxis->logParam, MOTOR_ERROR, "motorAxisMove[%d,%d]: invalid mutex ID. Call XPSConfigAxis first for initialization.\n", pAxis->card, pAxis->axis); + return MOTOR_AXIS_ERROR; + } + PRINT(pAxis->logParam, FLOW, "Set card %d, axis %d move to %f, min vel=%f, max_vel=%f, accel=%f\n", pAxis->card, pAxis->axis, position, min_velocity, max_velocity, acceleration); diff --git a/motorApp/NewportSrc/drvXPSAsynAux.c b/motorApp/NewportSrc/drvXPSAsynAux.c index 11d2eb8..ab5671b 100644 --- a/motorApp/NewportSrc/drvXPSAsynAux.c +++ b/motorApp/NewportSrc/drvXPSAsynAux.c @@ -25,8 +25,8 @@ #include #include -#include #include +#include typedef struct { char *portName; diff --git a/motorApp/NewportSrc/hxp_drivers.cpp b/motorApp/NewportSrc/hxp_drivers.cpp index 1d00218..0ca5211 100644 --- a/motorApp/NewportSrc/hxp_drivers.cpp +++ b/motorApp/NewportSrc/hxp_drivers.cpp @@ -1,6904 +1,6899 @@ -/* - * Created source file hxp_drivers.cpp for API description - */ - - -#include -#include -#include -#include -#include "Socket.h" - -#ifdef _WIN32 - #define DLL _declspec(dllexport) - #include "strtok_r.h" -#else - #define DLL -#endif - -#include "hxp_drivers.h" - - - -#define SIZE_SMALL 1024 -#define SIZE_NOMINAL 1024 -#define SIZE_BIG 2048 -#define SIZE_HUGE 65536 - -#define SIZE_EXECUTE_METHOD 1024 - -#define SIZE_NAME 100 -#ifdef __cplusplus -extern "C" -{ -#else -#typedef int bool; /* C does not know bool, only C++ */ -#endif - - - -#define DLL_VERSION "Library version for HXP Firmware V1.3.x" - -/************************************************************************* -* Replace 'oldChar' by 'newChar' only between the startChar and endChar -*************************************************************************/ -void ReplaceCharacter (char *strSourceInOut, char oldChar, char newChar, char startChar, char endChar) -{ - char *pt; - char *ptNext; - ptNext = strSourceInOut; - do - { - pt = strchr(ptNext, startChar); - if (pt != NULL) - { - *pt++; - while ((pt != NULL) && (*pt != endChar)) - { - if (*pt == oldChar) - *pt = newChar; - pt++; - } - ptNext = pt++; - } - } - while ((pt != NULL) && (ptNext != NULL)); -} - -/************************************************************************* -* Delete space and tabulation characters between 'startChar' and 'endChar' -*************************************************************************/ -void CleanString (char *strSourceInOut, char startChar, char endChar) -{ - int len = 0; - int startIndex = 0; - int endIndex = 0; - int outputIndex = 0; - char outputString[SIZE_NOMINAL]; - len = strlen(strSourceInOut); - do - { - while ((strSourceInOut[startIndex] != startChar) && (startIndex < len) && (outputIndex < SIZE_NOMINAL)) - { - outputString[outputIndex] = strSourceInOut[startIndex]; - outputIndex++; - startIndex++; - } - while ((strSourceInOut[endIndex] != endChar) && (endIndex < len)) - endIndex++; - if ((startIndex != endIndex) && (startIndex < len)) - { - for (int i = startIndex; (i <= endIndex) && (outputIndex < SIZE_NOMINAL); i++) - { - if ((strSourceInOut[i] != ' ') && (strSourceInOut[i] != '\t')) - { - outputString[outputIndex] = strSourceInOut[i]; - outputIndex++; - } - } - endIndex++; - startIndex = endIndex; - } - } - while (startIndex < len); - outputString[outputIndex] = '\0'; - strcpy (strSourceInOut, outputString); -} - -/************************************************************************* -* Delete a specified characters -*************************************************************************/ -void DeleteCharacters (char *strSourceInOut, char *charactersToDelete) -{ - int len = 0; - int nbChar = 0; - int outputIndex = 0; - bool bCopy; - char outputString[SIZE_NOMINAL]; - len = strlen(strSourceInOut); - nbChar = strlen(charactersToDelete); - for (int i = 0; (i <= len) && (outputIndex < SIZE_NOMINAL); i++) - { - bCopy = true; - for (int j = 0; (j < nbChar) && (bCopy == true); j++) - { - if (strSourceInOut[i] == charactersToDelete[j]) - bCopy = false; - } - if (bCopy) - { - outputString[outputIndex] = strSourceInOut[i]; - outputIndex++; - } - } - outputString[outputIndex] = '\0'; - strcpy (strSourceInOut, outputString); -} - -/***********************************************************************/ -int __stdcall HXPTCP_ConnectToServer(char *Ip_Address, int Ip_Port, double TimeOut) -{ - return (ConnectToServer(Ip_Address, Ip_Port, TimeOut)); -} -/***********************************************************************/ -void __stdcall HXPTCP_SetTimeout(int SocketIndex, double Timeout) -{ - SetTCPTimeout(SocketIndex, Timeout); -} -/***********************************************************************/ -void __stdcall HXPTCP_CloseSocket(int SocketIndex) -{ - CloseSocket(SocketIndex); -} -/***********************************************************************/ -char * __stdcall HXPTCP_GetError(int SocketIndex) -{ - return (GetError(SocketIndex)); -} -/***********************************************************************/ -char * __stdcall HXPGetLibraryVersion(void) -{ - return (DLL_VERSION); -} - -/*********************************************************************** - * ControllerMotionKernelTimeLoadGet : Get controller motion kernel time load - * - * - Parameters : - * int SocketIndex - * double *CPUTotalLoadRatio - * double *CPUCorrectorLoadRatio - * double *CPUProfilerLoadRatio - * double *CPUServitudesLoadRatio - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPControllerMotionKernelTimeLoadGet (int SocketIndex, double * CPUTotalLoadRatio, double * CPUCorrectorLoadRatio, double * CPUProfilerLoadRatio, double * CPUServitudesLoadRatio) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "ControllerMotionKernelTimeLoadGet (double *,double *,double *,double *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CPUTotalLoadRatio); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CPUCorrectorLoadRatio); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CPUProfilerLoadRatio); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CPUServitudesLoadRatio); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * ElapsedTimeGet : Return elapsed time from controller power on - * - * - Parameters : - * int SocketIndex - * double *ElapsedTime - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPElapsedTimeGet (int SocketIndex, double * ElapsedTime) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "ElapsedTimeGet (double *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", ElapsedTime); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * ErrorStringGet : Return the error string corresponding to the error code - * - * - Parameters : - * int SocketIndex - * int ErrorCode - * char *ErrorString - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPErrorStringGet (int SocketIndex, int ErrorCode, char * ErrorString) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "ErrorStringGet (%d,char *)", ErrorCode); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (ErrorString, pt); - ptNext = strchr (ErrorString, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * FirmwareVersionGet : Return firmware version - * - * - Parameters : - * int SocketIndex - * char *Version - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPFirmwareVersionGet (int SocketIndex, char * Version) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "FirmwareVersionGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (Version, pt); - ptNext = strchr (Version, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * TCLScriptExecute : Execute a TCL script from a TCL file - * - * - Parameters : - * int SocketIndex - * char *TCLFileName - * char *TaskName - * char *ParametersList - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPTCLScriptExecute (int SocketIndex, char * TCLFileName, char * TaskName, char * ParametersList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "TCLScriptExecute (%s,%s,%s)", TCLFileName, TaskName, ParametersList); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * TCLScriptExecuteAndWait : Execute a TCL script from a TCL file and wait the end of execution to return - * - * - Parameters : - * int SocketIndex - * char *TCLFileName - * char *TaskName - * char *InputParametersList - * char *OutputParametersList - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPTCLScriptExecuteAndWait (int SocketIndex, char * TCLFileName, char * TaskName, char * InputParametersList, char * OutputParametersList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "TCLScriptExecuteAndWait (%s,%s,%s,char *)", TCLFileName, TaskName, InputParametersList); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (OutputParametersList, pt); - ptNext = strchr (OutputParametersList, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * TCLScriptKill : Kill TCL Task - * - * - Parameters : - * int SocketIndex - * char *TaskName - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPTCLScriptKill (int SocketIndex, char * TaskName) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "TCLScriptKill (%s)", TaskName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * TimerGet : Get a timer - * - * - Parameters : - * int SocketIndex - * char *TimerName - * int *FrequencyTicks - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPTimerGet (int SocketIndex, char * TimerName, int * FrequencyTicks) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "TimerGet (%s,int *)", TimerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", FrequencyTicks); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * TimerSet : Set a timer - * - * - Parameters : - * int SocketIndex - * char *TimerName - * int FrequencyTicks - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPTimerSet (int SocketIndex, char * TimerName, int FrequencyTicks) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "TimerSet (%s,%d)", TimerName, FrequencyTicks); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * Reboot : Reboot the controller - * - * - Parameters : - * int SocketIndex - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPReboot (int SocketIndex) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "Reboot ()"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * Login : Log in - * - * - Parameters : - * int SocketIndex - * char *Name - * char *Password - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPLogin (int SocketIndex, char * Name, char * Password) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "Login (%s,%s)", Name, Password); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * CloseAllOtherSockets : Close all socket beside the one used to send this command - * - * - Parameters : - * int SocketIndex - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPCloseAllOtherSockets (int SocketIndex) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "CloseAllOtherSockets ()"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventAdd : ** OBSOLETE ** Add an event - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * char *EventName - * char *EventParameter - * char *ActionName - * char *ActionParameter1 - * char *ActionParameter2 - * char *ActionParameter3 - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventAdd (int SocketIndex, char * PositionerName, char * EventName, char * EventParameter, char * ActionName, char * ActionParameter1, char * ActionParameter2, char * ActionParameter3) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "EventAdd (%s,%s,%s,%s,%s,%s,%s)", PositionerName, EventName, EventParameter, ActionName, ActionParameter1, ActionParameter2, ActionParameter3); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventGet : ** OBSOLETE ** Read events and actions list - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * char *EventsAndActionsList - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventGet (int SocketIndex, char * PositionerName, char * EventsAndActionsList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "EventGet (%s,char *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (EventsAndActionsList, pt); - ptNext = strchr (EventsAndActionsList, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventRemove : ** OBSOLETE ** Delete an event - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * char *EventName - * char *EventParameter - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventRemove (int SocketIndex, char * PositionerName, char * EventName, char * EventParameter) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "EventRemove (%s,%s,%s)", PositionerName, EventName, EventParameter); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventWait : ** OBSOLETE ** Wait an event - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * char *EventName - * char *EventParameter - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventWait (int SocketIndex, char * PositionerName, char * EventName, char * EventParameter) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "EventWait (%s,%s,%s)", PositionerName, EventName, EventParameter); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventExtendedConfigurationTriggerSet : Configure one or several events - * - * - Parameters : - * int SocketIndex - * int nbElement - * char *ExtendedEventName - * char *EventParameter1 - * char *EventParameter2 - * char *EventParameter3 - * char *EventParameter4 - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventExtendedConfigurationTriggerSet (int SocketIndex, int NbElements, char * ExtendedEventNameList, char * EventParameter1List, char * EventParameter2List, char * EventParameter3List, char * EventParameter4List) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Split list */ - char *token; - char seps[] = " \t;"; - int indice; - char list [SIZE_NOMINAL]; - char *list_r; - char subString[] = "{}"; - - char (*stringArray0)[SIZE_NAME]; - stringArray0 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, ExtendedEventNameList, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray0[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray0[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - char (*stringArray1)[SIZE_NAME]; - stringArray1 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, EventParameter1List, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray1[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray1[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray1[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray1[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - char (*stringArray2)[SIZE_NAME]; - stringArray2 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, EventParameter2List, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray2[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray2[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray2[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray2[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - char (*stringArray3)[SIZE_NAME]; - stringArray3 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, EventParameter3List, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray3[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray3[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray3[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray3[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - char (*stringArray4)[SIZE_NAME]; - stringArray4 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, EventParameter4List, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray4[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray4[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray4[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray4[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - - /* Convert to string */ - sprintf (ExecuteMethod, "EventExtendedConfigurationTriggerSet ("); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "%s,%s,%s,%s,%s", stringArray0[i], stringArray1[i], stringArray2[i], stringArray3[i], stringArray4[i]); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Clear memory */ - delete [] stringArray0; - delete [] stringArray1; - delete [] stringArray2; - delete [] stringArray3; - delete [] stringArray4; - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventExtendedConfigurationTriggerGet : Read the event configuration - * - * - Parameters : - * int SocketIndex - * char *EventTriggerConfiguration - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventExtendedConfigurationTriggerGet (int SocketIndex, char * EventTriggerConfiguration) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "EventExtendedConfigurationTriggerGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (EventTriggerConfiguration, pt); - ptNext = strchr (EventTriggerConfiguration, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventExtendedConfigurationActionSet : Configure one or several actions - * - * - Parameters : - * int SocketIndex - * int nbElement - * char *ExtendedActionName - * char *ActionParameter1 - * char *ActionParameter2 - * char *ActionParameter3 - * char *ActionParameter4 - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventExtendedConfigurationActionSet (int SocketIndex, int NbElements, char * ExtendedActionNameList, char * ActionParameter1List, char * ActionParameter2List, char * ActionParameter3List, char * ActionParameter4List) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Split list */ - char *token; - char seps[] = " \t;"; - int indice; - char list [SIZE_NOMINAL]; - char *list_r; - char subString[] = "{}"; - - char (*stringArray0)[SIZE_NAME]; - stringArray0 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, ExtendedActionNameList, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray0[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray0[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - char (*stringArray1)[SIZE_NAME]; - stringArray1 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, ActionParameter1List, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray1[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray1[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray1[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray1[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - char (*stringArray2)[SIZE_NAME]; - stringArray2 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, ActionParameter2List, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray2[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray2[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray2[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray2[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - char (*stringArray3)[SIZE_NAME]; - stringArray3 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, ActionParameter3List, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray3[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray3[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray3[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray3[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - char (*stringArray4)[SIZE_NAME]; - stringArray4 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, ActionParameter4List, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray4[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray4[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray4[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray4[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - - /* Convert to string */ - sprintf (ExecuteMethod, "EventExtendedConfigurationActionSet ("); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "%s,%s,%s,%s,%s", stringArray0[i], stringArray1[i], stringArray2[i], stringArray3[i], stringArray4[i]); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Clear memory */ - delete [] stringArray0; - delete [] stringArray1; - delete [] stringArray2; - delete [] stringArray3; - delete [] stringArray4; - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventExtendedConfigurationActionGet : Read the action configuration - * - * - Parameters : - * int SocketIndex - * char *ActionConfiguration - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventExtendedConfigurationActionGet (int SocketIndex, char * ActionConfiguration) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "EventExtendedConfigurationActionGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (ActionConfiguration, pt); - ptNext = strchr (ActionConfiguration, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventExtendedStart : Launch the last event and action configuration and return an ID - * - * - Parameters : - * int SocketIndex - * int *ID - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventExtendedStart (int SocketIndex, int * ID) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "EventExtendedStart (int *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", ID); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventExtendedAllGet : Read all event and action configurations - * - * - Parameters : - * int SocketIndex - * char *EventActionConfigurations - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventExtendedAllGet (int SocketIndex, char * EventActionConfigurations) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); - - /* Convert to string */ - sprintf (ExecuteMethod, "EventExtendedAllGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (EventActionConfigurations, pt); - ptNext = strchr (EventActionConfigurations, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventExtendedGet : Read the event and action configuration defined by ID - * - * - Parameters : - * int SocketIndex - * int ID - * char *EventTriggerConfiguration - * char *ActionConfiguration - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventExtendedGet (int SocketIndex, int ID, char * EventTriggerConfiguration, char * ActionConfiguration) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "EventExtendedGet (%d,char *,char *)", ID); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (EventTriggerConfiguration, pt); - ptNext = strchr (EventTriggerConfiguration, ','); - if (ptNext != NULL) *ptNext = '\0'; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (ActionConfiguration, pt); - ptNext = strchr (ActionConfiguration, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventExtendedRemove : Remove the event and action configuration defined by ID - * - * - Parameters : - * int SocketIndex - * int ID - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventExtendedRemove (int SocketIndex, int ID) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "EventExtendedRemove (%d)", ID); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventExtendedWait : Wait events from the last event configuration - * - * - Parameters : - * int SocketIndex - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventExtendedWait (int SocketIndex) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "EventExtendedWait ()"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringConfigurationGet : Read different mnemonique type - * - * - Parameters : - * int SocketIndex - * char *Type - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringConfigurationGet (int SocketIndex, char * Type) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringConfigurationGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (Type, pt); - ptNext = strchr (Type, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringConfigurationSet : Configuration acquisition - * - * - Parameters : - * int SocketIndex - * int nbElement - * char *Type - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringConfigurationSet (int SocketIndex, int NbElements, char * TypeList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Split list */ - char *token; - char seps[] = " \t;"; - int indice; - char list [SIZE_NOMINAL]; - char *list_r; - char subString[] = "{}"; - - char (*stringArray0)[SIZE_NAME]; - stringArray0 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, TypeList, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray0[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray0[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringConfigurationSet ("); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "%s", stringArray0[i]); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Clear memory */ - delete [] stringArray0; - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringCurrentNumberGet : Maximum number of samples and current number during acquisition - * - * - Parameters : - * int SocketIndex - * int *CurrentNumber - * int *MaximumSamplesNumber - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringCurrentNumberGet (int SocketIndex, int * CurrentNumber, int * MaximumSamplesNumber) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringCurrentNumberGet (int *,int *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", CurrentNumber); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", MaximumSamplesNumber); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringStopAndSave : Stop acquisition and save data - * - * - Parameters : - * int SocketIndex - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringStopAndSave (int SocketIndex) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringStopAndSave ()"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringDataAcquire : Acquire a configured data - * - * - Parameters : - * int SocketIndex - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringDataAcquire (int SocketIndex) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringDataAcquire ()"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringDataGet : Get a data line from gathering buffer - * - * - Parameters : - * int SocketIndex - * int IndexPoint - * char *DataBufferLine - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringDataGet (int SocketIndex, int IndexPoint, char * DataBufferLine) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringDataGet (%d,char *)", IndexPoint); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (DataBufferLine, pt); - ptNext = strchr (DataBufferLine, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringReset : Empty the gathered data in memory to start new gathering from scratch - * - * - Parameters : - * int SocketIndex - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringReset (int SocketIndex) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringReset ()"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringRun : Start a new gathering - * - * - Parameters : - * int SocketIndex - * int DataNumber - * int Divisor - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringRun (int SocketIndex, int DataNumber, int Divisor) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringRun (%d,%d)", DataNumber, Divisor); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringStop : Stop the data gathering (without saving to file) - * - * - Parameters : - * int SocketIndex - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringStop (int SocketIndex) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringStop ()"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringExternalConfigurationSet : Configuration acquisition - * - * - Parameters : - * int SocketIndex - * int nbElement - * char *Type - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringExternalConfigurationSet (int SocketIndex, int NbElements, char * TypeList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Split list */ - char *token; - char seps[] = " \t;"; - int indice; - char list [SIZE_NOMINAL]; - char *list_r; - char subString[] = "{}"; - - char (*stringArray0)[SIZE_NAME]; - stringArray0 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, TypeList, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray0[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray0[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringExternalConfigurationSet ("); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "%s", stringArray0[i]); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Clear memory */ - delete [] stringArray0; - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringExternalConfigurationGet : Read different mnemonique type - * - * - Parameters : - * int SocketIndex - * char *Type - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringExternalConfigurationGet (int SocketIndex, char * Type) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringExternalConfigurationGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (Type, pt); - ptNext = strchr (Type, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringExternalCurrentNumberGet : Maximum number of samples and current number during acquisition - * - * - Parameters : - * int SocketIndex - * int *CurrentNumber - * int *MaximumSamplesNumber - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringExternalCurrentNumberGet (int SocketIndex, int * CurrentNumber, int * MaximumSamplesNumber) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringExternalCurrentNumberGet (int *,int *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", CurrentNumber); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", MaximumSamplesNumber); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringExternalStopAndSave : Stop acquisition and save data - * - * - Parameters : - * int SocketIndex - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringExternalStopAndSave (int SocketIndex) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringExternalStopAndSave ()"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GlobalArrayGet : Get global array value - * - * - Parameters : - * int SocketIndex - * int Number - * char *ValueString - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGlobalArrayGet (int SocketIndex, int Number, char * ValueString) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GlobalArrayGet (%d,char *)", Number); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (ValueString, pt); - ptNext = strchr (ValueString, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GlobalArraySet : Set global array value - * - * - Parameters : - * int SocketIndex - * int Number - * char *ValueString - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGlobalArraySet (int SocketIndex, int Number, char * ValueString) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GlobalArraySet (%d,%s)", Number, ValueString); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * DoubleGlobalArrayGet : Get double global array value - * - * - Parameters : - * int SocketIndex - * int Number - * double *DoubleValue - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPDoubleGlobalArrayGet (int SocketIndex, int Number, double * DoubleValue) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "DoubleGlobalArrayGet (%d,double *)", Number); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", DoubleValue); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * DoubleGlobalArraySet : Set double global array value - * - * - Parameters : - * int SocketIndex - * int Number - * double DoubleValue - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPDoubleGlobalArraySet (int SocketIndex, int Number, double DoubleValue) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "DoubleGlobalArraySet (%d,%.13g)", Number, DoubleValue); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GPIOAnalogGet : Read analog input or analog output for one or few input - * - * - Parameters : - * int SocketIndex - * int nbElement - * char *GPIOName - * double *AnalogValue - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGPIOAnalogGet (int SocketIndex, int NbElements, char * GPIONameList, double AnalogValue[]) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Split list */ - char *token; - char seps[] = " \t;"; - int indice; - char list [SIZE_NOMINAL]; - char *list_r; - char subString[] = "{}"; - - char (*stringArray0)[SIZE_NAME]; - stringArray0 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, GPIONameList, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray0[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray0[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - - /* Convert to string */ - sprintf (ExecuteMethod, "GPIOAnalogGet ("); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "%s,double *", stringArray0[i]); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Clear memory */ - delete [] stringArray0; - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - - for (int i = 0; i < NbElements; i++) - { - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", &AnalogValue[i]); - } - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GPIOAnalogSet : Set analog output for one or few output - * - * - Parameters : - * int SocketIndex - * int nbElement - * char *GPIOName - * double AnalogOutputValue - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGPIOAnalogSet (int SocketIndex, int NbElements, char * GPIONameList, double AnalogOutputValue[]) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Split list */ - char *token; - char seps[] = " \t;"; - int indice; - char list [SIZE_NOMINAL]; - char *list_r; - char subString[] = "{}"; - - char (*stringArray0)[SIZE_NAME]; - stringArray0 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, GPIONameList, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray0[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray0[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - - /* Convert to string */ - sprintf (ExecuteMethod, "GPIOAnalogSet ("); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "%s,%.13g", stringArray0[i], AnalogOutputValue[i]); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Clear memory */ - delete [] stringArray0; - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GPIOAnalogGainGet : Read analog input gain (1, 2, 4 or 8) for one or few input - * - * - Parameters : - * int SocketIndex - * int nbElement - * char *GPIOName - * int *AnalogInputGainValue - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGPIOAnalogGainGet (int SocketIndex, int NbElements, char * GPIONameList, int AnalogInputGainValue[]) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Split list */ - char *token; - char seps[] = " \t;"; - int indice; - char list [SIZE_NOMINAL]; - char *list_r; - char subString[] = "{}"; - - char (*stringArray0)[SIZE_NAME]; - stringArray0 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, GPIONameList, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray0[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray0[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - - /* Convert to string */ - sprintf (ExecuteMethod, "GPIOAnalogGainGet ("); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "%s,int *", stringArray0[i]); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Clear memory */ - delete [] stringArray0; - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - - for (int i = 0; i < NbElements; i++) - { - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", &AnalogInputGainValue[i]); - } - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GPIOAnalogGainSet : Set analog input gain (1, 2, 4 or 8) for one or few input - * - * - Parameters : - * int SocketIndex - * int nbElement - * char *GPIOName - * int AnalogInputGainValue - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGPIOAnalogGainSet (int SocketIndex, int NbElements, char * GPIONameList, int AnalogInputGainValue[]) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Split list */ - char *token; - char seps[] = " \t;"; - int indice; - char list [SIZE_NOMINAL]; - char *list_r; - char subString[] = "{}"; - - char (*stringArray0)[SIZE_NAME]; - stringArray0 = new char [NbElements][SIZE_NAME]; - indice = 0; - strncpyWithEOS(list, GPIONameList, SIZE_NOMINAL, SIZE_NOMINAL); - ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ - CleanString(list, '{', '}'); - list_r = NULL; - token = strtok_r (list, seps, &list_r); - while ((NULL != token) && (indice < NbElements)) - { - memset(stringArray0[indice],'\0', SIZE_NAME); - strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); - ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); - DeleteCharacters (stringArray0[indice], subString); - token = strtok_r (NULL, seps, &list_r); - indice++; - } - - /* Convert to string */ - sprintf (ExecuteMethod, "GPIOAnalogGainSet ("); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "%s,%d", stringArray0[i], AnalogInputGainValue[i]); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Clear memory */ - delete [] stringArray0; - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GPIODigitalGet : Read digital output or digital input - * - * - Parameters : - * int SocketIndex - * char *GPIOName - * unsigned short *DigitalValue - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGPIODigitalGet (int SocketIndex, char * GPIOName, unsigned short * DigitalValue) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GPIODigitalGet (%s,unsigned short *)", GPIOName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%hu", DigitalValue); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GPIODigitalSet : Set Digital Output for one or few output TTL - * - * - Parameters : - * int SocketIndex - * char *GPIOName - * unsigned short Mask - * unsigned short DigitalOutputValue - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGPIODigitalSet (int SocketIndex, char * GPIOName, unsigned short Mask, unsigned short DigitalOutputValue) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GPIODigitalSet (%s,%hu,%hu)", GPIOName, Mask, DigitalOutputValue); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupCorrectorOutputGet : Return corrector outputs - * - * - Parameters : - * int SocketIndex - * char *GroupName - * int nbElement - * double *CorrectorOutput - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupCorrectorOutputGet (int SocketIndex, char * GroupName, int NbElements, double CorrectorOutput[]) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupCorrectorOutputGet (%s,", GroupName); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "double *"); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - - for (int i = 0; i < NbElements; i++) - { - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", &CorrectorOutput[i]); - } - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupHomeSearch : Start home search sequence - * - * - Parameters : - * int SocketIndex - * char *GroupName - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupHomeSearch (int SocketIndex, char * GroupName) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupHomeSearch (%s)", GroupName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupHomeSearchAndRelativeMove : Start home search sequence and execute a displacement - * - * - Parameters : - * int SocketIndex - * char *GroupName - * double TargetDisplacement - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupHomeSearchAndRelativeMove (int SocketIndex, char * GroupName, int NbElements, double TargetDisplacement[]) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupHomeSearchAndRelativeMove (%s,", GroupName); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "%.13g", TargetDisplacement[i]); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupInitialize : Start the initialization - * - * - Parameters : - * int SocketIndex - * char *GroupName - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupInitialize (int SocketIndex, char * GroupName) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupInitialize (%s)", GroupName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupInitializeWithEncoderCalibration : Start the initialization with encoder calibration - * - * - Parameters : - * int SocketIndex - * char *GroupName - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupInitializeWithEncoderCalibration (int SocketIndex, char * GroupName) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupInitializeWithEncoderCalibration (%s)", GroupName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupKill : Kill the group - * - * - Parameters : - * int SocketIndex - * char *GroupName - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupKill (int SocketIndex, char * GroupName) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupKill (%s)", GroupName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupMoveAbort : Abort a move - * - * - Parameters : - * int SocketIndex - * char *GroupName - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupMoveAbort (int SocketIndex, char * GroupName) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupMoveAbort (%s)", GroupName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupMoveAbsolute : Do an absolute move - * - * - Parameters : - * int SocketIndex - * char *GroupName - * double TargetPosition - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupMoveAbsolute (int SocketIndex, char * GroupName, int NbElements, double TargetPosition[]) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupMoveAbsolute (%s,", GroupName); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "%.13g", TargetPosition[i]); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupMoveRelative : Do a relative move - * - * - Parameters : - * int SocketIndex - * char *GroupName - * double TargetDisplacement - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupMoveRelative (int SocketIndex, char * GroupName, int NbElements, double TargetDisplacement[]) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupMoveRelative (%s,", GroupName); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "%.13g", TargetDisplacement[i]); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupMotionDisable : Set Motion disable on selected group - * - * - Parameters : - * int SocketIndex - * char *GroupName - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupMotionDisable (int SocketIndex, char * GroupName) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupMotionDisable (%s)", GroupName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupMotionEnable : Set Motion enable on selected group - * - * - Parameters : - * int SocketIndex - * char *GroupName - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupMotionEnable (int SocketIndex, char * GroupName) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupMotionEnable (%s)", GroupName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupPositionCorrectedProfilerGet : Return corrected profiler positions - * - * - Parameters : - * int SocketIndex - * char *GroupName - * double PositionX - * double PositionY - * double *CorrectedProfilerPositionX - * double *CorrectedProfilerPositionY - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupPositionCorrectedProfilerGet (int SocketIndex, char * GroupName, double PositionX, double PositionY, double * CorrectedProfilerPositionX, double * CorrectedProfilerPositionY) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupPositionCorrectedProfilerGet (%s,%.13g,%.13g,double *,double *)", GroupName, PositionX, PositionY); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CorrectedProfilerPositionX); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CorrectedProfilerPositionY); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupPositionCurrentGet : Return current positions - * - * - Parameters : - * int SocketIndex - * char *GroupName - * int nbElement - * double *CurrentEncoderPosition - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupPositionCurrentGet (int SocketIndex, char * GroupName, int NbElements, double CurrentEncoderPosition[]) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupPositionCurrentGet (%s,", GroupName); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "double *"); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - - for (int i = 0; i < NbElements; i++) - { - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", &CurrentEncoderPosition[i]); - } - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupPositionSetpointGet : Return setpoint positions - * - * - Parameters : - * int SocketIndex - * char *GroupName - * int nbElement - * double *SetPointPosition - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupPositionSetpointGet (int SocketIndex, char * GroupName, int NbElements, double SetPointPosition[]) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupPositionSetpointGet (%s,", GroupName); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "double *"); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - - for (int i = 0; i < NbElements; i++) - { - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", &SetPointPosition[i]); - } - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupPositionTargetGet : Return target positions - * - * - Parameters : - * int SocketIndex - * char *GroupName - * int nbElement - * double *TargetPosition - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupPositionTargetGet (int SocketIndex, char * GroupName, int NbElements, double TargetPosition[]) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - char temp[SIZE_NOMINAL]; - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupPositionTargetGet (%s,", GroupName); - for (int i = 0; i < NbElements; i++) - { - sprintf (temp, "double *"); - strncat (ExecuteMethod, temp, SIZE_SMALL); - if ((i + 1) < NbElements) - { - strncat (ExecuteMethod, ",", SIZE_SMALL); - } - } - strcat (ExecuteMethod, ")"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - - for (int i = 0; i < NbElements; i++) - { - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", &TargetPosition[i]); - } - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupStatusGet : Return group status - * - * - Parameters : - * int SocketIndex - * char *GroupName - * int *Status - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupStatusGet (int SocketIndex, char * GroupName, int * Status) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupStatusGet (%s,int *)", GroupName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", Status); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupStatusStringGet : Return the group status string corresponding to the group status code - * - * - Parameters : - * int SocketIndex - * int GroupStatusCode - * char *GroupStatusString - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupStatusStringGet (int SocketIndex, int GroupStatusCode, char * GroupStatusString) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupStatusStringGet (%d,char *)", GroupStatusCode); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (GroupStatusString, pt); - ptNext = strchr (GroupStatusString, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * KillAll : Put all groups in 'Not initialized' state - * - * - Parameters : - * int SocketIndex - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPKillAll (int SocketIndex) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "KillAll ()"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * RestartApplication : Restart the Controller - * - * - Parameters : - * int SocketIndex - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPRestartApplication (int SocketIndex) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "RestartApplication ()"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerBacklashGet : Read backlash value and status - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double *BacklashValue - * char *BacklaskStatus - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerBacklashGet (int SocketIndex, char * PositionerName, double * BacklashValue, char * BacklaskStatus) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerBacklashGet (%s,double *,char *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", BacklashValue); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (BacklaskStatus, pt); - ptNext = strchr (BacklaskStatus, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerBacklashSet : Set backlash value - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double BacklashValue - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerBacklashSet (int SocketIndex, char * PositionerName, double BacklashValue) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerBacklashSet (%s,%.13g)", PositionerName, BacklashValue); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerBacklashEnable : Enable the backlash - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerBacklashEnable (int SocketIndex, char * PositionerName) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerBacklashEnable (%s)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerBacklashDisable : Disable the backlash - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerBacklashDisable (int SocketIndex, char * PositionerName) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerBacklashDisable (%s)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerCorrectorNotchFiltersSet : Update filters parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double NotchFrequency1 - * double NotchBandwith1 - * double NotchGain1 - * double NotchFrequency2 - * double NotchBandwith2 - * double NotchGain2 - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerCorrectorNotchFiltersSet (int SocketIndex, char * PositionerName, double NotchFrequency1, double NotchBandwith1, double NotchGain1, double NotchFrequency2, double NotchBandwith2, double NotchGain2) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerCorrectorNotchFiltersSet (%s,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", PositionerName, NotchFrequency1, NotchBandwith1, NotchGain1, NotchFrequency2, NotchBandwith2, NotchGain2); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerCorrectorNotchFiltersGet : Read filters parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double *NotchFrequency1 - * double *NotchBandwith1 - * double *NotchGain1 - * double *NotchFrequency2 - * double *NotchBandwith2 - * double *NotchGain2 - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerCorrectorNotchFiltersGet (int SocketIndex, char * PositionerName, double * NotchFrequency1, double * NotchBandwith1, double * NotchGain1, double * NotchFrequency2, double * NotchBandwith2, double * NotchGain2) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerCorrectorNotchFiltersGet (%s,double *,double *,double *,double *,double *,double *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", NotchFrequency1); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", NotchBandwith1); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", NotchGain1); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", NotchFrequency2); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", NotchBandwith2); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", NotchGain2); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerCorrectorPIDFFAccelerationSet : Update corrector parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * bool ClosedLoopStatus - * double KP - * double KI - * double KD - * double KS - * double IntegrationTime - * double DerivativeFilterCutOffFrequency - * double GKP - * double GKI - * double GKD - * double KForm - * double FeedForwardGainAcceleration - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerCorrectorPIDFFAccelerationSet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double KD, double KS, double IntegrationTime, double DerivativeFilterCutOffFrequency, double GKP, double GKI, double GKD, double KForm, double FeedForwardGainAcceleration) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerCorrectorPIDFFAccelerationSet (%s,%d,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", PositionerName, ClosedLoopStatus, KP, KI, KD, KS, IntegrationTime, DerivativeFilterCutOffFrequency, GKP, GKI, GKD, KForm, FeedForwardGainAcceleration); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerCorrectorPIDFFAccelerationGet : Read corrector parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * bool *ClosedLoopStatus - * double *KP - * double *KI - * double *KD - * double *KS - * double *IntegrationTime - * double *DerivativeFilterCutOffFrequency - * double *GKP - * double *GKI - * double *GKD - * double *KForm - * double *FeedForwardGainAcceleration - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerCorrectorPIDFFAccelerationGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * KD, double * KS, double * IntegrationTime, double * DerivativeFilterCutOffFrequency, double * GKP, double * GKI, double * GKD, double * KForm, double * FeedForwardGainAcceleration) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - int boolScanTmp; - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerCorrectorPIDFFAccelerationGet (%s,bool *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", &boolScanTmp); - *ClosedLoopStatus = (bool) boolScanTmp; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KP); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KI); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KD); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KS); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", IntegrationTime); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", DerivativeFilterCutOffFrequency); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", GKP); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", GKI); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", GKD); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KForm); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", FeedForwardGainAcceleration); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerCorrectorPIDFFVelocitySet : Update corrector parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * bool ClosedLoopStatus - * double KP - * double KI - * double KD - * double KS - * double IntegrationTime - * double DerivativeFilterCutOffFrequency - * double GKP - * double GKI - * double GKD - * double KForm - * double FeedForwardGainVelocity - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerCorrectorPIDFFVelocitySet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double KD, double KS, double IntegrationTime, double DerivativeFilterCutOffFrequency, double GKP, double GKI, double GKD, double KForm, double FeedForwardGainVelocity) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerCorrectorPIDFFVelocitySet (%s,%d,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", PositionerName, ClosedLoopStatus, KP, KI, KD, KS, IntegrationTime, DerivativeFilterCutOffFrequency, GKP, GKI, GKD, KForm, FeedForwardGainVelocity); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerCorrectorPIDFFVelocityGet : Read corrector parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * bool *ClosedLoopStatus - * double *KP - * double *KI - * double *KD - * double *KS - * double *IntegrationTime - * double *DerivativeFilterCutOffFrequency - * double *GKP - * double *GKI - * double *GKD - * double *KForm - * double *FeedForwardGainVelocity - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerCorrectorPIDFFVelocityGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * KD, double * KS, double * IntegrationTime, double * DerivativeFilterCutOffFrequency, double * GKP, double * GKI, double * GKD, double * KForm, double * FeedForwardGainVelocity) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - int boolScanTmp; - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerCorrectorPIDFFVelocityGet (%s,bool *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", &boolScanTmp); - *ClosedLoopStatus = (bool) boolScanTmp; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KP); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KI); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KD); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KS); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", IntegrationTime); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", DerivativeFilterCutOffFrequency); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", GKP); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", GKI); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", GKD); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KForm); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", FeedForwardGainVelocity); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerCorrectorPIDDualFFVoltageSet : Update corrector parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * bool ClosedLoopStatus - * double KP - * double KI - * double KD - * double KS - * double IntegrationTime - * double DerivativeFilterCutOffFrequency - * double GKP - * double GKI - * double GKD - * double KForm - * double FeedForwardGainVelocity - * double FeedForwardGainAcceleration - * double Friction - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerCorrectorPIDDualFFVoltageSet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double KD, double KS, double IntegrationTime, double DerivativeFilterCutOffFrequency, double GKP, double GKI, double GKD, double KForm, double FeedForwardGainVelocity, double FeedForwardGainAcceleration, double Friction) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerCorrectorPIDDualFFVoltageSet (%s,%d,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", PositionerName, ClosedLoopStatus, KP, KI, KD, KS, IntegrationTime, DerivativeFilterCutOffFrequency, GKP, GKI, GKD, KForm, FeedForwardGainVelocity, FeedForwardGainAcceleration, Friction); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerCorrectorPIDDualFFVoltageGet : Read corrector parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * bool *ClosedLoopStatus - * double *KP - * double *KI - * double *KD - * double *KS - * double *IntegrationTime - * double *DerivativeFilterCutOffFrequency - * double *GKP - * double *GKI - * double *GKD - * double *KForm - * double *FeedForwardGainVelocity - * double *FeedForwardGainAcceleration - * double *Friction - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerCorrectorPIDDualFFVoltageGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * KD, double * KS, double * IntegrationTime, double * DerivativeFilterCutOffFrequency, double * GKP, double * GKI, double * GKD, double * KForm, double * FeedForwardGainVelocity, double * FeedForwardGainAcceleration, double * Friction) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - int boolScanTmp; - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerCorrectorPIDDualFFVoltageGet (%s,bool *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", &boolScanTmp); - *ClosedLoopStatus = (bool) boolScanTmp; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KP); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KI); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KD); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KS); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", IntegrationTime); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", DerivativeFilterCutOffFrequency); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", GKP); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", GKI); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", GKD); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KForm); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", FeedForwardGainVelocity); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", FeedForwardGainAcceleration); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", Friction); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerCorrectorPIPositionSet : Update corrector parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * bool ClosedLoopStatus - * double KP - * double KI - * double IntegrationTime - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerCorrectorPIPositionSet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double IntegrationTime) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerCorrectorPIPositionSet (%s,%d,%.13g,%.13g,%.13g)", PositionerName, ClosedLoopStatus, KP, KI, IntegrationTime); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerCorrectorPIPositionGet : Read corrector parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * bool *ClosedLoopStatus - * double *KP - * double *KI - * double *IntegrationTime - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerCorrectorPIPositionGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * IntegrationTime) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - int boolScanTmp; - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerCorrectorPIPositionGet (%s,bool *,double *,double *,double *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", &boolScanTmp); - *ClosedLoopStatus = (bool) boolScanTmp; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KP); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", KI); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", IntegrationTime); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerCorrectorTypeGet : Read corrector type - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * char *CorrectorType - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerCorrectorTypeGet (int SocketIndex, char * PositionerName, char * CorrectorType) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerCorrectorTypeGet (%s,char *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (CorrectorType, pt); - ptNext = strchr (CorrectorType, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerCurrentVelocityAccelerationFiltersSet : Set current velocity and acceleration cut off frequencies - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double CurrentVelocityCutOffFrequency - * double CurrentAccelerationCutOffFrequency - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerCurrentVelocityAccelerationFiltersSet (int SocketIndex, char * PositionerName, double CurrentVelocityCutOffFrequency, double CurrentAccelerationCutOffFrequency) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerCurrentVelocityAccelerationFiltersSet (%s,%.13g,%.13g)", PositionerName, CurrentVelocityCutOffFrequency, CurrentAccelerationCutOffFrequency); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerCurrentVelocityAccelerationFiltersGet : Get current velocity and acceleration cut off frequencies - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double *CurrentVelocityCutOffFrequency - * double *CurrentAccelerationCutOffFrequency - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerCurrentVelocityAccelerationFiltersGet (int SocketIndex, char * PositionerName, double * CurrentVelocityCutOffFrequency, double * CurrentAccelerationCutOffFrequency) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerCurrentVelocityAccelerationFiltersGet (%s,double *,double *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CurrentVelocityCutOffFrequency); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CurrentAccelerationCutOffFrequency); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerDriverStatusGet : Read positioner driver status - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * int *DriverStatus - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerDriverStatusGet (int SocketIndex, char * PositionerName, int * DriverStatus) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerDriverStatusGet (%s,int *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", DriverStatus); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerDriverStatusStringGet : Return the positioner driver status string corresponding to the positioner error code - * - * - Parameters : - * int SocketIndex - * int PositionerDriverStatus - * char *PositionerDriverStatusString - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerDriverStatusStringGet (int SocketIndex, int PositionerDriverStatus, char * PositionerDriverStatusString) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerDriverStatusStringGet (%d,char *)", PositionerDriverStatus); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (PositionerDriverStatusString, pt); - ptNext = strchr (PositionerDriverStatusString, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerEncoderAmplitudeValuesGet : Read analog interpolated encoder amplitude values - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double *CalibrationSinusAmplitude - * double *CurrentSinusAmplitude - * double *CalibrationCosinusAmplitude - * double *CurrentCosinusAmplitude - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerEncoderAmplitudeValuesGet (int SocketIndex, char * PositionerName, double * CalibrationSinusAmplitude, double * CurrentSinusAmplitude, double * CalibrationCosinusAmplitude, double * CurrentCosinusAmplitude) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerEncoderAmplitudeValuesGet (%s,double *,double *,double *,double *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CalibrationSinusAmplitude); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CurrentSinusAmplitude); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CalibrationCosinusAmplitude); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CurrentCosinusAmplitude); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerEncoderCalibrationParametersGet : Read analog interpolated encoder calibration parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double *SinusOffset - * double *CosinusOffset - * double *DifferentialGain - * double *PhaseCompensation - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerEncoderCalibrationParametersGet (int SocketIndex, char * PositionerName, double * SinusOffset, double * CosinusOffset, double * DifferentialGain, double * PhaseCompensation) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerEncoderCalibrationParametersGet (%s,double *,double *,double *,double *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", SinusOffset); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CosinusOffset); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", DifferentialGain); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", PhaseCompensation); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerErrorGet : Read and clear positioner error code - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * int *ErrorCode - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerErrorGet (int SocketIndex, char * PositionerName, int * ErrorCode) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerErrorGet (%s,int *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", ErrorCode); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerErrorRead : Read only positioner error code without clear it - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * int *ErrorCode - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerErrorRead (int SocketIndex, char * PositionerName, int * ErrorCode) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerErrorRead (%s,int *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", ErrorCode); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerErrorStringGet : Return the positioner status string corresponding to the positioner error code - * - * - Parameters : - * int SocketIndex - * int PositionerErrorCode - * char *PositionerErrorString - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerErrorStringGet (int SocketIndex, int PositionerErrorCode, char * PositionerErrorString) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerErrorStringGet (%d,char *)", PositionerErrorCode); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (PositionerErrorString, pt); - ptNext = strchr (PositionerErrorString, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerHardwareStatusGet : Read positioner hardware status - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * int *HardwareStatus - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerHardwareStatusGet (int SocketIndex, char * PositionerName, int * HardwareStatus) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerHardwareStatusGet (%s,int *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", HardwareStatus); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerHardwareStatusStringGet : Return the positioner hardware status string corresponding to the positioner error code - * - * - Parameters : - * int SocketIndex - * int PositionerHardwareStatus - * char *PositionerHardwareStatusString - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerHardwareStatusStringGet (int SocketIndex, int PositionerHardwareStatus, char * PositionerHardwareStatusString) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerHardwareStatusStringGet (%d,char *)", PositionerHardwareStatus); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (PositionerHardwareStatusString, pt); - ptNext = strchr (PositionerHardwareStatusString, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerHardInterpolatorFactorGet : Get hard interpolator parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * int *InterpolationFactor - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerHardInterpolatorFactorGet (int SocketIndex, char * PositionerName, int * InterpolationFactor) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerHardInterpolatorFactorGet (%s,int *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", InterpolationFactor); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerHardInterpolatorFactorSet : Set hard interpolator parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * int InterpolationFactor - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerHardInterpolatorFactorSet (int SocketIndex, char * PositionerName, int InterpolationFactor) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerHardInterpolatorFactorSet (%s,%d)", PositionerName, InterpolationFactor); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerMaximumVelocityAndAccelerationGet : Return maximum velocity and acceleration of the positioner - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double *MaximumVelocity - * double *MaximumAcceleration - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerMaximumVelocityAndAccelerationGet (int SocketIndex, char * PositionerName, double * MaximumVelocity, double * MaximumAcceleration) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerMaximumVelocityAndAccelerationGet (%s,double *,double *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", MaximumVelocity); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", MaximumAcceleration); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerMotionDoneGet : Read motion done parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double *PositionWindow - * double *VelocityWindow - * double *CheckingTime - * double *MeanPeriod - * double *TimeOut - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerMotionDoneGet (int SocketIndex, char * PositionerName, double * PositionWindow, double * VelocityWindow, double * CheckingTime, double * MeanPeriod, double * TimeOut) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerMotionDoneGet (%s,double *,double *,double *,double *,double *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", PositionWindow); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", VelocityWindow); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CheckingTime); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", MeanPeriod); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", TimeOut); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerMotionDoneSet : Update motion done parameters - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double PositionWindow - * double VelocityWindow - * double CheckingTime - * double MeanPeriod - * double TimeOut - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerMotionDoneSet (int SocketIndex, char * PositionerName, double PositionWindow, double VelocityWindow, double CheckingTime, double MeanPeriod, double TimeOut) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerMotionDoneSet (%s,%.13g,%.13g,%.13g,%.13g,%.13g)", PositionerName, PositionWindow, VelocityWindow, CheckingTime, MeanPeriod, TimeOut); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerSGammaExactVelocityAjustedDisplacementGet : Return adjusted displacement to get exact velocity - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double DesiredDisplacement - * double *AdjustedDisplacement - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerSGammaExactVelocityAjustedDisplacementGet (int SocketIndex, char * PositionerName, double DesiredDisplacement, double * AdjustedDisplacement) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerSGammaExactVelocityAjustedDisplacementGet (%s,%.13g,double *)", PositionerName, DesiredDisplacement); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", AdjustedDisplacement); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerSGammaParametersGet : Read dynamic parameters for one axe of a group for a future displacement - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double *Velocity - * double *Acceleration - * double *MinimumTjerkTime - * double *MaximumTjerkTime - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerSGammaParametersGet (int SocketIndex, char * PositionerName, double * Velocity, double * Acceleration, double * MinimumTjerkTime, double * MaximumTjerkTime) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerSGammaParametersGet (%s,double *,double *,double *,double *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", Velocity); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", Acceleration); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", MinimumTjerkTime); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", MaximumTjerkTime); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerSGammaParametersSet : Update dynamic parameters for one axe of a group for a future displacement - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double Velocity - * double Acceleration - * double MinimumTjerkTime - * double MaximumTjerkTime - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerSGammaParametersSet (int SocketIndex, char * PositionerName, double Velocity, double Acceleration, double MinimumTjerkTime, double MaximumTjerkTime) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerSGammaParametersSet (%s,%.13g,%.13g,%.13g,%.13g)", PositionerName, Velocity, Acceleration, MinimumTjerkTime, MaximumTjerkTime); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerSGammaPreviousMotionTimesGet : Read SettingTime and SettlingTime - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double *SettingTime - * double *SettlingTime - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerSGammaPreviousMotionTimesGet (int SocketIndex, char * PositionerName, double * SettingTime, double * SettlingTime) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerSGammaPreviousMotionTimesGet (%s,double *,double *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", SettingTime); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", SettlingTime); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerStageParameterGet : Return the stage parameter - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * char *ParameterName - * char *ParameterValue - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerStageParameterGet (int SocketIndex, char * PositionerName, char * ParameterName, char * ParameterValue) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerStageParameterGet (%s,%s,char *)", PositionerName, ParameterName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (ParameterValue, pt); - ptNext = strchr (ParameterValue, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerStageParameterSet : Save the stage parameter - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * char *ParameterName - * char *ParameterValue - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerStageParameterSet (int SocketIndex, char * PositionerName, char * ParameterName, char * ParameterValue) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerStageParameterSet (%s,%s,%s)", PositionerName, ParameterName, ParameterValue); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerUserTravelLimitsGet : Read UserMinimumTarget and UserMaximumTarget - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double *UserMinimumTarget - * double *UserMaximumTarget - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerUserTravelLimitsGet (int SocketIndex, char * PositionerName, double * UserMinimumTarget, double * UserMaximumTarget) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerUserTravelLimitsGet (%s,double *,double *)", PositionerName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", UserMinimumTarget); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", UserMaximumTarget); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerUserTravelLimitsSet : Update UserMinimumTarget and UserMaximumTarget - * - * - Parameters : - * int SocketIndex - * char *PositionerName - * double UserMinimumTarget - * double UserMaximumTarget - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerUserTravelLimitsSet (int SocketIndex, char * PositionerName, double UserMinimumTarget, double UserMaximumTarget) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerUserTravelLimitsSet (%s,%.13g,%.13g)", PositionerName, UserMinimumTarget, UserMaximumTarget); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * HexapodMoveAbsolute : Hexapod absolute move in a specific coordinate system - * - * - Parameters : - * int SocketIndex - * char *GroupName - * char *CoordinateSystem - * double X - * double Y - * double Z - * double U - * double V - * double W - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPHexapodMoveAbsolute (int SocketIndex, char * GroupName, char * CoordinateSystem, double X, double Y, double Z, double U, double V, double W) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "HexapodMoveAbsolute (%s,%s,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", GroupName, CoordinateSystem, X, Y, Z, U, V, W); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * HexapodMoveIncremental : Hexapod incremental move in a specific coordinate system - * - * - Parameters : - * int SocketIndex - * char *GroupName - * char *CoordinateSystem - * double dX - * double dY - * double dZ - * double dU - * double dV - * double dW - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPHexapodMoveIncremental (int SocketIndex, char * GroupName, char * CoordinateSystem, double dX, double dY, double dZ, double dU, double dV, double dW) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "HexapodMoveIncremental (%s,%s,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", GroupName, CoordinateSystem, dX, dY, dZ, dU, dV, dW); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * HexapodCoordinatesGet : Get coordinates in a specific coordinate system of a point specified in another coordinate system - * - * - Parameters : - * int SocketIndex - * char *GroupName - * char *CoordinateSystemIn - * char *CoordinateSystemOut - * double Xin - * double Yin - * double Zin - * double Uin - * double Vin - * double Win - * double *Xout - * double *Yout - * double *Zout - * double *Uout - * double *Vout - * double *Wout - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPHexapodCoordinatesGet (int SocketIndex, char * GroupName, char * CoordinateSystemIn, char * CoordinateSystemOut, double Xin, double Yin, double Zin, double Uin, double Vin, double Win, double * Xout, double * Yout, double * Zout, double * Uout, double * Vout, double * Wout) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "HexapodCoordinatesGet (%s,%s,%s,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,double *,double *,double *,double *,double *,double *)", GroupName, CoordinateSystemIn, CoordinateSystemOut, Xin, Yin, Zin, Uin, Vin, Win); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", Xout); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", Yout); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", Zout); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", Uout); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", Vout); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", Wout); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * HexapodCoordinateSystemSet : Modify the position of a coordinate system - * - * - Parameters : - * int SocketIndex - * char *GroupName - * char *CoordinateSystem - * double X - * double Y - * double Z - * double U - * double V - * double W - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPHexapodCoordinateSystemSet (int SocketIndex, char * GroupName, char * CoordinateSystem, double X, double Y, double Z, double U, double V, double W) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "HexapodCoordinateSystemSet (%s,%s,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", GroupName, CoordinateSystem, X, Y, Z, U, V, W); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * HexapodCoordinateSystemGet : Get the position of a coordinate system - * - * - Parameters : - * int SocketIndex - * char *GroupName - * char *CoordinateSystem - * double *X - * double *Y - * double *Z - * double *U - * double *V - * double *W - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPHexapodCoordinateSystemGet (int SocketIndex, char * GroupName, char * CoordinateSystem, double * X, double * Y, double * Z, double * U, double * V, double * W) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "HexapodCoordinateSystemGet (%s,%s,double *,double *,double *,double *,double *,double *)", GroupName, CoordinateSystem); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", X); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", Y); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", Z); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", U); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", V); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", W); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * OptionalModuleExecute : Execute an optional module - * - * - Parameters : - * int SocketIndex - * char *ModuleFileName - * char *TaskName - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPOptionalModuleExecute (int SocketIndex, char * ModuleFileName, char * TaskName) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "OptionalModuleExecute (%s,%s)", ModuleFileName, TaskName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * OptionalModuleKill : Kill an optional module - * - * - Parameters : - * int SocketIndex - * char *TaskName - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPOptionalModuleKill (int SocketIndex, char * TaskName) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "OptionalModuleKill (%s)", TaskName); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * ControllerStatusGet : Read controller current status - * - * - Parameters : - * int SocketIndex - * int *ControllerStatus - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPControllerStatusGet (int SocketIndex, int * ControllerStatus) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "ControllerStatusGet (int *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%d", ControllerStatus); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * ControllerStatusStringGet : Return the controller status string corresponding to the controller status code - * - * - Parameters : - * int SocketIndex - * int ControllerStatusCode - * char *ControllerStatusString - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPControllerStatusStringGet (int SocketIndex, int ControllerStatusCode, char * ControllerStatusString) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "ControllerStatusStringGet (%d,char *)", ControllerStatusCode); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (ControllerStatusString, pt); - ptNext = strchr (ControllerStatusString, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EEPROMCIESet : Set CIE EEPROM reference string - * - * - Parameters : - * int SocketIndex - * int CardNumber - * char *ReferenceString - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEEPROMCIESet (int SocketIndex, int CardNumber, char * ReferenceString) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "EEPROMCIESet (%d,%s)", CardNumber, ReferenceString); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EEPROMDACOffsetCIESet : Set CIE DAC offsets - * - * - Parameters : - * int SocketIndex - * int PlugNumber - * double DAC1Offset - * double DAC2Offset - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEEPROMDACOffsetCIESet (int SocketIndex, int PlugNumber, double DAC1Offset, double DAC2Offset) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "EEPROMDACOffsetCIESet (%d,%.13g,%.13g)", PlugNumber, DAC1Offset, DAC2Offset); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EEPROMDriverSet : Set Driver EEPROM reference string - * - * - Parameters : - * int SocketIndex - * int PlugNumber - * char *ReferenceString - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEEPROMDriverSet (int SocketIndex, int PlugNumber, char * ReferenceString) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "EEPROMDriverSet (%d,%s)", PlugNumber, ReferenceString); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EEPROMINTSet : Set INT EEPROM reference string - * - * - Parameters : - * int SocketIndex - * int CardNumber - * char *ReferenceString - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEEPROMINTSet (int SocketIndex, int CardNumber, char * ReferenceString) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "EEPROMINTSet (%d,%s)", CardNumber, ReferenceString); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * CPUCoreAndBoardSupplyVoltagesGet : Get power informations - * - * - Parameters : - * int SocketIndex - * double *VoltageCPUCore - * double *SupplyVoltage1P5V - * double *SupplyVoltage3P3V - * double *SupplyVoltage5V - * double *SupplyVoltage12V - * double *SupplyVoltageM12V - * double *SupplyVoltageM5V - * double *SupplyVoltage5VSB - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPCPUCoreAndBoardSupplyVoltagesGet (int SocketIndex, double * VoltageCPUCore, double * SupplyVoltage1P5V, double * SupplyVoltage3P3V, double * SupplyVoltage5V, double * SupplyVoltage12V, double * SupplyVoltageM12V, double * SupplyVoltageM5V, double * SupplyVoltage5VSB) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "CPUCoreAndBoardSupplyVoltagesGet (double *,double *,double *,double *,double *,double *,double *,double *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", VoltageCPUCore); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", SupplyVoltage1P5V); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", SupplyVoltage3P3V); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", SupplyVoltage5V); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", SupplyVoltage12V); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", SupplyVoltageM12V); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", SupplyVoltageM5V); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", SupplyVoltage5VSB); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * CPUTemperatureAndFanSpeedGet : Get CPU temperature and fan speed - * - * - Parameters : - * int SocketIndex - * double *CPUTemperature - * double *CPUFanSpeed - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPCPUTemperatureAndFanSpeedGet (int SocketIndex, double * CPUTemperature, double * CPUFanSpeed) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "CPUTemperatureAndFanSpeedGet (double *,double *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CPUTemperature); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", CPUFanSpeed); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * ActionListGet : Action list - * - * - Parameters : - * int SocketIndex - * char *ActionList - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPActionListGet (int SocketIndex, char * ActionList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "ActionListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (ActionList, pt); - ptNext = strchr (ActionList, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * ActionExtendedListGet : Action extended list - * - * - Parameters : - * int SocketIndex - * char *ActionList - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPActionExtendedListGet (int SocketIndex, char * ActionList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "ActionExtendedListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (ActionList, pt); - ptNext = strchr (ActionList, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * APIExtendedListGet : API method list - * - * - Parameters : - * int SocketIndex - * char *Method - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPAPIExtendedListGet (int SocketIndex, char * Method) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); - - /* Convert to string */ - sprintf (ExecuteMethod, "APIExtendedListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (Method, pt); - ptNext = strchr (Method, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * APIListGet : API method list without extended API - * - * - Parameters : - * int SocketIndex - * char *Method - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPAPIListGet (int SocketIndex, char * Method) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); - - /* Convert to string */ - sprintf (ExecuteMethod, "APIListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (Method, pt); - ptNext = strchr (Method, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * ErrorListGet : Error list - * - * - Parameters : - * int SocketIndex - * char *ErrorsList - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPErrorListGet (int SocketIndex, char * ErrorsList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); - - /* Convert to string */ - sprintf (ExecuteMethod, "ErrorListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (ErrorsList, pt); - ptNext = strchr (ErrorsList, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * EventListGet : General event list - * - * - Parameters : - * int SocketIndex - * char *EventList - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPEventListGet (int SocketIndex, char * EventList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "EventListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (EventList, pt); - ptNext = strchr (EventList, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringListGet : Gathering type list - * - * - Parameters : - * int SocketIndex - * char *list - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringListGet (int SocketIndex, char * list) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (list, pt); - ptNext = strchr (list, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringExtendedListGet : Gathering type extended list - * - * - Parameters : - * int SocketIndex - * char *list - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringExtendedListGet (int SocketIndex, char * list) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringExtendedListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (list, pt); - ptNext = strchr (list, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringExternalListGet : External Gathering type list - * - * - Parameters : - * int SocketIndex - * char *list - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringExternalListGet (int SocketIndex, char * list) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringExternalListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (list, pt); - ptNext = strchr (list, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GroupStatusListGet : Group status list - * - * - Parameters : - * int SocketIndex - * char *GroupStatusList - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGroupStatusListGet (int SocketIndex, char * GroupStatusList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); - - /* Convert to string */ - sprintf (ExecuteMethod, "GroupStatusListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (GroupStatusList, pt); - ptNext = strchr (GroupStatusList, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * HardwareInternalListGet : Internal hardware list - * - * - Parameters : - * int SocketIndex - * char *InternalHardwareList - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPHardwareInternalListGet (int SocketIndex, char * InternalHardwareList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); - - /* Convert to string */ - sprintf (ExecuteMethod, "HardwareInternalListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (InternalHardwareList, pt); - ptNext = strchr (InternalHardwareList, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * HardwareDriverAndStageGet : Smart hardware - * - * - Parameters : - * int SocketIndex - * int PlugNumber - * char *DriverName - * char *StageName - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPHardwareDriverAndStageGet (int SocketIndex, int PlugNumber, char * DriverName, char * StageName) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); - - /* Convert to string */ - sprintf (ExecuteMethod, "HardwareDriverAndStageGet (%d,char *,char *)", PlugNumber); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (DriverName, pt); - ptNext = strchr (DriverName, ','); - if (ptNext != NULL) *ptNext = '\0'; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (StageName, pt); - ptNext = strchr (StageName, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * ObjectsListGet : Group name and positioner name - * - * - Parameters : - * int SocketIndex - * char *ObjectsList - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPObjectsListGet (int SocketIndex, char * ObjectsList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); - - /* Convert to string */ - sprintf (ExecuteMethod, "ObjectsListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (ObjectsList, pt); - ptNext = strchr (ObjectsList, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerErrorListGet : Positioner error list - * - * - Parameters : - * int SocketIndex - * char *PositionerErrorList - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerErrorListGet (int SocketIndex, char * PositionerErrorList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerErrorListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (PositionerErrorList, pt); - ptNext = strchr (PositionerErrorList, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerHardwareStatusListGet : Positioner hardware status list - * - * - Parameters : - * int SocketIndex - * char *PositionerHardwareStatusList - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerHardwareStatusListGet (int SocketIndex, char * PositionerHardwareStatusList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerHardwareStatusListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (PositionerHardwareStatusList, pt); - ptNext = strchr (PositionerHardwareStatusList, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PositionerDriverStatusListGet : Positioner driver status list - * - * - Parameters : - * int SocketIndex - * char *PositionerDriverStatusList - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPositionerDriverStatusListGet (int SocketIndex, char * PositionerDriverStatusList) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "PositionerDriverStatusListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (PositionerDriverStatusList, pt); - ptNext = strchr (PositionerDriverStatusList, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * ReferencingActionListGet : Get referencing action list - * - * - Parameters : - * int SocketIndex - * char *list - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPReferencingActionListGet (int SocketIndex, char * list) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "ReferencingActionListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (list, pt); - ptNext = strchr (list, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * ReferencingSensorListGet : Get referencing sensor list - * - * - Parameters : - * int SocketIndex - * char *list - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPReferencingSensorListGet (int SocketIndex, char * list) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); - - /* Convert to string */ - sprintf (ExecuteMethod, "ReferencingSensorListGet (char *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (list, pt); - ptNext = strchr (list, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * GatheringUserDatasGet : Return UserDatas values - * - * - Parameters : - * int SocketIndex - * double *UserData1 - * double *UserData2 - * double *UserData3 - * double *UserData4 - * double *UserData5 - * double *UserData6 - * double *UserData7 - * double *UserData8 - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPGatheringUserDatasGet (int SocketIndex, double * UserData1, double * UserData2, double * UserData3, double * UserData4, double * UserData5, double * UserData6, double * UserData7, double * UserData8) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "GatheringUserDatasGet (double *,double *,double *,double *,double *,double *,double *,double *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", UserData1); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", UserData2); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", UserData3); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", UserData4); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", UserData5); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", UserData6); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", UserData7); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", UserData8); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * ControllerMotionKernelPeriodMinMaxGet : Get controller motion kernel min/max periods - * - * - Parameters : - * int SocketIndex - * double *MinimumCorrectorPeriod - * double *MaximumCorrectorPeriod - * double *MinimumProfilerPeriod - * double *MaximumProfilerPeriod - * double *MinimumServitudesPeriod - * double *MaximumServitudesPeriod - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPControllerMotionKernelPeriodMinMaxGet (int SocketIndex, double * MinimumCorrectorPeriod, double * MaximumCorrectorPeriod, double * MinimumProfilerPeriod, double * MaximumProfilerPeriod, double * MinimumServitudesPeriod, double * MaximumServitudesPeriod) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "ControllerMotionKernelPeriodMinMaxGet (double *,double *,double *,double *,double *,double *)"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", MinimumCorrectorPeriod); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", MaximumCorrectorPeriod); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", MinimumProfilerPeriod); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", MaximumProfilerPeriod); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", MinimumServitudesPeriod); - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) sscanf (pt, "%lf", MaximumServitudesPeriod); - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * ControllerMotionKernelPeriodMinMaxReset : Reset controller motion kernel min/max periods - * - * - Parameters : - * int SocketIndex - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPControllerMotionKernelPeriodMinMaxReset (int SocketIndex) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "ControllerMotionKernelPeriodMinMaxReset ()"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * TestTCP : Test TCP/IP transfert - * - * - Parameters : - * int SocketIndex - * char *InputString - * char *ReturnString - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPTestTCP (int SocketIndex, char * InputString, char * ReturnString) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "TestTCP (%s,char *)", InputString); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (ret == 0) - { - char * pt; - char * ptNext; - - pt = ReturnedValue; - ptNext = NULL; - if (pt != NULL) pt = strchr (pt, ','); - if (pt != NULL) pt++; - if (pt != NULL) strcpy (ReturnString, pt); - ptNext = strchr (ReturnString, ','); - if (ptNext != NULL) *ptNext = '\0'; - } - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - -/*********************************************************************** - * PrepareForUpdate : Kill QNX processes for firmware update - * - * - Parameters : - * int SocketIndex - * - Return : - * int errorCode - ***********************************************************************/ -int __stdcall HXPPrepareForUpdate (int SocketIndex) -{ - int ret = -1; - char ExecuteMethod[SIZE_EXECUTE_METHOD]; - char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); - - /* Convert to string */ - sprintf (ExecuteMethod, "PrepareForUpdate ()"); - - /* Send this string and wait return function from controller */ - /* return function : ==0 -> OK ; < 0 -> NOK */ - SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); - if (strlen (ReturnedValue) > 0) - sscanf (ReturnedValue, "%i", &ret); - - /* Get the returned values in the out parameters */ - if (NULL != ReturnedValue) - free (ReturnedValue); - - return (ret); -} - - - -#ifdef __cplusplus -} -#endif +/* + * Created source file hxp_drivers.cpp for API description + */ + + +#include +#include +#include +#include +#include "Socket.h" + +#define epicsExportSharedSymbols +#include +#include "XPS_C8_drivers.h" +#ifdef _WIN32 +#include "strtok_r.h" +#endif + +#define SIZE_SMALL 1024 +#define SIZE_NOMINAL 1024 +#define SIZE_BIG 2048 +#define SIZE_HUGE 65536 + +#define SIZE_EXECUTE_METHOD 1024 + +#define SIZE_NAME 100 +#ifdef __cplusplus +extern "C" +{ +#else +#typedef int bool; /* C does not know bool, only C++ */ +#endif + + +#define DLL_VERSION "Library version for HXP Firmware V1.3.x" + +/************************************************************************* +* Replace 'oldChar' by 'newChar' only between the startChar and endChar +*************************************************************************/ +void ReplaceCharacter (char *strSourceInOut, char oldChar, char newChar, char startChar, char endChar) +{ + char *pt; + char *ptNext; + ptNext = strSourceInOut; + do + { + pt = strchr(ptNext, startChar); + if (pt != NULL) + { + *pt++; + while ((pt != NULL) && (*pt != endChar)) + { + if (*pt == oldChar) + *pt = newChar; + pt++; + } + ptNext = pt++; + } + } + while ((pt != NULL) && (ptNext != NULL)); +} + +/************************************************************************* +* Delete space and tabulation characters between 'startChar' and 'endChar' +*************************************************************************/ +void CleanString (char *strSourceInOut, char startChar, char endChar) +{ + int len = 0; + int startIndex = 0; + int endIndex = 0; + int outputIndex = 0; + char outputString[SIZE_NOMINAL]; + len = strlen(strSourceInOut); + do + { + while ((strSourceInOut[startIndex] != startChar) && (startIndex < len) && (outputIndex < SIZE_NOMINAL)) + { + outputString[outputIndex] = strSourceInOut[startIndex]; + outputIndex++; + startIndex++; + } + while ((strSourceInOut[endIndex] != endChar) && (endIndex < len)) + endIndex++; + if ((startIndex != endIndex) && (startIndex < len)) + { + for (int i = startIndex; (i <= endIndex) && (outputIndex < SIZE_NOMINAL); i++) + { + if ((strSourceInOut[i] != ' ') && (strSourceInOut[i] != '\t')) + { + outputString[outputIndex] = strSourceInOut[i]; + outputIndex++; + } + } + endIndex++; + startIndex = endIndex; + } + } + while (startIndex < len); + outputString[outputIndex] = '\0'; + strcpy (strSourceInOut, outputString); +} + +/************************************************************************* +* Delete a specified characters +*************************************************************************/ +void DeleteCharacters (char *strSourceInOut, char *charactersToDelete) +{ + int len = 0; + int nbChar = 0; + int outputIndex = 0; + bool bCopy; + char outputString[SIZE_NOMINAL]; + len = strlen(strSourceInOut); + nbChar = strlen(charactersToDelete); + for (int i = 0; (i <= len) && (outputIndex < SIZE_NOMINAL); i++) + { + bCopy = true; + for (int j = 0; (j < nbChar) && (bCopy == true); j++) + { + if (strSourceInOut[i] == charactersToDelete[j]) + bCopy = false; + } + if (bCopy) + { + outputString[outputIndex] = strSourceInOut[i]; + outputIndex++; + } + } + outputString[outputIndex] = '\0'; + strcpy (strSourceInOut, outputString); +} + +/***********************************************************************/ +int __stdcall HXPTCP_ConnectToServer(char *Ip_Address, int Ip_Port, double TimeOut) +{ + return (ConnectToServer(Ip_Address, Ip_Port, TimeOut)); +} +/***********************************************************************/ +void __stdcall HXPTCP_SetTimeout(int SocketIndex, double Timeout) +{ + SetTCPTimeout(SocketIndex, Timeout); +} +/***********************************************************************/ +void __stdcall HXPTCP_CloseSocket(int SocketIndex) +{ + CloseSocket(SocketIndex); +} +/***********************************************************************/ +char * __stdcall HXPTCP_GetError(int SocketIndex) +{ + return (GetError(SocketIndex)); +} +/***********************************************************************/ +char * __stdcall HXPGetLibraryVersion(void) +{ + return (DLL_VERSION); +} + +/*********************************************************************** + * ControllerMotionKernelTimeLoadGet : Get controller motion kernel time load + * + * - Parameters : + * int SocketIndex + * double *CPUTotalLoadRatio + * double *CPUCorrectorLoadRatio + * double *CPUProfilerLoadRatio + * double *CPUServitudesLoadRatio + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPControllerMotionKernelTimeLoadGet (int SocketIndex, double * CPUTotalLoadRatio, double * CPUCorrectorLoadRatio, double * CPUProfilerLoadRatio, double * CPUServitudesLoadRatio) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "ControllerMotionKernelTimeLoadGet (double *,double *,double *,double *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CPUTotalLoadRatio); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CPUCorrectorLoadRatio); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CPUProfilerLoadRatio); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CPUServitudesLoadRatio); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * ElapsedTimeGet : Return elapsed time from controller power on + * + * - Parameters : + * int SocketIndex + * double *ElapsedTime + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPElapsedTimeGet (int SocketIndex, double * ElapsedTime) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "ElapsedTimeGet (double *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", ElapsedTime); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * ErrorStringGet : Return the error string corresponding to the error code + * + * - Parameters : + * int SocketIndex + * int ErrorCode + * char *ErrorString + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPErrorStringGet (int SocketIndex, int ErrorCode, char * ErrorString) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "ErrorStringGet (%d,char *)", ErrorCode); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (ErrorString, pt); + ptNext = strchr (ErrorString, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * FirmwareVersionGet : Return firmware version + * + * - Parameters : + * int SocketIndex + * char *Version + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPFirmwareVersionGet (int SocketIndex, char * Version) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "FirmwareVersionGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (Version, pt); + ptNext = strchr (Version, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * TCLScriptExecute : Execute a TCL script from a TCL file + * + * - Parameters : + * int SocketIndex + * char *TCLFileName + * char *TaskName + * char *ParametersList + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPTCLScriptExecute (int SocketIndex, char * TCLFileName, char * TaskName, char * ParametersList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "TCLScriptExecute (%s,%s,%s)", TCLFileName, TaskName, ParametersList); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * TCLScriptExecuteAndWait : Execute a TCL script from a TCL file and wait the end of execution to return + * + * - Parameters : + * int SocketIndex + * char *TCLFileName + * char *TaskName + * char *InputParametersList + * char *OutputParametersList + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPTCLScriptExecuteAndWait (int SocketIndex, char * TCLFileName, char * TaskName, char * InputParametersList, char * OutputParametersList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "TCLScriptExecuteAndWait (%s,%s,%s,char *)", TCLFileName, TaskName, InputParametersList); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (OutputParametersList, pt); + ptNext = strchr (OutputParametersList, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * TCLScriptKill : Kill TCL Task + * + * - Parameters : + * int SocketIndex + * char *TaskName + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPTCLScriptKill (int SocketIndex, char * TaskName) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "TCLScriptKill (%s)", TaskName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * TimerGet : Get a timer + * + * - Parameters : + * int SocketIndex + * char *TimerName + * int *FrequencyTicks + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPTimerGet (int SocketIndex, char * TimerName, int * FrequencyTicks) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "TimerGet (%s,int *)", TimerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", FrequencyTicks); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * TimerSet : Set a timer + * + * - Parameters : + * int SocketIndex + * char *TimerName + * int FrequencyTicks + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPTimerSet (int SocketIndex, char * TimerName, int FrequencyTicks) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "TimerSet (%s,%d)", TimerName, FrequencyTicks); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * Reboot : Reboot the controller + * + * - Parameters : + * int SocketIndex + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPReboot (int SocketIndex) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "Reboot ()"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * Login : Log in + * + * - Parameters : + * int SocketIndex + * char *Name + * char *Password + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPLogin (int SocketIndex, char * Name, char * Password) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "Login (%s,%s)", Name, Password); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * CloseAllOtherSockets : Close all socket beside the one used to send this command + * + * - Parameters : + * int SocketIndex + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPCloseAllOtherSockets (int SocketIndex) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "CloseAllOtherSockets ()"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventAdd : ** OBSOLETE ** Add an event + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * char *EventName + * char *EventParameter + * char *ActionName + * char *ActionParameter1 + * char *ActionParameter2 + * char *ActionParameter3 + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventAdd (int SocketIndex, char * PositionerName, char * EventName, char * EventParameter, char * ActionName, char * ActionParameter1, char * ActionParameter2, char * ActionParameter3) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "EventAdd (%s,%s,%s,%s,%s,%s,%s)", PositionerName, EventName, EventParameter, ActionName, ActionParameter1, ActionParameter2, ActionParameter3); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventGet : ** OBSOLETE ** Read events and actions list + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * char *EventsAndActionsList + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventGet (int SocketIndex, char * PositionerName, char * EventsAndActionsList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "EventGet (%s,char *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (EventsAndActionsList, pt); + ptNext = strchr (EventsAndActionsList, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventRemove : ** OBSOLETE ** Delete an event + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * char *EventName + * char *EventParameter + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventRemove (int SocketIndex, char * PositionerName, char * EventName, char * EventParameter) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "EventRemove (%s,%s,%s)", PositionerName, EventName, EventParameter); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventWait : ** OBSOLETE ** Wait an event + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * char *EventName + * char *EventParameter + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventWait (int SocketIndex, char * PositionerName, char * EventName, char * EventParameter) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "EventWait (%s,%s,%s)", PositionerName, EventName, EventParameter); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventExtendedConfigurationTriggerSet : Configure one or several events + * + * - Parameters : + * int SocketIndex + * int nbElement + * char *ExtendedEventName + * char *EventParameter1 + * char *EventParameter2 + * char *EventParameter3 + * char *EventParameter4 + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventExtendedConfigurationTriggerSet (int SocketIndex, int NbElements, char * ExtendedEventNameList, char * EventParameter1List, char * EventParameter2List, char * EventParameter3List, char * EventParameter4List) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Split list */ + char *token; + char seps[] = " \t;"; + int indice; + char list [SIZE_NOMINAL]; + char *list_r; + char subString[] = "{}"; + + char (*stringArray0)[SIZE_NAME]; + stringArray0 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, ExtendedEventNameList, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray0[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray0[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + char (*stringArray1)[SIZE_NAME]; + stringArray1 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, EventParameter1List, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray1[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray1[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray1[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray1[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + char (*stringArray2)[SIZE_NAME]; + stringArray2 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, EventParameter2List, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray2[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray2[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray2[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray2[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + char (*stringArray3)[SIZE_NAME]; + stringArray3 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, EventParameter3List, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray3[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray3[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray3[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray3[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + char (*stringArray4)[SIZE_NAME]; + stringArray4 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, EventParameter4List, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray4[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray4[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray4[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray4[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + + /* Convert to string */ + sprintf (ExecuteMethod, "EventExtendedConfigurationTriggerSet ("); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "%s,%s,%s,%s,%s", stringArray0[i], stringArray1[i], stringArray2[i], stringArray3[i], stringArray4[i]); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Clear memory */ + delete [] stringArray0; + delete [] stringArray1; + delete [] stringArray2; + delete [] stringArray3; + delete [] stringArray4; + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventExtendedConfigurationTriggerGet : Read the event configuration + * + * - Parameters : + * int SocketIndex + * char *EventTriggerConfiguration + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventExtendedConfigurationTriggerGet (int SocketIndex, char * EventTriggerConfiguration) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "EventExtendedConfigurationTriggerGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (EventTriggerConfiguration, pt); + ptNext = strchr (EventTriggerConfiguration, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventExtendedConfigurationActionSet : Configure one or several actions + * + * - Parameters : + * int SocketIndex + * int nbElement + * char *ExtendedActionName + * char *ActionParameter1 + * char *ActionParameter2 + * char *ActionParameter3 + * char *ActionParameter4 + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventExtendedConfigurationActionSet (int SocketIndex, int NbElements, char * ExtendedActionNameList, char * ActionParameter1List, char * ActionParameter2List, char * ActionParameter3List, char * ActionParameter4List) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Split list */ + char *token; + char seps[] = " \t;"; + int indice; + char list [SIZE_NOMINAL]; + char *list_r; + char subString[] = "{}"; + + char (*stringArray0)[SIZE_NAME]; + stringArray0 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, ExtendedActionNameList, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray0[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray0[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + char (*stringArray1)[SIZE_NAME]; + stringArray1 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, ActionParameter1List, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray1[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray1[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray1[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray1[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + char (*stringArray2)[SIZE_NAME]; + stringArray2 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, ActionParameter2List, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray2[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray2[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray2[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray2[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + char (*stringArray3)[SIZE_NAME]; + stringArray3 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, ActionParameter3List, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray3[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray3[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray3[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray3[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + char (*stringArray4)[SIZE_NAME]; + stringArray4 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, ActionParameter4List, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray4[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray4[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray4[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray4[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + + /* Convert to string */ + sprintf (ExecuteMethod, "EventExtendedConfigurationActionSet ("); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "%s,%s,%s,%s,%s", stringArray0[i], stringArray1[i], stringArray2[i], stringArray3[i], stringArray4[i]); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Clear memory */ + delete [] stringArray0; + delete [] stringArray1; + delete [] stringArray2; + delete [] stringArray3; + delete [] stringArray4; + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventExtendedConfigurationActionGet : Read the action configuration + * + * - Parameters : + * int SocketIndex + * char *ActionConfiguration + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventExtendedConfigurationActionGet (int SocketIndex, char * ActionConfiguration) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "EventExtendedConfigurationActionGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (ActionConfiguration, pt); + ptNext = strchr (ActionConfiguration, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventExtendedStart : Launch the last event and action configuration and return an ID + * + * - Parameters : + * int SocketIndex + * int *ID + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventExtendedStart (int SocketIndex, int * ID) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "EventExtendedStart (int *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", ID); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventExtendedAllGet : Read all event and action configurations + * + * - Parameters : + * int SocketIndex + * char *EventActionConfigurations + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventExtendedAllGet (int SocketIndex, char * EventActionConfigurations) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); + + /* Convert to string */ + sprintf (ExecuteMethod, "EventExtendedAllGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (EventActionConfigurations, pt); + ptNext = strchr (EventActionConfigurations, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventExtendedGet : Read the event and action configuration defined by ID + * + * - Parameters : + * int SocketIndex + * int ID + * char *EventTriggerConfiguration + * char *ActionConfiguration + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventExtendedGet (int SocketIndex, int ID, char * EventTriggerConfiguration, char * ActionConfiguration) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "EventExtendedGet (%d,char *,char *)", ID); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (EventTriggerConfiguration, pt); + ptNext = strchr (EventTriggerConfiguration, ','); + if (ptNext != NULL) *ptNext = '\0'; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (ActionConfiguration, pt); + ptNext = strchr (ActionConfiguration, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventExtendedRemove : Remove the event and action configuration defined by ID + * + * - Parameters : + * int SocketIndex + * int ID + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventExtendedRemove (int SocketIndex, int ID) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "EventExtendedRemove (%d)", ID); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventExtendedWait : Wait events from the last event configuration + * + * - Parameters : + * int SocketIndex + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventExtendedWait (int SocketIndex) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "EventExtendedWait ()"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringConfigurationGet : Read different mnemonique type + * + * - Parameters : + * int SocketIndex + * char *Type + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringConfigurationGet (int SocketIndex, char * Type) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringConfigurationGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (Type, pt); + ptNext = strchr (Type, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringConfigurationSet : Configuration acquisition + * + * - Parameters : + * int SocketIndex + * int nbElement + * char *Type + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringConfigurationSet (int SocketIndex, int NbElements, char * TypeList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Split list */ + char *token; + char seps[] = " \t;"; + int indice; + char list [SIZE_NOMINAL]; + char *list_r; + char subString[] = "{}"; + + char (*stringArray0)[SIZE_NAME]; + stringArray0 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, TypeList, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray0[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray0[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringConfigurationSet ("); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "%s", stringArray0[i]); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Clear memory */ + delete [] stringArray0; + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringCurrentNumberGet : Maximum number of samples and current number during acquisition + * + * - Parameters : + * int SocketIndex + * int *CurrentNumber + * int *MaximumSamplesNumber + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringCurrentNumberGet (int SocketIndex, int * CurrentNumber, int * MaximumSamplesNumber) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringCurrentNumberGet (int *,int *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", CurrentNumber); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", MaximumSamplesNumber); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringStopAndSave : Stop acquisition and save data + * + * - Parameters : + * int SocketIndex + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringStopAndSave (int SocketIndex) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringStopAndSave ()"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringDataAcquire : Acquire a configured data + * + * - Parameters : + * int SocketIndex + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringDataAcquire (int SocketIndex) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringDataAcquire ()"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringDataGet : Get a data line from gathering buffer + * + * - Parameters : + * int SocketIndex + * int IndexPoint + * char *DataBufferLine + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringDataGet (int SocketIndex, int IndexPoint, char * DataBufferLine) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringDataGet (%d,char *)", IndexPoint); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (DataBufferLine, pt); + ptNext = strchr (DataBufferLine, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringReset : Empty the gathered data in memory to start new gathering from scratch + * + * - Parameters : + * int SocketIndex + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringReset (int SocketIndex) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringReset ()"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringRun : Start a new gathering + * + * - Parameters : + * int SocketIndex + * int DataNumber + * int Divisor + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringRun (int SocketIndex, int DataNumber, int Divisor) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringRun (%d,%d)", DataNumber, Divisor); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringStop : Stop the data gathering (without saving to file) + * + * - Parameters : + * int SocketIndex + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringStop (int SocketIndex) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringStop ()"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringExternalConfigurationSet : Configuration acquisition + * + * - Parameters : + * int SocketIndex + * int nbElement + * char *Type + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringExternalConfigurationSet (int SocketIndex, int NbElements, char * TypeList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Split list */ + char *token; + char seps[] = " \t;"; + int indice; + char list [SIZE_NOMINAL]; + char *list_r; + char subString[] = "{}"; + + char (*stringArray0)[SIZE_NAME]; + stringArray0 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, TypeList, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray0[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray0[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringExternalConfigurationSet ("); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "%s", stringArray0[i]); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Clear memory */ + delete [] stringArray0; + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringExternalConfigurationGet : Read different mnemonique type + * + * - Parameters : + * int SocketIndex + * char *Type + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringExternalConfigurationGet (int SocketIndex, char * Type) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringExternalConfigurationGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (Type, pt); + ptNext = strchr (Type, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringExternalCurrentNumberGet : Maximum number of samples and current number during acquisition + * + * - Parameters : + * int SocketIndex + * int *CurrentNumber + * int *MaximumSamplesNumber + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringExternalCurrentNumberGet (int SocketIndex, int * CurrentNumber, int * MaximumSamplesNumber) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringExternalCurrentNumberGet (int *,int *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", CurrentNumber); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", MaximumSamplesNumber); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringExternalStopAndSave : Stop acquisition and save data + * + * - Parameters : + * int SocketIndex + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringExternalStopAndSave (int SocketIndex) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringExternalStopAndSave ()"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GlobalArrayGet : Get global array value + * + * - Parameters : + * int SocketIndex + * int Number + * char *ValueString + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGlobalArrayGet (int SocketIndex, int Number, char * ValueString) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GlobalArrayGet (%d,char *)", Number); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (ValueString, pt); + ptNext = strchr (ValueString, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GlobalArraySet : Set global array value + * + * - Parameters : + * int SocketIndex + * int Number + * char *ValueString + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGlobalArraySet (int SocketIndex, int Number, char * ValueString) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GlobalArraySet (%d,%s)", Number, ValueString); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * DoubleGlobalArrayGet : Get double global array value + * + * - Parameters : + * int SocketIndex + * int Number + * double *DoubleValue + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPDoubleGlobalArrayGet (int SocketIndex, int Number, double * DoubleValue) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "DoubleGlobalArrayGet (%d,double *)", Number); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", DoubleValue); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * DoubleGlobalArraySet : Set double global array value + * + * - Parameters : + * int SocketIndex + * int Number + * double DoubleValue + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPDoubleGlobalArraySet (int SocketIndex, int Number, double DoubleValue) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "DoubleGlobalArraySet (%d,%.13g)", Number, DoubleValue); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GPIOAnalogGet : Read analog input or analog output for one or few input + * + * - Parameters : + * int SocketIndex + * int nbElement + * char *GPIOName + * double *AnalogValue + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGPIOAnalogGet (int SocketIndex, int NbElements, char * GPIONameList, double AnalogValue[]) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Split list */ + char *token; + char seps[] = " \t;"; + int indice; + char list [SIZE_NOMINAL]; + char *list_r; + char subString[] = "{}"; + + char (*stringArray0)[SIZE_NAME]; + stringArray0 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, GPIONameList, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray0[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray0[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + + /* Convert to string */ + sprintf (ExecuteMethod, "GPIOAnalogGet ("); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "%s,double *", stringArray0[i]); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Clear memory */ + delete [] stringArray0; + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + + for (int i = 0; i < NbElements; i++) + { + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", &AnalogValue[i]); + } + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GPIOAnalogSet : Set analog output for one or few output + * + * - Parameters : + * int SocketIndex + * int nbElement + * char *GPIOName + * double AnalogOutputValue + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGPIOAnalogSet (int SocketIndex, int NbElements, char * GPIONameList, double AnalogOutputValue[]) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Split list */ + char *token; + char seps[] = " \t;"; + int indice; + char list [SIZE_NOMINAL]; + char *list_r; + char subString[] = "{}"; + + char (*stringArray0)[SIZE_NAME]; + stringArray0 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, GPIONameList, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray0[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray0[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + + /* Convert to string */ + sprintf (ExecuteMethod, "GPIOAnalogSet ("); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "%s,%.13g", stringArray0[i], AnalogOutputValue[i]); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Clear memory */ + delete [] stringArray0; + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GPIOAnalogGainGet : Read analog input gain (1, 2, 4 or 8) for one or few input + * + * - Parameters : + * int SocketIndex + * int nbElement + * char *GPIOName + * int *AnalogInputGainValue + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGPIOAnalogGainGet (int SocketIndex, int NbElements, char * GPIONameList, int AnalogInputGainValue[]) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Split list */ + char *token; + char seps[] = " \t;"; + int indice; + char list [SIZE_NOMINAL]; + char *list_r; + char subString[] = "{}"; + + char (*stringArray0)[SIZE_NAME]; + stringArray0 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, GPIONameList, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray0[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray0[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + + /* Convert to string */ + sprintf (ExecuteMethod, "GPIOAnalogGainGet ("); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "%s,int *", stringArray0[i]); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Clear memory */ + delete [] stringArray0; + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + + for (int i = 0; i < NbElements; i++) + { + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", &AnalogInputGainValue[i]); + } + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GPIOAnalogGainSet : Set analog input gain (1, 2, 4 or 8) for one or few input + * + * - Parameters : + * int SocketIndex + * int nbElement + * char *GPIOName + * int AnalogInputGainValue + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGPIOAnalogGainSet (int SocketIndex, int NbElements, char * GPIONameList, int AnalogInputGainValue[]) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Split list */ + char *token; + char seps[] = " \t;"; + int indice; + char list [SIZE_NOMINAL]; + char *list_r; + char subString[] = "{}"; + + char (*stringArray0)[SIZE_NAME]; + stringArray0 = new char [NbElements][SIZE_NAME]; + indice = 0; + strncpyWithEOS(list, GPIONameList, SIZE_NOMINAL, SIZE_NOMINAL); + ReplaceCharacter(list, ';', ':', '{', '}'); /* for argument {x1;x2} */ + CleanString(list, '{', '}'); + list_r = NULL; + token = strtok_r (list, seps, &list_r); + while ((NULL != token) && (indice < NbElements)) + { + memset(stringArray0[indice],'\0', SIZE_NAME); + strncpyWithEOS(stringArray0[indice], token, SIZE_NAME, SIZE_NAME); + ReplaceCharacter (stringArray0[indice], ':', ';', '{', '}'); + DeleteCharacters (stringArray0[indice], subString); + token = strtok_r (NULL, seps, &list_r); + indice++; + } + + /* Convert to string */ + sprintf (ExecuteMethod, "GPIOAnalogGainSet ("); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "%s,%d", stringArray0[i], AnalogInputGainValue[i]); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Clear memory */ + delete [] stringArray0; + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GPIODigitalGet : Read digital output or digital input + * + * - Parameters : + * int SocketIndex + * char *GPIOName + * unsigned short *DigitalValue + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGPIODigitalGet (int SocketIndex, char * GPIOName, unsigned short * DigitalValue) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GPIODigitalGet (%s,unsigned short *)", GPIOName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%hu", DigitalValue); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GPIODigitalSet : Set Digital Output for one or few output TTL + * + * - Parameters : + * int SocketIndex + * char *GPIOName + * unsigned short Mask + * unsigned short DigitalOutputValue + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGPIODigitalSet (int SocketIndex, char * GPIOName, unsigned short Mask, unsigned short DigitalOutputValue) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GPIODigitalSet (%s,%hu,%hu)", GPIOName, Mask, DigitalOutputValue); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupCorrectorOutputGet : Return corrector outputs + * + * - Parameters : + * int SocketIndex + * char *GroupName + * int nbElement + * double *CorrectorOutput + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupCorrectorOutputGet (int SocketIndex, char * GroupName, int NbElements, double CorrectorOutput[]) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupCorrectorOutputGet (%s,", GroupName); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "double *"); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + + for (int i = 0; i < NbElements; i++) + { + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", &CorrectorOutput[i]); + } + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupHomeSearch : Start home search sequence + * + * - Parameters : + * int SocketIndex + * char *GroupName + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupHomeSearch (int SocketIndex, char * GroupName) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupHomeSearch (%s)", GroupName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupHomeSearchAndRelativeMove : Start home search sequence and execute a displacement + * + * - Parameters : + * int SocketIndex + * char *GroupName + * double TargetDisplacement + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupHomeSearchAndRelativeMove (int SocketIndex, char * GroupName, int NbElements, double TargetDisplacement[]) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupHomeSearchAndRelativeMove (%s,", GroupName); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "%.13g", TargetDisplacement[i]); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupInitialize : Start the initialization + * + * - Parameters : + * int SocketIndex + * char *GroupName + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupInitialize (int SocketIndex, char * GroupName) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupInitialize (%s)", GroupName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupInitializeWithEncoderCalibration : Start the initialization with encoder calibration + * + * - Parameters : + * int SocketIndex + * char *GroupName + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupInitializeWithEncoderCalibration (int SocketIndex, char * GroupName) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupInitializeWithEncoderCalibration (%s)", GroupName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupKill : Kill the group + * + * - Parameters : + * int SocketIndex + * char *GroupName + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupKill (int SocketIndex, char * GroupName) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupKill (%s)", GroupName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupMoveAbort : Abort a move + * + * - Parameters : + * int SocketIndex + * char *GroupName + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupMoveAbort (int SocketIndex, char * GroupName) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupMoveAbort (%s)", GroupName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupMoveAbsolute : Do an absolute move + * + * - Parameters : + * int SocketIndex + * char *GroupName + * double TargetPosition + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupMoveAbsolute (int SocketIndex, char * GroupName, int NbElements, double TargetPosition[]) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupMoveAbsolute (%s,", GroupName); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "%.13g", TargetPosition[i]); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupMoveRelative : Do a relative move + * + * - Parameters : + * int SocketIndex + * char *GroupName + * double TargetDisplacement + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupMoveRelative (int SocketIndex, char * GroupName, int NbElements, double TargetDisplacement[]) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupMoveRelative (%s,", GroupName); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "%.13g", TargetDisplacement[i]); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupMotionDisable : Set Motion disable on selected group + * + * - Parameters : + * int SocketIndex + * char *GroupName + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupMotionDisable (int SocketIndex, char * GroupName) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupMotionDisable (%s)", GroupName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupMotionEnable : Set Motion enable on selected group + * + * - Parameters : + * int SocketIndex + * char *GroupName + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupMotionEnable (int SocketIndex, char * GroupName) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupMotionEnable (%s)", GroupName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupPositionCorrectedProfilerGet : Return corrected profiler positions + * + * - Parameters : + * int SocketIndex + * char *GroupName + * double PositionX + * double PositionY + * double *CorrectedProfilerPositionX + * double *CorrectedProfilerPositionY + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupPositionCorrectedProfilerGet (int SocketIndex, char * GroupName, double PositionX, double PositionY, double * CorrectedProfilerPositionX, double * CorrectedProfilerPositionY) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupPositionCorrectedProfilerGet (%s,%.13g,%.13g,double *,double *)", GroupName, PositionX, PositionY); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CorrectedProfilerPositionX); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CorrectedProfilerPositionY); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupPositionCurrentGet : Return current positions + * + * - Parameters : + * int SocketIndex + * char *GroupName + * int nbElement + * double *CurrentEncoderPosition + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupPositionCurrentGet (int SocketIndex, char * GroupName, int NbElements, double CurrentEncoderPosition[]) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupPositionCurrentGet (%s,", GroupName); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "double *"); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + + for (int i = 0; i < NbElements; i++) + { + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", &CurrentEncoderPosition[i]); + } + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupPositionSetpointGet : Return setpoint positions + * + * - Parameters : + * int SocketIndex + * char *GroupName + * int nbElement + * double *SetPointPosition + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupPositionSetpointGet (int SocketIndex, char * GroupName, int NbElements, double SetPointPosition[]) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupPositionSetpointGet (%s,", GroupName); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "double *"); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + + for (int i = 0; i < NbElements; i++) + { + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", &SetPointPosition[i]); + } + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupPositionTargetGet : Return target positions + * + * - Parameters : + * int SocketIndex + * char *GroupName + * int nbElement + * double *TargetPosition + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupPositionTargetGet (int SocketIndex, char * GroupName, int NbElements, double TargetPosition[]) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + char temp[SIZE_NOMINAL]; + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupPositionTargetGet (%s,", GroupName); + for (int i = 0; i < NbElements; i++) + { + sprintf (temp, "double *"); + strncat (ExecuteMethod, temp, SIZE_SMALL); + if ((i + 1) < NbElements) + { + strncat (ExecuteMethod, ",", SIZE_SMALL); + } + } + strcat (ExecuteMethod, ")"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + + for (int i = 0; i < NbElements; i++) + { + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", &TargetPosition[i]); + } + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupStatusGet : Return group status + * + * - Parameters : + * int SocketIndex + * char *GroupName + * int *Status + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupStatusGet (int SocketIndex, char * GroupName, int * Status) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupStatusGet (%s,int *)", GroupName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", Status); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupStatusStringGet : Return the group status string corresponding to the group status code + * + * - Parameters : + * int SocketIndex + * int GroupStatusCode + * char *GroupStatusString + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupStatusStringGet (int SocketIndex, int GroupStatusCode, char * GroupStatusString) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupStatusStringGet (%d,char *)", GroupStatusCode); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (GroupStatusString, pt); + ptNext = strchr (GroupStatusString, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * KillAll : Put all groups in 'Not initialized' state + * + * - Parameters : + * int SocketIndex + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPKillAll (int SocketIndex) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "KillAll ()"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * RestartApplication : Restart the Controller + * + * - Parameters : + * int SocketIndex + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPRestartApplication (int SocketIndex) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "RestartApplication ()"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerBacklashGet : Read backlash value and status + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double *BacklashValue + * char *BacklaskStatus + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerBacklashGet (int SocketIndex, char * PositionerName, double * BacklashValue, char * BacklaskStatus) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerBacklashGet (%s,double *,char *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", BacklashValue); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (BacklaskStatus, pt); + ptNext = strchr (BacklaskStatus, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerBacklashSet : Set backlash value + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double BacklashValue + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerBacklashSet (int SocketIndex, char * PositionerName, double BacklashValue) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerBacklashSet (%s,%.13g)", PositionerName, BacklashValue); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerBacklashEnable : Enable the backlash + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerBacklashEnable (int SocketIndex, char * PositionerName) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerBacklashEnable (%s)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerBacklashDisable : Disable the backlash + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerBacklashDisable (int SocketIndex, char * PositionerName) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerBacklashDisable (%s)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerCorrectorNotchFiltersSet : Update filters parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double NotchFrequency1 + * double NotchBandwith1 + * double NotchGain1 + * double NotchFrequency2 + * double NotchBandwith2 + * double NotchGain2 + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerCorrectorNotchFiltersSet (int SocketIndex, char * PositionerName, double NotchFrequency1, double NotchBandwith1, double NotchGain1, double NotchFrequency2, double NotchBandwith2, double NotchGain2) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerCorrectorNotchFiltersSet (%s,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", PositionerName, NotchFrequency1, NotchBandwith1, NotchGain1, NotchFrequency2, NotchBandwith2, NotchGain2); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerCorrectorNotchFiltersGet : Read filters parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double *NotchFrequency1 + * double *NotchBandwith1 + * double *NotchGain1 + * double *NotchFrequency2 + * double *NotchBandwith2 + * double *NotchGain2 + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerCorrectorNotchFiltersGet (int SocketIndex, char * PositionerName, double * NotchFrequency1, double * NotchBandwith1, double * NotchGain1, double * NotchFrequency2, double * NotchBandwith2, double * NotchGain2) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerCorrectorNotchFiltersGet (%s,double *,double *,double *,double *,double *,double *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", NotchFrequency1); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", NotchBandwith1); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", NotchGain1); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", NotchFrequency2); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", NotchBandwith2); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", NotchGain2); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerCorrectorPIDFFAccelerationSet : Update corrector parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * bool ClosedLoopStatus + * double KP + * double KI + * double KD + * double KS + * double IntegrationTime + * double DerivativeFilterCutOffFrequency + * double GKP + * double GKI + * double GKD + * double KForm + * double FeedForwardGainAcceleration + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerCorrectorPIDFFAccelerationSet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double KD, double KS, double IntegrationTime, double DerivativeFilterCutOffFrequency, double GKP, double GKI, double GKD, double KForm, double FeedForwardGainAcceleration) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerCorrectorPIDFFAccelerationSet (%s,%d,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", PositionerName, ClosedLoopStatus, KP, KI, KD, KS, IntegrationTime, DerivativeFilterCutOffFrequency, GKP, GKI, GKD, KForm, FeedForwardGainAcceleration); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerCorrectorPIDFFAccelerationGet : Read corrector parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * bool *ClosedLoopStatus + * double *KP + * double *KI + * double *KD + * double *KS + * double *IntegrationTime + * double *DerivativeFilterCutOffFrequency + * double *GKP + * double *GKI + * double *GKD + * double *KForm + * double *FeedForwardGainAcceleration + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerCorrectorPIDFFAccelerationGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * KD, double * KS, double * IntegrationTime, double * DerivativeFilterCutOffFrequency, double * GKP, double * GKI, double * GKD, double * KForm, double * FeedForwardGainAcceleration) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + int boolScanTmp; + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerCorrectorPIDFFAccelerationGet (%s,bool *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", &boolScanTmp); + *ClosedLoopStatus = (bool) boolScanTmp; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KP); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KI); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KD); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KS); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", IntegrationTime); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", DerivativeFilterCutOffFrequency); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", GKP); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", GKI); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", GKD); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KForm); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", FeedForwardGainAcceleration); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerCorrectorPIDFFVelocitySet : Update corrector parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * bool ClosedLoopStatus + * double KP + * double KI + * double KD + * double KS + * double IntegrationTime + * double DerivativeFilterCutOffFrequency + * double GKP + * double GKI + * double GKD + * double KForm + * double FeedForwardGainVelocity + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerCorrectorPIDFFVelocitySet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double KD, double KS, double IntegrationTime, double DerivativeFilterCutOffFrequency, double GKP, double GKI, double GKD, double KForm, double FeedForwardGainVelocity) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerCorrectorPIDFFVelocitySet (%s,%d,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", PositionerName, ClosedLoopStatus, KP, KI, KD, KS, IntegrationTime, DerivativeFilterCutOffFrequency, GKP, GKI, GKD, KForm, FeedForwardGainVelocity); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerCorrectorPIDFFVelocityGet : Read corrector parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * bool *ClosedLoopStatus + * double *KP + * double *KI + * double *KD + * double *KS + * double *IntegrationTime + * double *DerivativeFilterCutOffFrequency + * double *GKP + * double *GKI + * double *GKD + * double *KForm + * double *FeedForwardGainVelocity + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerCorrectorPIDFFVelocityGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * KD, double * KS, double * IntegrationTime, double * DerivativeFilterCutOffFrequency, double * GKP, double * GKI, double * GKD, double * KForm, double * FeedForwardGainVelocity) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + int boolScanTmp; + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerCorrectorPIDFFVelocityGet (%s,bool *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", &boolScanTmp); + *ClosedLoopStatus = (bool) boolScanTmp; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KP); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KI); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KD); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KS); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", IntegrationTime); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", DerivativeFilterCutOffFrequency); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", GKP); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", GKI); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", GKD); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KForm); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", FeedForwardGainVelocity); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerCorrectorPIDDualFFVoltageSet : Update corrector parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * bool ClosedLoopStatus + * double KP + * double KI + * double KD + * double KS + * double IntegrationTime + * double DerivativeFilterCutOffFrequency + * double GKP + * double GKI + * double GKD + * double KForm + * double FeedForwardGainVelocity + * double FeedForwardGainAcceleration + * double Friction + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerCorrectorPIDDualFFVoltageSet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double KD, double KS, double IntegrationTime, double DerivativeFilterCutOffFrequency, double GKP, double GKI, double GKD, double KForm, double FeedForwardGainVelocity, double FeedForwardGainAcceleration, double Friction) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerCorrectorPIDDualFFVoltageSet (%s,%d,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", PositionerName, ClosedLoopStatus, KP, KI, KD, KS, IntegrationTime, DerivativeFilterCutOffFrequency, GKP, GKI, GKD, KForm, FeedForwardGainVelocity, FeedForwardGainAcceleration, Friction); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerCorrectorPIDDualFFVoltageGet : Read corrector parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * bool *ClosedLoopStatus + * double *KP + * double *KI + * double *KD + * double *KS + * double *IntegrationTime + * double *DerivativeFilterCutOffFrequency + * double *GKP + * double *GKI + * double *GKD + * double *KForm + * double *FeedForwardGainVelocity + * double *FeedForwardGainAcceleration + * double *Friction + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerCorrectorPIDDualFFVoltageGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * KD, double * KS, double * IntegrationTime, double * DerivativeFilterCutOffFrequency, double * GKP, double * GKI, double * GKD, double * KForm, double * FeedForwardGainVelocity, double * FeedForwardGainAcceleration, double * Friction) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + int boolScanTmp; + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerCorrectorPIDDualFFVoltageGet (%s,bool *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *,double *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", &boolScanTmp); + *ClosedLoopStatus = (bool) boolScanTmp; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KP); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KI); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KD); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KS); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", IntegrationTime); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", DerivativeFilterCutOffFrequency); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", GKP); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", GKI); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", GKD); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KForm); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", FeedForwardGainVelocity); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", FeedForwardGainAcceleration); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", Friction); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerCorrectorPIPositionSet : Update corrector parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * bool ClosedLoopStatus + * double KP + * double KI + * double IntegrationTime + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerCorrectorPIPositionSet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double IntegrationTime) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerCorrectorPIPositionSet (%s,%d,%.13g,%.13g,%.13g)", PositionerName, ClosedLoopStatus, KP, KI, IntegrationTime); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerCorrectorPIPositionGet : Read corrector parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * bool *ClosedLoopStatus + * double *KP + * double *KI + * double *IntegrationTime + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerCorrectorPIPositionGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * IntegrationTime) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + int boolScanTmp; + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerCorrectorPIPositionGet (%s,bool *,double *,double *,double *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", &boolScanTmp); + *ClosedLoopStatus = (bool) boolScanTmp; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KP); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", KI); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", IntegrationTime); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerCorrectorTypeGet : Read corrector type + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * char *CorrectorType + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerCorrectorTypeGet (int SocketIndex, char * PositionerName, char * CorrectorType) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerCorrectorTypeGet (%s,char *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (CorrectorType, pt); + ptNext = strchr (CorrectorType, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerCurrentVelocityAccelerationFiltersSet : Set current velocity and acceleration cut off frequencies + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double CurrentVelocityCutOffFrequency + * double CurrentAccelerationCutOffFrequency + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerCurrentVelocityAccelerationFiltersSet (int SocketIndex, char * PositionerName, double CurrentVelocityCutOffFrequency, double CurrentAccelerationCutOffFrequency) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerCurrentVelocityAccelerationFiltersSet (%s,%.13g,%.13g)", PositionerName, CurrentVelocityCutOffFrequency, CurrentAccelerationCutOffFrequency); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerCurrentVelocityAccelerationFiltersGet : Get current velocity and acceleration cut off frequencies + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double *CurrentVelocityCutOffFrequency + * double *CurrentAccelerationCutOffFrequency + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerCurrentVelocityAccelerationFiltersGet (int SocketIndex, char * PositionerName, double * CurrentVelocityCutOffFrequency, double * CurrentAccelerationCutOffFrequency) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerCurrentVelocityAccelerationFiltersGet (%s,double *,double *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CurrentVelocityCutOffFrequency); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CurrentAccelerationCutOffFrequency); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerDriverStatusGet : Read positioner driver status + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * int *DriverStatus + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerDriverStatusGet (int SocketIndex, char * PositionerName, int * DriverStatus) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerDriverStatusGet (%s,int *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", DriverStatus); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerDriverStatusStringGet : Return the positioner driver status string corresponding to the positioner error code + * + * - Parameters : + * int SocketIndex + * int PositionerDriverStatus + * char *PositionerDriverStatusString + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerDriverStatusStringGet (int SocketIndex, int PositionerDriverStatus, char * PositionerDriverStatusString) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerDriverStatusStringGet (%d,char *)", PositionerDriverStatus); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (PositionerDriverStatusString, pt); + ptNext = strchr (PositionerDriverStatusString, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerEncoderAmplitudeValuesGet : Read analog interpolated encoder amplitude values + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double *CalibrationSinusAmplitude + * double *CurrentSinusAmplitude + * double *CalibrationCosinusAmplitude + * double *CurrentCosinusAmplitude + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerEncoderAmplitudeValuesGet (int SocketIndex, char * PositionerName, double * CalibrationSinusAmplitude, double * CurrentSinusAmplitude, double * CalibrationCosinusAmplitude, double * CurrentCosinusAmplitude) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerEncoderAmplitudeValuesGet (%s,double *,double *,double *,double *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CalibrationSinusAmplitude); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CurrentSinusAmplitude); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CalibrationCosinusAmplitude); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CurrentCosinusAmplitude); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerEncoderCalibrationParametersGet : Read analog interpolated encoder calibration parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double *SinusOffset + * double *CosinusOffset + * double *DifferentialGain + * double *PhaseCompensation + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerEncoderCalibrationParametersGet (int SocketIndex, char * PositionerName, double * SinusOffset, double * CosinusOffset, double * DifferentialGain, double * PhaseCompensation) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerEncoderCalibrationParametersGet (%s,double *,double *,double *,double *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", SinusOffset); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CosinusOffset); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", DifferentialGain); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", PhaseCompensation); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerErrorGet : Read and clear positioner error code + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * int *ErrorCode + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerErrorGet (int SocketIndex, char * PositionerName, int * ErrorCode) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerErrorGet (%s,int *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", ErrorCode); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerErrorRead : Read only positioner error code without clear it + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * int *ErrorCode + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerErrorRead (int SocketIndex, char * PositionerName, int * ErrorCode) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerErrorRead (%s,int *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", ErrorCode); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerErrorStringGet : Return the positioner status string corresponding to the positioner error code + * + * - Parameters : + * int SocketIndex + * int PositionerErrorCode + * char *PositionerErrorString + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerErrorStringGet (int SocketIndex, int PositionerErrorCode, char * PositionerErrorString) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerErrorStringGet (%d,char *)", PositionerErrorCode); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (PositionerErrorString, pt); + ptNext = strchr (PositionerErrorString, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerHardwareStatusGet : Read positioner hardware status + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * int *HardwareStatus + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerHardwareStatusGet (int SocketIndex, char * PositionerName, int * HardwareStatus) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerHardwareStatusGet (%s,int *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", HardwareStatus); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerHardwareStatusStringGet : Return the positioner hardware status string corresponding to the positioner error code + * + * - Parameters : + * int SocketIndex + * int PositionerHardwareStatus + * char *PositionerHardwareStatusString + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerHardwareStatusStringGet (int SocketIndex, int PositionerHardwareStatus, char * PositionerHardwareStatusString) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerHardwareStatusStringGet (%d,char *)", PositionerHardwareStatus); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (PositionerHardwareStatusString, pt); + ptNext = strchr (PositionerHardwareStatusString, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerHardInterpolatorFactorGet : Get hard interpolator parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * int *InterpolationFactor + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerHardInterpolatorFactorGet (int SocketIndex, char * PositionerName, int * InterpolationFactor) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerHardInterpolatorFactorGet (%s,int *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", InterpolationFactor); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerHardInterpolatorFactorSet : Set hard interpolator parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * int InterpolationFactor + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerHardInterpolatorFactorSet (int SocketIndex, char * PositionerName, int InterpolationFactor) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerHardInterpolatorFactorSet (%s,%d)", PositionerName, InterpolationFactor); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerMaximumVelocityAndAccelerationGet : Return maximum velocity and acceleration of the positioner + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double *MaximumVelocity + * double *MaximumAcceleration + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerMaximumVelocityAndAccelerationGet (int SocketIndex, char * PositionerName, double * MaximumVelocity, double * MaximumAcceleration) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerMaximumVelocityAndAccelerationGet (%s,double *,double *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", MaximumVelocity); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", MaximumAcceleration); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerMotionDoneGet : Read motion done parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double *PositionWindow + * double *VelocityWindow + * double *CheckingTime + * double *MeanPeriod + * double *TimeOut + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerMotionDoneGet (int SocketIndex, char * PositionerName, double * PositionWindow, double * VelocityWindow, double * CheckingTime, double * MeanPeriod, double * TimeOut) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerMotionDoneGet (%s,double *,double *,double *,double *,double *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", PositionWindow); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", VelocityWindow); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CheckingTime); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", MeanPeriod); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", TimeOut); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerMotionDoneSet : Update motion done parameters + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double PositionWindow + * double VelocityWindow + * double CheckingTime + * double MeanPeriod + * double TimeOut + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerMotionDoneSet (int SocketIndex, char * PositionerName, double PositionWindow, double VelocityWindow, double CheckingTime, double MeanPeriod, double TimeOut) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerMotionDoneSet (%s,%.13g,%.13g,%.13g,%.13g,%.13g)", PositionerName, PositionWindow, VelocityWindow, CheckingTime, MeanPeriod, TimeOut); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerSGammaExactVelocityAjustedDisplacementGet : Return adjusted displacement to get exact velocity + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double DesiredDisplacement + * double *AdjustedDisplacement + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerSGammaExactVelocityAjustedDisplacementGet (int SocketIndex, char * PositionerName, double DesiredDisplacement, double * AdjustedDisplacement) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerSGammaExactVelocityAjustedDisplacementGet (%s,%.13g,double *)", PositionerName, DesiredDisplacement); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", AdjustedDisplacement); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerSGammaParametersGet : Read dynamic parameters for one axe of a group for a future displacement + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double *Velocity + * double *Acceleration + * double *MinimumTjerkTime + * double *MaximumTjerkTime + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerSGammaParametersGet (int SocketIndex, char * PositionerName, double * Velocity, double * Acceleration, double * MinimumTjerkTime, double * MaximumTjerkTime) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerSGammaParametersGet (%s,double *,double *,double *,double *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", Velocity); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", Acceleration); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", MinimumTjerkTime); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", MaximumTjerkTime); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerSGammaParametersSet : Update dynamic parameters for one axe of a group for a future displacement + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double Velocity + * double Acceleration + * double MinimumTjerkTime + * double MaximumTjerkTime + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerSGammaParametersSet (int SocketIndex, char * PositionerName, double Velocity, double Acceleration, double MinimumTjerkTime, double MaximumTjerkTime) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerSGammaParametersSet (%s,%.13g,%.13g,%.13g,%.13g)", PositionerName, Velocity, Acceleration, MinimumTjerkTime, MaximumTjerkTime); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerSGammaPreviousMotionTimesGet : Read SettingTime and SettlingTime + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double *SettingTime + * double *SettlingTime + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerSGammaPreviousMotionTimesGet (int SocketIndex, char * PositionerName, double * SettingTime, double * SettlingTime) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerSGammaPreviousMotionTimesGet (%s,double *,double *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", SettingTime); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", SettlingTime); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerStageParameterGet : Return the stage parameter + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * char *ParameterName + * char *ParameterValue + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerStageParameterGet (int SocketIndex, char * PositionerName, char * ParameterName, char * ParameterValue) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerStageParameterGet (%s,%s,char *)", PositionerName, ParameterName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (ParameterValue, pt); + ptNext = strchr (ParameterValue, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerStageParameterSet : Save the stage parameter + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * char *ParameterName + * char *ParameterValue + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerStageParameterSet (int SocketIndex, char * PositionerName, char * ParameterName, char * ParameterValue) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerStageParameterSet (%s,%s,%s)", PositionerName, ParameterName, ParameterValue); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerUserTravelLimitsGet : Read UserMinimumTarget and UserMaximumTarget + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double *UserMinimumTarget + * double *UserMaximumTarget + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerUserTravelLimitsGet (int SocketIndex, char * PositionerName, double * UserMinimumTarget, double * UserMaximumTarget) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerUserTravelLimitsGet (%s,double *,double *)", PositionerName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", UserMinimumTarget); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", UserMaximumTarget); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerUserTravelLimitsSet : Update UserMinimumTarget and UserMaximumTarget + * + * - Parameters : + * int SocketIndex + * char *PositionerName + * double UserMinimumTarget + * double UserMaximumTarget + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerUserTravelLimitsSet (int SocketIndex, char * PositionerName, double UserMinimumTarget, double UserMaximumTarget) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerUserTravelLimitsSet (%s,%.13g,%.13g)", PositionerName, UserMinimumTarget, UserMaximumTarget); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * HexapodMoveAbsolute : Hexapod absolute move in a specific coordinate system + * + * - Parameters : + * int SocketIndex + * char *GroupName + * char *CoordinateSystem + * double X + * double Y + * double Z + * double U + * double V + * double W + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPHexapodMoveAbsolute (int SocketIndex, char * GroupName, char * CoordinateSystem, double X, double Y, double Z, double U, double V, double W) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "HexapodMoveAbsolute (%s,%s,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", GroupName, CoordinateSystem, X, Y, Z, U, V, W); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * HexapodMoveIncremental : Hexapod incremental move in a specific coordinate system + * + * - Parameters : + * int SocketIndex + * char *GroupName + * char *CoordinateSystem + * double dX + * double dY + * double dZ + * double dU + * double dV + * double dW + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPHexapodMoveIncremental (int SocketIndex, char * GroupName, char * CoordinateSystem, double dX, double dY, double dZ, double dU, double dV, double dW) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "HexapodMoveIncremental (%s,%s,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", GroupName, CoordinateSystem, dX, dY, dZ, dU, dV, dW); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * HexapodCoordinatesGet : Get coordinates in a specific coordinate system of a point specified in another coordinate system + * + * - Parameters : + * int SocketIndex + * char *GroupName + * char *CoordinateSystemIn + * char *CoordinateSystemOut + * double Xin + * double Yin + * double Zin + * double Uin + * double Vin + * double Win + * double *Xout + * double *Yout + * double *Zout + * double *Uout + * double *Vout + * double *Wout + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPHexapodCoordinatesGet (int SocketIndex, char * GroupName, char * CoordinateSystemIn, char * CoordinateSystemOut, double Xin, double Yin, double Zin, double Uin, double Vin, double Win, double * Xout, double * Yout, double * Zout, double * Uout, double * Vout, double * Wout) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "HexapodCoordinatesGet (%s,%s,%s,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g,double *,double *,double *,double *,double *,double *)", GroupName, CoordinateSystemIn, CoordinateSystemOut, Xin, Yin, Zin, Uin, Vin, Win); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", Xout); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", Yout); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", Zout); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", Uout); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", Vout); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", Wout); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * HexapodCoordinateSystemSet : Modify the position of a coordinate system + * + * - Parameters : + * int SocketIndex + * char *GroupName + * char *CoordinateSystem + * double X + * double Y + * double Z + * double U + * double V + * double W + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPHexapodCoordinateSystemSet (int SocketIndex, char * GroupName, char * CoordinateSystem, double X, double Y, double Z, double U, double V, double W) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "HexapodCoordinateSystemSet (%s,%s,%.13g,%.13g,%.13g,%.13g,%.13g,%.13g)", GroupName, CoordinateSystem, X, Y, Z, U, V, W); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * HexapodCoordinateSystemGet : Get the position of a coordinate system + * + * - Parameters : + * int SocketIndex + * char *GroupName + * char *CoordinateSystem + * double *X + * double *Y + * double *Z + * double *U + * double *V + * double *W + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPHexapodCoordinateSystemGet (int SocketIndex, char * GroupName, char * CoordinateSystem, double * X, double * Y, double * Z, double * U, double * V, double * W) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "HexapodCoordinateSystemGet (%s,%s,double *,double *,double *,double *,double *,double *)", GroupName, CoordinateSystem); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", X); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", Y); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", Z); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", U); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", V); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", W); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * OptionalModuleExecute : Execute an optional module + * + * - Parameters : + * int SocketIndex + * char *ModuleFileName + * char *TaskName + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPOptionalModuleExecute (int SocketIndex, char * ModuleFileName, char * TaskName) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "OptionalModuleExecute (%s,%s)", ModuleFileName, TaskName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * OptionalModuleKill : Kill an optional module + * + * - Parameters : + * int SocketIndex + * char *TaskName + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPOptionalModuleKill (int SocketIndex, char * TaskName) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "OptionalModuleKill (%s)", TaskName); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * ControllerStatusGet : Read controller current status + * + * - Parameters : + * int SocketIndex + * int *ControllerStatus + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPControllerStatusGet (int SocketIndex, int * ControllerStatus) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "ControllerStatusGet (int *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%d", ControllerStatus); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * ControllerStatusStringGet : Return the controller status string corresponding to the controller status code + * + * - Parameters : + * int SocketIndex + * int ControllerStatusCode + * char *ControllerStatusString + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPControllerStatusStringGet (int SocketIndex, int ControllerStatusCode, char * ControllerStatusString) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "ControllerStatusStringGet (%d,char *)", ControllerStatusCode); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (ControllerStatusString, pt); + ptNext = strchr (ControllerStatusString, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EEPROMCIESet : Set CIE EEPROM reference string + * + * - Parameters : + * int SocketIndex + * int CardNumber + * char *ReferenceString + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEEPROMCIESet (int SocketIndex, int CardNumber, char * ReferenceString) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "EEPROMCIESet (%d,%s)", CardNumber, ReferenceString); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EEPROMDACOffsetCIESet : Set CIE DAC offsets + * + * - Parameters : + * int SocketIndex + * int PlugNumber + * double DAC1Offset + * double DAC2Offset + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEEPROMDACOffsetCIESet (int SocketIndex, int PlugNumber, double DAC1Offset, double DAC2Offset) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "EEPROMDACOffsetCIESet (%d,%.13g,%.13g)", PlugNumber, DAC1Offset, DAC2Offset); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EEPROMDriverSet : Set Driver EEPROM reference string + * + * - Parameters : + * int SocketIndex + * int PlugNumber + * char *ReferenceString + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEEPROMDriverSet (int SocketIndex, int PlugNumber, char * ReferenceString) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "EEPROMDriverSet (%d,%s)", PlugNumber, ReferenceString); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EEPROMINTSet : Set INT EEPROM reference string + * + * - Parameters : + * int SocketIndex + * int CardNumber + * char *ReferenceString + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEEPROMINTSet (int SocketIndex, int CardNumber, char * ReferenceString) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "EEPROMINTSet (%d,%s)", CardNumber, ReferenceString); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * CPUCoreAndBoardSupplyVoltagesGet : Get power informations + * + * - Parameters : + * int SocketIndex + * double *VoltageCPUCore + * double *SupplyVoltage1P5V + * double *SupplyVoltage3P3V + * double *SupplyVoltage5V + * double *SupplyVoltage12V + * double *SupplyVoltageM12V + * double *SupplyVoltageM5V + * double *SupplyVoltage5VSB + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPCPUCoreAndBoardSupplyVoltagesGet (int SocketIndex, double * VoltageCPUCore, double * SupplyVoltage1P5V, double * SupplyVoltage3P3V, double * SupplyVoltage5V, double * SupplyVoltage12V, double * SupplyVoltageM12V, double * SupplyVoltageM5V, double * SupplyVoltage5VSB) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "CPUCoreAndBoardSupplyVoltagesGet (double *,double *,double *,double *,double *,double *,double *,double *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", VoltageCPUCore); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", SupplyVoltage1P5V); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", SupplyVoltage3P3V); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", SupplyVoltage5V); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", SupplyVoltage12V); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", SupplyVoltageM12V); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", SupplyVoltageM5V); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", SupplyVoltage5VSB); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * CPUTemperatureAndFanSpeedGet : Get CPU temperature and fan speed + * + * - Parameters : + * int SocketIndex + * double *CPUTemperature + * double *CPUFanSpeed + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPCPUTemperatureAndFanSpeedGet (int SocketIndex, double * CPUTemperature, double * CPUFanSpeed) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "CPUTemperatureAndFanSpeedGet (double *,double *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CPUTemperature); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", CPUFanSpeed); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * ActionListGet : Action list + * + * - Parameters : + * int SocketIndex + * char *ActionList + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPActionListGet (int SocketIndex, char * ActionList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "ActionListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (ActionList, pt); + ptNext = strchr (ActionList, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * ActionExtendedListGet : Action extended list + * + * - Parameters : + * int SocketIndex + * char *ActionList + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPActionExtendedListGet (int SocketIndex, char * ActionList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "ActionExtendedListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (ActionList, pt); + ptNext = strchr (ActionList, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * APIExtendedListGet : API method list + * + * - Parameters : + * int SocketIndex + * char *Method + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPAPIExtendedListGet (int SocketIndex, char * Method) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); + + /* Convert to string */ + sprintf (ExecuteMethod, "APIExtendedListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (Method, pt); + ptNext = strchr (Method, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * APIListGet : API method list without extended API + * + * - Parameters : + * int SocketIndex + * char *Method + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPAPIListGet (int SocketIndex, char * Method) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); + + /* Convert to string */ + sprintf (ExecuteMethod, "APIListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (Method, pt); + ptNext = strchr (Method, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * ErrorListGet : Error list + * + * - Parameters : + * int SocketIndex + * char *ErrorsList + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPErrorListGet (int SocketIndex, char * ErrorsList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); + + /* Convert to string */ + sprintf (ExecuteMethod, "ErrorListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (ErrorsList, pt); + ptNext = strchr (ErrorsList, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * EventListGet : General event list + * + * - Parameters : + * int SocketIndex + * char *EventList + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPEventListGet (int SocketIndex, char * EventList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "EventListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (EventList, pt); + ptNext = strchr (EventList, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringListGet : Gathering type list + * + * - Parameters : + * int SocketIndex + * char *list + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringListGet (int SocketIndex, char * list) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (list, pt); + ptNext = strchr (list, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringExtendedListGet : Gathering type extended list + * + * - Parameters : + * int SocketIndex + * char *list + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringExtendedListGet (int SocketIndex, char * list) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringExtendedListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (list, pt); + ptNext = strchr (list, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringExternalListGet : External Gathering type list + * + * - Parameters : + * int SocketIndex + * char *list + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringExternalListGet (int SocketIndex, char * list) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringExternalListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (list, pt); + ptNext = strchr (list, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GroupStatusListGet : Group status list + * + * - Parameters : + * int SocketIndex + * char *GroupStatusList + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGroupStatusListGet (int SocketIndex, char * GroupStatusList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); + + /* Convert to string */ + sprintf (ExecuteMethod, "GroupStatusListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (GroupStatusList, pt); + ptNext = strchr (GroupStatusList, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * HardwareInternalListGet : Internal hardware list + * + * - Parameters : + * int SocketIndex + * char *InternalHardwareList + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPHardwareInternalListGet (int SocketIndex, char * InternalHardwareList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); + + /* Convert to string */ + sprintf (ExecuteMethod, "HardwareInternalListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (InternalHardwareList, pt); + ptNext = strchr (InternalHardwareList, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * HardwareDriverAndStageGet : Smart hardware + * + * - Parameters : + * int SocketIndex + * int PlugNumber + * char *DriverName + * char *StageName + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPHardwareDriverAndStageGet (int SocketIndex, int PlugNumber, char * DriverName, char * StageName) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_NOMINAL); + + /* Convert to string */ + sprintf (ExecuteMethod, "HardwareDriverAndStageGet (%d,char *,char *)", PlugNumber); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_NOMINAL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (DriverName, pt); + ptNext = strchr (DriverName, ','); + if (ptNext != NULL) *ptNext = '\0'; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (StageName, pt); + ptNext = strchr (StageName, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * ObjectsListGet : Group name and positioner name + * + * - Parameters : + * int SocketIndex + * char *ObjectsList + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPObjectsListGet (int SocketIndex, char * ObjectsList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_HUGE); + + /* Convert to string */ + sprintf (ExecuteMethod, "ObjectsListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_HUGE); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (ObjectsList, pt); + ptNext = strchr (ObjectsList, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerErrorListGet : Positioner error list + * + * - Parameters : + * int SocketIndex + * char *PositionerErrorList + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerErrorListGet (int SocketIndex, char * PositionerErrorList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerErrorListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (PositionerErrorList, pt); + ptNext = strchr (PositionerErrorList, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerHardwareStatusListGet : Positioner hardware status list + * + * - Parameters : + * int SocketIndex + * char *PositionerHardwareStatusList + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerHardwareStatusListGet (int SocketIndex, char * PositionerHardwareStatusList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerHardwareStatusListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (PositionerHardwareStatusList, pt); + ptNext = strchr (PositionerHardwareStatusList, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PositionerDriverStatusListGet : Positioner driver status list + * + * - Parameters : + * int SocketIndex + * char *PositionerDriverStatusList + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPositionerDriverStatusListGet (int SocketIndex, char * PositionerDriverStatusList) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "PositionerDriverStatusListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (PositionerDriverStatusList, pt); + ptNext = strchr (PositionerDriverStatusList, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * ReferencingActionListGet : Get referencing action list + * + * - Parameters : + * int SocketIndex + * char *list + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPReferencingActionListGet (int SocketIndex, char * list) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "ReferencingActionListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (list, pt); + ptNext = strchr (list, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * ReferencingSensorListGet : Get referencing sensor list + * + * - Parameters : + * int SocketIndex + * char *list + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPReferencingSensorListGet (int SocketIndex, char * list) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_BIG); + + /* Convert to string */ + sprintf (ExecuteMethod, "ReferencingSensorListGet (char *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_BIG); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (list, pt); + ptNext = strchr (list, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * GatheringUserDatasGet : Return UserDatas values + * + * - Parameters : + * int SocketIndex + * double *UserData1 + * double *UserData2 + * double *UserData3 + * double *UserData4 + * double *UserData5 + * double *UserData6 + * double *UserData7 + * double *UserData8 + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPGatheringUserDatasGet (int SocketIndex, double * UserData1, double * UserData2, double * UserData3, double * UserData4, double * UserData5, double * UserData6, double * UserData7, double * UserData8) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "GatheringUserDatasGet (double *,double *,double *,double *,double *,double *,double *,double *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", UserData1); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", UserData2); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", UserData3); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", UserData4); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", UserData5); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", UserData6); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", UserData7); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", UserData8); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * ControllerMotionKernelPeriodMinMaxGet : Get controller motion kernel min/max periods + * + * - Parameters : + * int SocketIndex + * double *MinimumCorrectorPeriod + * double *MaximumCorrectorPeriod + * double *MinimumProfilerPeriod + * double *MaximumProfilerPeriod + * double *MinimumServitudesPeriod + * double *MaximumServitudesPeriod + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPControllerMotionKernelPeriodMinMaxGet (int SocketIndex, double * MinimumCorrectorPeriod, double * MaximumCorrectorPeriod, double * MinimumProfilerPeriod, double * MaximumProfilerPeriod, double * MinimumServitudesPeriod, double * MaximumServitudesPeriod) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "ControllerMotionKernelPeriodMinMaxGet (double *,double *,double *,double *,double *,double *)"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", MinimumCorrectorPeriod); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", MaximumCorrectorPeriod); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", MinimumProfilerPeriod); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", MaximumProfilerPeriod); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", MinimumServitudesPeriod); + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) sscanf (pt, "%lf", MaximumServitudesPeriod); + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * ControllerMotionKernelPeriodMinMaxReset : Reset controller motion kernel min/max periods + * + * - Parameters : + * int SocketIndex + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPControllerMotionKernelPeriodMinMaxReset (int SocketIndex) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "ControllerMotionKernelPeriodMinMaxReset ()"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * TestTCP : Test TCP/IP transfert + * + * - Parameters : + * int SocketIndex + * char *InputString + * char *ReturnString + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPTestTCP (int SocketIndex, char * InputString, char * ReturnString) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "TestTCP (%s,char *)", InputString); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (ret == 0) + { + char * pt; + char * ptNext; + + pt = ReturnedValue; + ptNext = NULL; + if (pt != NULL) pt = strchr (pt, ','); + if (pt != NULL) pt++; + if (pt != NULL) strcpy (ReturnString, pt); + ptNext = strchr (ReturnString, ','); + if (ptNext != NULL) *ptNext = '\0'; + } + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + +/*********************************************************************** + * PrepareForUpdate : Kill QNX processes for firmware update + * + * - Parameters : + * int SocketIndex + * - Return : + * int errorCode + ***********************************************************************/ +int __stdcall HXPPrepareForUpdate (int SocketIndex) +{ + int ret = -1; + char ExecuteMethod[SIZE_EXECUTE_METHOD]; + char *ReturnedValue = (char *) malloc (sizeof(char) * SIZE_SMALL); + + /* Convert to string */ + sprintf (ExecuteMethod, "PrepareForUpdate ()"); + + /* Send this string and wait return function from controller */ + /* return function : ==0 -> OK ; < 0 -> NOK */ + SendAndReceive (SocketIndex, ExecuteMethod, ReturnedValue, SIZE_SMALL); + if (strlen (ReturnedValue) > 0) + sscanf (ReturnedValue, "%i", &ret); + + /* Get the returned values in the out parameters */ + if (NULL != ReturnedValue) + free (ReturnedValue); + + return (ret); +} + + + +#ifdef __cplusplus +} +#endif diff --git a/motorApp/NewportSrc/hxp_drivers.h b/motorApp/NewportSrc/hxp_drivers.h index 45c6bc2..09ddc3e 100644 --- a/motorApp/NewportSrc/hxp_drivers.h +++ b/motorApp/NewportSrc/hxp_drivers.h @@ -1,181 +1,180 @@ -/************************************************* - * XPS_API.h * - * * - * Description: * - * XPS functions * - *************************************************/ - -#ifdef _WIN32 - #ifndef DLL - #ifdef _DLL /* _DLL is defined by EPICS if we are being compiled to call DLLs */ - #define DLL _declspec(dllimport) - #else - #define DLL - #endif - #endif -#else - #define DLL - #define __stdcall -#endif -#ifdef __cplusplus -extern "C" -{ -#else -#typedef int bool; /* C does not know bool, only C++ */ -#endif - - -DLL int __stdcall HXPTCP_ConnectToServer(char *Ip_Address, int Ip_Port, double TimeOut); -DLL void __stdcall HXPTCP_SetTimeout(int SocketIndex, double Timeout); -DLL void __stdcall HXPTCP_CloseSocket(int SocketIndex); -DLL char * __stdcall HXPTCP_GetError(int SocketIndex); -DLL char * __stdcall HXPGetLibraryVersion(void); -DLL int __stdcall HXPControllerMotionKernelTimeLoadGet (int SocketIndex, double * CPUTotalLoadRatio, double * CPUCorrectorLoadRatio, double * CPUProfilerLoadRatio, double * CPUServitudesLoadRatio); /* Get controller motion kernel time load */ -DLL int __stdcall HXPElapsedTimeGet (int SocketIndex, double * ElapsedTime); /* Return elapsed time from controller power on */ -DLL int __stdcall HXPErrorStringGet (int SocketIndex, int ErrorCode, char * ErrorString); /* Return the error string corresponding to the error code */ -DLL int __stdcall HXPFirmwareVersionGet (int SocketIndex, char * Version); /* Return firmware version */ -DLL int __stdcall HXPTCLScriptExecute (int SocketIndex, char * TCLFileName, char * TaskName, char * ParametersList); /* Execute a TCL script from a TCL file */ -DLL int __stdcall HXPTCLScriptExecuteAndWait (int SocketIndex, char * TCLFileName, char * TaskName, char * InputParametersList, char * OutputParametersList); /* Execute a TCL script from a TCL file and wait the end of execution to return */ -DLL int __stdcall HXPTCLScriptKill (int SocketIndex, char * TaskName); /* Kill TCL Task */ -DLL int __stdcall HXPTimerGet (int SocketIndex, char * TimerName, int * FrequencyTicks); /* Get a timer */ -DLL int __stdcall HXPTimerSet (int SocketIndex, char * TimerName, int FrequencyTicks); /* Set a timer */ -DLL int __stdcall HXPReboot (int SocketIndex); /* Reboot the controller */ -DLL int __stdcall HXPLogin (int SocketIndex, char * Name, char * Password); /* Log in */ -DLL int __stdcall HXPCloseAllOtherSockets (int SocketIndex); /* Close all socket beside the one used to send this command */ -DLL int __stdcall HXPEventAdd (int SocketIndex, char * PositionerName, char * EventName, char * EventParameter, char * ActionName, char * ActionParameter1, char * ActionParameter2, char * ActionParameter3); /* ** OBSOLETE ** Add an event */ -DLL int __stdcall HXPEventGet (int SocketIndex, char * PositionerName, char * EventsAndActionsList); /* ** OBSOLETE ** Read events and actions list */ -DLL int __stdcall HXPEventRemove (int SocketIndex, char * PositionerName, char * EventName, char * EventParameter); /* ** OBSOLETE ** Delete an event */ -DLL int __stdcall HXPEventWait (int SocketIndex, char * PositionerName, char * EventName, char * EventParameter); /* ** OBSOLETE ** Wait an event */ -DLL int __stdcall HXPEventExtendedConfigurationTriggerSet (int SocketIndex, int NbElements, char * ExtendedEventNameList, char * EventParameter1List, char * EventParameter2List, char * EventParameter3List, char * EventParameter4List); /* Configure one or several events */ -DLL int __stdcall HXPEventExtendedConfigurationTriggerGet (int SocketIndex, char * EventTriggerConfiguration); /* Read the event configuration */ -DLL int __stdcall HXPEventExtendedConfigurationActionSet (int SocketIndex, int NbElements, char * ExtendedActionNameList, char * ActionParameter1List, char * ActionParameter2List, char * ActionParameter3List, char * ActionParameter4List); /* Configure one or several actions */ -DLL int __stdcall HXPEventExtendedConfigurationActionGet (int SocketIndex, char * ActionConfiguration); /* Read the action configuration */ -DLL int __stdcall HXPEventExtendedStart (int SocketIndex, int * ID); /* Launch the last event and action configuration and return an ID */ -DLL int __stdcall HXPEventExtendedAllGet (int SocketIndex, char * EventActionConfigurations); /* Read all event and action configurations */ -DLL int __stdcall HXPEventExtendedGet (int SocketIndex, int ID, char * EventTriggerConfiguration, char * ActionConfiguration); /* Read the event and action configuration defined by ID */ -DLL int __stdcall HXPEventExtendedRemove (int SocketIndex, int ID); /* Remove the event and action configuration defined by ID */ -DLL int __stdcall HXPEventExtendedWait (int SocketIndex); /* Wait events from the last event configuration */ -DLL int __stdcall HXPGatheringConfigurationGet (int SocketIndex, char * Type); /* Read different mnemonique type */ -DLL int __stdcall HXPGatheringConfigurationSet (int SocketIndex, int NbElements, char * TypeList); /* Configuration acquisition */ -DLL int __stdcall HXPGatheringCurrentNumberGet (int SocketIndex, int * CurrentNumber, int * MaximumSamplesNumber); /* Maximum number of samples and current number during acquisition */ -DLL int __stdcall HXPGatheringStopAndSave (int SocketIndex); /* Stop acquisition and save data */ -DLL int __stdcall HXPGatheringDataAcquire (int SocketIndex); /* Acquire a configured data */ -DLL int __stdcall HXPGatheringDataGet (int SocketIndex, int IndexPoint, char * DataBufferLine); /* Get a data line from gathering buffer */ -DLL int __stdcall HXPGatheringReset (int SocketIndex); /* Empty the gathered data in memory to start new gathering from scratch */ -DLL int __stdcall HXPGatheringRun (int SocketIndex, int DataNumber, int Divisor); /* Start a new gathering */ -DLL int __stdcall HXPGatheringStop (int SocketIndex); /* Stop the data gathering (without saving to file) */ -DLL int __stdcall HXPGatheringExternalConfigurationSet (int SocketIndex, int NbElements, char * TypeList); /* Configuration acquisition */ -DLL int __stdcall HXPGatheringExternalConfigurationGet (int SocketIndex, char * Type); /* Read different mnemonique type */ -DLL int __stdcall HXPGatheringExternalCurrentNumberGet (int SocketIndex, int * CurrentNumber, int * MaximumSamplesNumber); /* Maximum number of samples and current number during acquisition */ -DLL int __stdcall HXPGatheringExternalStopAndSave (int SocketIndex); /* Stop acquisition and save data */ -DLL int __stdcall HXPGlobalArrayGet (int SocketIndex, int Number, char * ValueString); /* Get global array value */ -DLL int __stdcall HXPGlobalArraySet (int SocketIndex, int Number, char * ValueString); /* Set global array value */ -DLL int __stdcall HXPDoubleGlobalArrayGet (int SocketIndex, int Number, double * DoubleValue); /* Get double global array value */ -DLL int __stdcall HXPDoubleGlobalArraySet (int SocketIndex, int Number, double DoubleValue); /* Set double global array value */ -DLL int __stdcall HXPGPIOAnalogGet (int SocketIndex, int NbElements, char * GPIONameList, double AnalogValue[]); /* Read analog input or analog output for one or few input */ -DLL int __stdcall HXPGPIOAnalogSet (int SocketIndex, int NbElements, char * GPIONameList, double AnalogOutputValue[]); /* Set analog output for one or few output */ -DLL int __stdcall HXPGPIOAnalogGainGet (int SocketIndex, int NbElements, char * GPIONameList, int AnalogInputGainValue[]); /* Read analog input gain (1, 2, 4 or 8) for one or few input */ -DLL int __stdcall HXPGPIOAnalogGainSet (int SocketIndex, int NbElements, char * GPIONameList, int AnalogInputGainValue[]); /* Set analog input gain (1, 2, 4 or 8) for one or few input */ -DLL int __stdcall HXPGPIODigitalGet (int SocketIndex, char * GPIOName, unsigned short * DigitalValue); /* Read digital output or digital input */ -DLL int __stdcall HXPGPIODigitalSet (int SocketIndex, char * GPIOName, unsigned short Mask, unsigned short DigitalOutputValue); /* Set Digital Output for one or few output TTL */ -DLL int __stdcall HXPGroupCorrectorOutputGet (int SocketIndex, char * GroupName, int NbElements, double CorrectorOutput[]); /* Return corrector outputs */ -DLL int __stdcall HXPGroupHomeSearch (int SocketIndex, char * GroupName); /* Start home search sequence */ -DLL int __stdcall HXPGroupHomeSearchAndRelativeMove (int SocketIndex, char * GroupName, int NbElements, double TargetDisplacement[]); /* Start home search sequence and execute a displacement */ -DLL int __stdcall HXPGroupInitialize (int SocketIndex, char * GroupName); /* Start the initialization */ -DLL int __stdcall HXPGroupInitializeWithEncoderCalibration (int SocketIndex, char * GroupName); /* Start the initialization with encoder calibration */ -DLL int __stdcall HXPGroupKill (int SocketIndex, char * GroupName); /* Kill the group */ -DLL int __stdcall HXPGroupMoveAbort (int SocketIndex, char * GroupName); /* Abort a move */ -DLL int __stdcall HXPGroupMoveAbsolute (int SocketIndex, char * GroupName, int NbElements, double TargetPosition[]); /* Do an absolute move */ -DLL int __stdcall HXPGroupMoveRelative (int SocketIndex, char * GroupName, int NbElements, double TargetDisplacement[]); /* Do a relative move */ -DLL int __stdcall HXPGroupMotionDisable (int SocketIndex, char * GroupName); /* Set Motion disable on selected group */ -DLL int __stdcall HXPGroupMotionEnable (int SocketIndex, char * GroupName); /* Set Motion enable on selected group */ -DLL int __stdcall HXPGroupPositionCorrectedProfilerGet (int SocketIndex, char * GroupName, double PositionX, double PositionY, double * CorrectedProfilerPositionX, double * CorrectedProfilerPositionY); /* Return corrected profiler positions */ -DLL int __stdcall HXPGroupPositionCurrentGet (int SocketIndex, char * GroupName, int NbElements, double CurrentEncoderPosition[]); /* Return current positions */ -DLL int __stdcall HXPGroupPositionSetpointGet (int SocketIndex, char * GroupName, int NbElements, double SetPointPosition[]); /* Return setpoint positions */ -DLL int __stdcall HXPGroupPositionTargetGet (int SocketIndex, char * GroupName, int NbElements, double TargetPosition[]); /* Return target positions */ -DLL int __stdcall HXPGroupStatusGet (int SocketIndex, char * GroupName, int * Status); /* Return group status */ -DLL int __stdcall HXPGroupStatusStringGet (int SocketIndex, int GroupStatusCode, char * GroupStatusString); /* Return the group status string corresponding to the group status code */ -DLL int __stdcall HXPKillAll (int SocketIndex); /* Put all groups in 'Not initialized' state */ -DLL int __stdcall HXPRestartApplication (int SocketIndex); /* Restart the Controller */ -DLL int __stdcall HXPPositionerBacklashGet (int SocketIndex, char * PositionerName, double * BacklashValue, char * BacklaskStatus); /* Read backlash value and status */ -DLL int __stdcall HXPPositionerBacklashSet (int SocketIndex, char * PositionerName, double BacklashValue); /* Set backlash value */ -DLL int __stdcall HXPPositionerBacklashEnable (int SocketIndex, char * PositionerName); /* Enable the backlash */ -DLL int __stdcall HXPPositionerBacklashDisable (int SocketIndex, char * PositionerName); /* Disable the backlash */ -DLL int __stdcall HXPPositionerCorrectorNotchFiltersSet (int SocketIndex, char * PositionerName, double NotchFrequency1, double NotchBandwith1, double NotchGain1, double NotchFrequency2, double NotchBandwith2, double NotchGain2); /* Update filters parameters */ -DLL int __stdcall HXPPositionerCorrectorNotchFiltersGet (int SocketIndex, char * PositionerName, double * NotchFrequency1, double * NotchBandwith1, double * NotchGain1, double * NotchFrequency2, double * NotchBandwith2, double * NotchGain2); /* Read filters parameters */ -DLL int __stdcall HXPPositionerCorrectorPIDFFAccelerationSet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double KD, double KS, double IntegrationTime, double DerivativeFilterCutOffFrequency, double GKP, double GKI, double GKD, double KForm, double FeedForwardGainAcceleration); /* Update corrector parameters */ -DLL int __stdcall HXPPositionerCorrectorPIDFFAccelerationGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * KD, double * KS, double * IntegrationTime, double * DerivativeFilterCutOffFrequency, double * GKP, double * GKI, double * GKD, double * KForm, double * FeedForwardGainAcceleration); /* Read corrector parameters */ -DLL int __stdcall HXPPositionerCorrectorPIDFFVelocitySet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double KD, double KS, double IntegrationTime, double DerivativeFilterCutOffFrequency, double GKP, double GKI, double GKD, double KForm, double FeedForwardGainVelocity); /* Update corrector parameters */ -DLL int __stdcall HXPPositionerCorrectorPIDFFVelocityGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * KD, double * KS, double * IntegrationTime, double * DerivativeFilterCutOffFrequency, double * GKP, double * GKI, double * GKD, double * KForm, double * FeedForwardGainVelocity); /* Read corrector parameters */ -DLL int __stdcall HXPPositionerCorrectorPIDDualFFVoltageSet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double KD, double KS, double IntegrationTime, double DerivativeFilterCutOffFrequency, double GKP, double GKI, double GKD, double KForm, double FeedForwardGainVelocity, double FeedForwardGainAcceleration, double Friction); /* Update corrector parameters */ -DLL int __stdcall HXPPositionerCorrectorPIDDualFFVoltageGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * KD, double * KS, double * IntegrationTime, double * DerivativeFilterCutOffFrequency, double * GKP, double * GKI, double * GKD, double * KForm, double * FeedForwardGainVelocity, double * FeedForwardGainAcceleration, double * Friction); /* Read corrector parameters */ -DLL int __stdcall HXPPositionerCorrectorPIPositionSet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double IntegrationTime); /* Update corrector parameters */ -DLL int __stdcall HXPPositionerCorrectorPIPositionGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * IntegrationTime); /* Read corrector parameters */ -DLL int __stdcall HXPPositionerCorrectorTypeGet (int SocketIndex, char * PositionerName, char * CorrectorType); /* Read corrector type */ -DLL int __stdcall HXPPositionerCurrentVelocityAccelerationFiltersSet (int SocketIndex, char * PositionerName, double CurrentVelocityCutOffFrequency, double CurrentAccelerationCutOffFrequency); /* Set current velocity and acceleration cut off frequencies */ -DLL int __stdcall HXPPositionerCurrentVelocityAccelerationFiltersGet (int SocketIndex, char * PositionerName, double * CurrentVelocityCutOffFrequency, double * CurrentAccelerationCutOffFrequency); /* Get current velocity and acceleration cut off frequencies */ -DLL int __stdcall HXPPositionerDriverStatusGet (int SocketIndex, char * PositionerName, int * DriverStatus); /* Read positioner driver status */ -DLL int __stdcall HXPPositionerDriverStatusStringGet (int SocketIndex, int PositionerDriverStatus, char * PositionerDriverStatusString); /* Return the positioner driver status string corresponding to the positioner error code */ -DLL int __stdcall HXPPositionerEncoderAmplitudeValuesGet (int SocketIndex, char * PositionerName, double * CalibrationSinusAmplitude, double * CurrentSinusAmplitude, double * CalibrationCosinusAmplitude, double * CurrentCosinusAmplitude); /* Read analog interpolated encoder amplitude values */ -DLL int __stdcall HXPPositionerEncoderCalibrationParametersGet (int SocketIndex, char * PositionerName, double * SinusOffset, double * CosinusOffset, double * DifferentialGain, double * PhaseCompensation); /* Read analog interpolated encoder calibration parameters */ -DLL int __stdcall HXPPositionerErrorGet (int SocketIndex, char * PositionerName, int * ErrorCode); /* Read and clear positioner error code */ -DLL int __stdcall HXPPositionerErrorRead (int SocketIndex, char * PositionerName, int * ErrorCode); /* Read only positioner error code without clear it */ -DLL int __stdcall HXPPositionerErrorStringGet (int SocketIndex, int PositionerErrorCode, char * PositionerErrorString); /* Return the positioner status string corresponding to the positioner error code */ -DLL int __stdcall HXPPositionerHardwareStatusGet (int SocketIndex, char * PositionerName, int * HardwareStatus); /* Read positioner hardware status */ -DLL int __stdcall HXPPositionerHardwareStatusStringGet (int SocketIndex, int PositionerHardwareStatus, char * PositionerHardwareStatusString); /* Return the positioner hardware status string corresponding to the positioner error code */ -DLL int __stdcall HXPPositionerHardInterpolatorFactorGet (int SocketIndex, char * PositionerName, int * InterpolationFactor); /* Get hard interpolator parameters */ -DLL int __stdcall HXPPositionerHardInterpolatorFactorSet (int SocketIndex, char * PositionerName, int InterpolationFactor); /* Set hard interpolator parameters */ -DLL int __stdcall HXPPositionerMaximumVelocityAndAccelerationGet (int SocketIndex, char * PositionerName, double * MaximumVelocity, double * MaximumAcceleration); /* Return maximum velocity and acceleration of the positioner */ -DLL int __stdcall HXPPositionerMotionDoneGet (int SocketIndex, char * PositionerName, double * PositionWindow, double * VelocityWindow, double * CheckingTime, double * MeanPeriod, double * TimeOut); /* Read motion done parameters */ -DLL int __stdcall HXPPositionerMotionDoneSet (int SocketIndex, char * PositionerName, double PositionWindow, double VelocityWindow, double CheckingTime, double MeanPeriod, double TimeOut); /* Update motion done parameters */ -DLL int __stdcall HXPPositionerSGammaExactVelocityAjustedDisplacementGet (int SocketIndex, char * PositionerName, double DesiredDisplacement, double * AdjustedDisplacement); /* Return adjusted displacement to get exact velocity */ -DLL int __stdcall HXPPositionerSGammaParametersGet (int SocketIndex, char * PositionerName, double * Velocity, double * Acceleration, double * MinimumTjerkTime, double * MaximumTjerkTime); /* Read dynamic parameters for one axe of a group for a future displacement */ -DLL int __stdcall HXPPositionerSGammaParametersSet (int SocketIndex, char * PositionerName, double Velocity, double Acceleration, double MinimumTjerkTime, double MaximumTjerkTime); /* Update dynamic parameters for one axe of a group for a future displacement */ -DLL int __stdcall HXPPositionerSGammaPreviousMotionTimesGet (int SocketIndex, char * PositionerName, double * SettingTime, double * SettlingTime); /* Read SettingTime and SettlingTime */ -DLL int __stdcall HXPPositionerStageParameterGet (int SocketIndex, char * PositionerName, char * ParameterName, char * ParameterValue); /* Return the stage parameter */ -DLL int __stdcall HXPPositionerStageParameterSet (int SocketIndex, char * PositionerName, char * ParameterName, char * ParameterValue); /* Save the stage parameter */ -DLL int __stdcall HXPPositionerUserTravelLimitsGet (int SocketIndex, char * PositionerName, double * UserMinimumTarget, double * UserMaximumTarget); /* Read UserMinimumTarget and UserMaximumTarget */ -DLL int __stdcall HXPPositionerUserTravelLimitsSet (int SocketIndex, char * PositionerName, double UserMinimumTarget, double UserMaximumTarget); /* Update UserMinimumTarget and UserMaximumTarget */ -DLL int __stdcall HXPHexapodMoveAbsolute (int SocketIndex, char * GroupName, char * CoordinateSystem, double X, double Y, double Z, double U, double V, double W); /* Hexapod absolute move in a specific coordinate system */ -DLL int __stdcall HXPHexapodMoveIncremental (int SocketIndex, char * GroupName, char * CoordinateSystem, double dX, double dY, double dZ, double dU, double dV, double dW); /* Hexapod incremental move in a specific coordinate system */ -DLL int __stdcall HXPHexapodCoordinatesGet (int SocketIndex, char * GroupName, char * CoordinateSystemIn, char * CoordinateSystemOut, double Xin, double Yin, double Zin, double Uin, double Vin, double Win, double * Xout, double * Yout, double * Zout, double * Uout, double * Vout, double * Wout); /* Get coordinates in a specific coordinate system of a point specified in another coordinate system */ -DLL int __stdcall HXPHexapodCoordinateSystemSet (int SocketIndex, char * GroupName, char * CoordinateSystem, double X, double Y, double Z, double U, double V, double W); /* Modify the position of a coordinate system */ -DLL int __stdcall HXPHexapodCoordinateSystemGet (int SocketIndex, char * GroupName, char * CoordinateSystem, double * X, double * Y, double * Z, double * U, double * V, double * W); /* Get the position of a coordinate system */ -DLL int __stdcall HXPOptionalModuleExecute (int SocketIndex, char * ModuleFileName, char * TaskName); /* Execute an optional module */ -DLL int __stdcall HXPOptionalModuleKill (int SocketIndex, char * TaskName); /* Kill an optional module */ -DLL int __stdcall HXPControllerStatusGet (int SocketIndex, int * ControllerStatus); /* Read controller current status */ -DLL int __stdcall HXPControllerStatusStringGet (int SocketIndex, int ControllerStatusCode, char * ControllerStatusString); /* Return the controller status string corresponding to the controller status code */ -DLL int __stdcall HXPEEPROMCIESet (int SocketIndex, int CardNumber, char * ReferenceString); /* Set CIE EEPROM reference string */ -DLL int __stdcall HXPEEPROMDACOffsetCIESet (int SocketIndex, int PlugNumber, double DAC1Offset, double DAC2Offset); /* Set CIE DAC offsets */ -DLL int __stdcall HXPEEPROMDriverSet (int SocketIndex, int PlugNumber, char * ReferenceString); /* Set Driver EEPROM reference string */ -DLL int __stdcall HXPEEPROMINTSet (int SocketIndex, int CardNumber, char * ReferenceString); /* Set INT EEPROM reference string */ -DLL int __stdcall HXPCPUCoreAndBoardSupplyVoltagesGet (int SocketIndex, double * VoltageCPUCore, double * SupplyVoltage1P5V, double * SupplyVoltage3P3V, double * SupplyVoltage5V, double * SupplyVoltage12V, double * SupplyVoltageM12V, double * SupplyVoltageM5V, double * SupplyVoltage5VSB); /* Get power informations */ -DLL int __stdcall HXPCPUTemperatureAndFanSpeedGet (int SocketIndex, double * CPUTemperature, double * CPUFanSpeed); /* Get CPU temperature and fan speed */ -DLL int __stdcall HXPActionListGet (int SocketIndex, char * ActionList); /* Action list */ -DLL int __stdcall HXPActionExtendedListGet (int SocketIndex, char * ActionList); /* Action extended list */ -DLL int __stdcall HXPAPIExtendedListGet (int SocketIndex, char * Method); /* API method list */ -DLL int __stdcall HXPAPIListGet (int SocketIndex, char * Method); /* API method list without extended API */ -DLL int __stdcall HXPErrorListGet (int SocketIndex, char * ErrorsList); /* Error list */ -DLL int __stdcall HXPEventListGet (int SocketIndex, char * EventList); /* General event list */ -DLL int __stdcall HXPGatheringListGet (int SocketIndex, char * list); /* Gathering type list */ -DLL int __stdcall HXPGatheringExtendedListGet (int SocketIndex, char * list); /* Gathering type extended list */ -DLL int __stdcall HXPGatheringExternalListGet (int SocketIndex, char * list); /* External Gathering type list */ -DLL int __stdcall HXPGroupStatusListGet (int SocketIndex, char * GroupStatusList); /* Group status list */ -DLL int __stdcall HXPHardwareInternalListGet (int SocketIndex, char * InternalHardwareList); /* Internal hardware list */ -DLL int __stdcall HXPHardwareDriverAndStageGet (int SocketIndex, int PlugNumber, char * DriverName, char * StageName); /* Smart hardware */ -DLL int __stdcall HXPObjectsListGet (int SocketIndex, char * ObjectsList); /* Group name and positioner name */ -DLL int __stdcall HXPPositionerErrorListGet (int SocketIndex, char * PositionerErrorList); /* Positioner error list */ -DLL int __stdcall HXPPositionerHardwareStatusListGet (int SocketIndex, char * PositionerHardwareStatusList); /* Positioner hardware status list */ -DLL int __stdcall HXPPositionerDriverStatusListGet (int SocketIndex, char * PositionerDriverStatusList); /* Positioner driver status list */ -DLL int __stdcall HXPReferencingActionListGet (int SocketIndex, char * list); /* Get referencing action list */ -DLL int __stdcall HXPReferencingSensorListGet (int SocketIndex, char * list); /* Get referencing sensor list */ -DLL int __stdcall HXPGatheringUserDatasGet (int SocketIndex, double * UserData1, double * UserData2, double * UserData3, double * UserData4, double * UserData5, double * UserData6, double * UserData7, double * UserData8); /* Return UserDatas values */ -DLL int __stdcall HXPControllerMotionKernelPeriodMinMaxGet (int SocketIndex, double * MinimumCorrectorPeriod, double * MaximumCorrectorPeriod, double * MinimumProfilerPeriod, double * MaximumProfilerPeriod, double * MinimumServitudesPeriod, double * MaximumServitudesPeriod); /* Get controller motion kernel min/max periods */ -DLL int __stdcall HXPControllerMotionKernelPeriodMinMaxReset (int SocketIndex); /* Reset controller motion kernel min/max periods */ -DLL int __stdcall HXPTestTCP (int SocketIndex, char * InputString, char * ReturnString); /* Test TCP/IP transfert */ -DLL int __stdcall HXPPrepareForUpdate (int SocketIndex); /* Kill QNX processes for firmware update */ - - -#ifdef __cplusplus -} -#endif +/************************************************* + * XPS_API.h * + * * + * Description: * + * XPS functions * + *************************************************/ + +#define DLL epicsShareFunc + +#if !defined(_WIN32) && !defined(CYGWIN32) +#define __stdcall +#endif + +#ifdef __rtems__ + #include "strtok_r.h" +#endif + +#ifdef __cplusplus +extern "C" +{ +#else +typedef int bool; /* C does not know bool, only C++ */ +#endif + + + +DLL int __stdcall HXPTCP_ConnectToServer(char *Ip_Address, int Ip_Port, double TimeOut); +DLL void __stdcall HXPTCP_SetTimeout(int SocketIndex, double Timeout); +DLL void __stdcall HXPTCP_CloseSocket(int SocketIndex); +DLL char * __stdcall HXPTCP_GetError(int SocketIndex); +DLL char * __stdcall HXPGetLibraryVersion(void); +DLL int __stdcall HXPControllerMotionKernelTimeLoadGet (int SocketIndex, double * CPUTotalLoadRatio, double * CPUCorrectorLoadRatio, double * CPUProfilerLoadRatio, double * CPUServitudesLoadRatio); /* Get controller motion kernel time load */ +DLL int __stdcall HXPElapsedTimeGet (int SocketIndex, double * ElapsedTime); /* Return elapsed time from controller power on */ +DLL int __stdcall HXPErrorStringGet (int SocketIndex, int ErrorCode, char * ErrorString); /* Return the error string corresponding to the error code */ +DLL int __stdcall HXPFirmwareVersionGet (int SocketIndex, char * Version); /* Return firmware version */ +DLL int __stdcall HXPTCLScriptExecute (int SocketIndex, char * TCLFileName, char * TaskName, char * ParametersList); /* Execute a TCL script from a TCL file */ +DLL int __stdcall HXPTCLScriptExecuteAndWait (int SocketIndex, char * TCLFileName, char * TaskName, char * InputParametersList, char * OutputParametersList); /* Execute a TCL script from a TCL file and wait the end of execution to return */ +DLL int __stdcall HXPTCLScriptKill (int SocketIndex, char * TaskName); /* Kill TCL Task */ +DLL int __stdcall HXPTimerGet (int SocketIndex, char * TimerName, int * FrequencyTicks); /* Get a timer */ +DLL int __stdcall HXPTimerSet (int SocketIndex, char * TimerName, int FrequencyTicks); /* Set a timer */ +DLL int __stdcall HXPReboot (int SocketIndex); /* Reboot the controller */ +DLL int __stdcall HXPLogin (int SocketIndex, char * Name, char * Password); /* Log in */ +DLL int __stdcall HXPCloseAllOtherSockets (int SocketIndex); /* Close all socket beside the one used to send this command */ +DLL int __stdcall HXPEventAdd (int SocketIndex, char * PositionerName, char * EventName, char * EventParameter, char * ActionName, char * ActionParameter1, char * ActionParameter2, char * ActionParameter3); /* ** OBSOLETE ** Add an event */ +DLL int __stdcall HXPEventGet (int SocketIndex, char * PositionerName, char * EventsAndActionsList); /* ** OBSOLETE ** Read events and actions list */ +DLL int __stdcall HXPEventRemove (int SocketIndex, char * PositionerName, char * EventName, char * EventParameter); /* ** OBSOLETE ** Delete an event */ +DLL int __stdcall HXPEventWait (int SocketIndex, char * PositionerName, char * EventName, char * EventParameter); /* ** OBSOLETE ** Wait an event */ +DLL int __stdcall HXPEventExtendedConfigurationTriggerSet (int SocketIndex, int NbElements, char * ExtendedEventNameList, char * EventParameter1List, char * EventParameter2List, char * EventParameter3List, char * EventParameter4List); /* Configure one or several events */ +DLL int __stdcall HXPEventExtendedConfigurationTriggerGet (int SocketIndex, char * EventTriggerConfiguration); /* Read the event configuration */ +DLL int __stdcall HXPEventExtendedConfigurationActionSet (int SocketIndex, int NbElements, char * ExtendedActionNameList, char * ActionParameter1List, char * ActionParameter2List, char * ActionParameter3List, char * ActionParameter4List); /* Configure one or several actions */ +DLL int __stdcall HXPEventExtendedConfigurationActionGet (int SocketIndex, char * ActionConfiguration); /* Read the action configuration */ +DLL int __stdcall HXPEventExtendedStart (int SocketIndex, int * ID); /* Launch the last event and action configuration and return an ID */ +DLL int __stdcall HXPEventExtendedAllGet (int SocketIndex, char * EventActionConfigurations); /* Read all event and action configurations */ +DLL int __stdcall HXPEventExtendedGet (int SocketIndex, int ID, char * EventTriggerConfiguration, char * ActionConfiguration); /* Read the event and action configuration defined by ID */ +DLL int __stdcall HXPEventExtendedRemove (int SocketIndex, int ID); /* Remove the event and action configuration defined by ID */ +DLL int __stdcall HXPEventExtendedWait (int SocketIndex); /* Wait events from the last event configuration */ +DLL int __stdcall HXPGatheringConfigurationGet (int SocketIndex, char * Type); /* Read different mnemonique type */ +DLL int __stdcall HXPGatheringConfigurationSet (int SocketIndex, int NbElements, char * TypeList); /* Configuration acquisition */ +DLL int __stdcall HXPGatheringCurrentNumberGet (int SocketIndex, int * CurrentNumber, int * MaximumSamplesNumber); /* Maximum number of samples and current number during acquisition */ +DLL int __stdcall HXPGatheringStopAndSave (int SocketIndex); /* Stop acquisition and save data */ +DLL int __stdcall HXPGatheringDataAcquire (int SocketIndex); /* Acquire a configured data */ +DLL int __stdcall HXPGatheringDataGet (int SocketIndex, int IndexPoint, char * DataBufferLine); /* Get a data line from gathering buffer */ +DLL int __stdcall HXPGatheringReset (int SocketIndex); /* Empty the gathered data in memory to start new gathering from scratch */ +DLL int __stdcall HXPGatheringRun (int SocketIndex, int DataNumber, int Divisor); /* Start a new gathering */ +DLL int __stdcall HXPGatheringStop (int SocketIndex); /* Stop the data gathering (without saving to file) */ +DLL int __stdcall HXPGatheringExternalConfigurationSet (int SocketIndex, int NbElements, char * TypeList); /* Configuration acquisition */ +DLL int __stdcall HXPGatheringExternalConfigurationGet (int SocketIndex, char * Type); /* Read different mnemonique type */ +DLL int __stdcall HXPGatheringExternalCurrentNumberGet (int SocketIndex, int * CurrentNumber, int * MaximumSamplesNumber); /* Maximum number of samples and current number during acquisition */ +DLL int __stdcall HXPGatheringExternalStopAndSave (int SocketIndex); /* Stop acquisition and save data */ +DLL int __stdcall HXPGlobalArrayGet (int SocketIndex, int Number, char * ValueString); /* Get global array value */ +DLL int __stdcall HXPGlobalArraySet (int SocketIndex, int Number, char * ValueString); /* Set global array value */ +DLL int __stdcall HXPDoubleGlobalArrayGet (int SocketIndex, int Number, double * DoubleValue); /* Get double global array value */ +DLL int __stdcall HXPDoubleGlobalArraySet (int SocketIndex, int Number, double DoubleValue); /* Set double global array value */ +DLL int __stdcall HXPGPIOAnalogGet (int SocketIndex, int NbElements, char * GPIONameList, double AnalogValue[]); /* Read analog input or analog output for one or few input */ +DLL int __stdcall HXPGPIOAnalogSet (int SocketIndex, int NbElements, char * GPIONameList, double AnalogOutputValue[]); /* Set analog output for one or few output */ +DLL int __stdcall HXPGPIOAnalogGainGet (int SocketIndex, int NbElements, char * GPIONameList, int AnalogInputGainValue[]); /* Read analog input gain (1, 2, 4 or 8) for one or few input */ +DLL int __stdcall HXPGPIOAnalogGainSet (int SocketIndex, int NbElements, char * GPIONameList, int AnalogInputGainValue[]); /* Set analog input gain (1, 2, 4 or 8) for one or few input */ +DLL int __stdcall HXPGPIODigitalGet (int SocketIndex, char * GPIOName, unsigned short * DigitalValue); /* Read digital output or digital input */ +DLL int __stdcall HXPGPIODigitalSet (int SocketIndex, char * GPIOName, unsigned short Mask, unsigned short DigitalOutputValue); /* Set Digital Output for one or few output TTL */ +DLL int __stdcall HXPGroupCorrectorOutputGet (int SocketIndex, char * GroupName, int NbElements, double CorrectorOutput[]); /* Return corrector outputs */ +DLL int __stdcall HXPGroupHomeSearch (int SocketIndex, char * GroupName); /* Start home search sequence */ +DLL int __stdcall HXPGroupHomeSearchAndRelativeMove (int SocketIndex, char * GroupName, int NbElements, double TargetDisplacement[]); /* Start home search sequence and execute a displacement */ +DLL int __stdcall HXPGroupInitialize (int SocketIndex, char * GroupName); /* Start the initialization */ +DLL int __stdcall HXPGroupInitializeWithEncoderCalibration (int SocketIndex, char * GroupName); /* Start the initialization with encoder calibration */ +DLL int __stdcall HXPGroupKill (int SocketIndex, char * GroupName); /* Kill the group */ +DLL int __stdcall HXPGroupMoveAbort (int SocketIndex, char * GroupName); /* Abort a move */ +DLL int __stdcall HXPGroupMoveAbsolute (int SocketIndex, char * GroupName, int NbElements, double TargetPosition[]); /* Do an absolute move */ +DLL int __stdcall HXPGroupMoveRelative (int SocketIndex, char * GroupName, int NbElements, double TargetDisplacement[]); /* Do a relative move */ +DLL int __stdcall HXPGroupMotionDisable (int SocketIndex, char * GroupName); /* Set Motion disable on selected group */ +DLL int __stdcall HXPGroupMotionEnable (int SocketIndex, char * GroupName); /* Set Motion enable on selected group */ +DLL int __stdcall HXPGroupPositionCorrectedProfilerGet (int SocketIndex, char * GroupName, double PositionX, double PositionY, double * CorrectedProfilerPositionX, double * CorrectedProfilerPositionY); /* Return corrected profiler positions */ +DLL int __stdcall HXPGroupPositionCurrentGet (int SocketIndex, char * GroupName, int NbElements, double CurrentEncoderPosition[]); /* Return current positions */ +DLL int __stdcall HXPGroupPositionSetpointGet (int SocketIndex, char * GroupName, int NbElements, double SetPointPosition[]); /* Return setpoint positions */ +DLL int __stdcall HXPGroupPositionTargetGet (int SocketIndex, char * GroupName, int NbElements, double TargetPosition[]); /* Return target positions */ +DLL int __stdcall HXPGroupStatusGet (int SocketIndex, char * GroupName, int * Status); /* Return group status */ +DLL int __stdcall HXPGroupStatusStringGet (int SocketIndex, int GroupStatusCode, char * GroupStatusString); /* Return the group status string corresponding to the group status code */ +DLL int __stdcall HXPKillAll (int SocketIndex); /* Put all groups in 'Not initialized' state */ +DLL int __stdcall HXPRestartApplication (int SocketIndex); /* Restart the Controller */ +DLL int __stdcall HXPPositionerBacklashGet (int SocketIndex, char * PositionerName, double * BacklashValue, char * BacklaskStatus); /* Read backlash value and status */ +DLL int __stdcall HXPPositionerBacklashSet (int SocketIndex, char * PositionerName, double BacklashValue); /* Set backlash value */ +DLL int __stdcall HXPPositionerBacklashEnable (int SocketIndex, char * PositionerName); /* Enable the backlash */ +DLL int __stdcall HXPPositionerBacklashDisable (int SocketIndex, char * PositionerName); /* Disable the backlash */ +DLL int __stdcall HXPPositionerCorrectorNotchFiltersSet (int SocketIndex, char * PositionerName, double NotchFrequency1, double NotchBandwith1, double NotchGain1, double NotchFrequency2, double NotchBandwith2, double NotchGain2); /* Update filters parameters */ +DLL int __stdcall HXPPositionerCorrectorNotchFiltersGet (int SocketIndex, char * PositionerName, double * NotchFrequency1, double * NotchBandwith1, double * NotchGain1, double * NotchFrequency2, double * NotchBandwith2, double * NotchGain2); /* Read filters parameters */ +DLL int __stdcall HXPPositionerCorrectorPIDFFAccelerationSet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double KD, double KS, double IntegrationTime, double DerivativeFilterCutOffFrequency, double GKP, double GKI, double GKD, double KForm, double FeedForwardGainAcceleration); /* Update corrector parameters */ +DLL int __stdcall HXPPositionerCorrectorPIDFFAccelerationGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * KD, double * KS, double * IntegrationTime, double * DerivativeFilterCutOffFrequency, double * GKP, double * GKI, double * GKD, double * KForm, double * FeedForwardGainAcceleration); /* Read corrector parameters */ +DLL int __stdcall HXPPositionerCorrectorPIDFFVelocitySet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double KD, double KS, double IntegrationTime, double DerivativeFilterCutOffFrequency, double GKP, double GKI, double GKD, double KForm, double FeedForwardGainVelocity); /* Update corrector parameters */ +DLL int __stdcall HXPPositionerCorrectorPIDFFVelocityGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * KD, double * KS, double * IntegrationTime, double * DerivativeFilterCutOffFrequency, double * GKP, double * GKI, double * GKD, double * KForm, double * FeedForwardGainVelocity); /* Read corrector parameters */ +DLL int __stdcall HXPPositionerCorrectorPIDDualFFVoltageSet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double KD, double KS, double IntegrationTime, double DerivativeFilterCutOffFrequency, double GKP, double GKI, double GKD, double KForm, double FeedForwardGainVelocity, double FeedForwardGainAcceleration, double Friction); /* Update corrector parameters */ +DLL int __stdcall HXPPositionerCorrectorPIDDualFFVoltageGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * KD, double * KS, double * IntegrationTime, double * DerivativeFilterCutOffFrequency, double * GKP, double * GKI, double * GKD, double * KForm, double * FeedForwardGainVelocity, double * FeedForwardGainAcceleration, double * Friction); /* Read corrector parameters */ +DLL int __stdcall HXPPositionerCorrectorPIPositionSet (int SocketIndex, char * PositionerName, bool ClosedLoopStatus, double KP, double KI, double IntegrationTime); /* Update corrector parameters */ +DLL int __stdcall HXPPositionerCorrectorPIPositionGet (int SocketIndex, char * PositionerName, bool * ClosedLoopStatus, double * KP, double * KI, double * IntegrationTime); /* Read corrector parameters */ +DLL int __stdcall HXPPositionerCorrectorTypeGet (int SocketIndex, char * PositionerName, char * CorrectorType); /* Read corrector type */ +DLL int __stdcall HXPPositionerCurrentVelocityAccelerationFiltersSet (int SocketIndex, char * PositionerName, double CurrentVelocityCutOffFrequency, double CurrentAccelerationCutOffFrequency); /* Set current velocity and acceleration cut off frequencies */ +DLL int __stdcall HXPPositionerCurrentVelocityAccelerationFiltersGet (int SocketIndex, char * PositionerName, double * CurrentVelocityCutOffFrequency, double * CurrentAccelerationCutOffFrequency); /* Get current velocity and acceleration cut off frequencies */ +DLL int __stdcall HXPPositionerDriverStatusGet (int SocketIndex, char * PositionerName, int * DriverStatus); /* Read positioner driver status */ +DLL int __stdcall HXPPositionerDriverStatusStringGet (int SocketIndex, int PositionerDriverStatus, char * PositionerDriverStatusString); /* Return the positioner driver status string corresponding to the positioner error code */ +DLL int __stdcall HXPPositionerEncoderAmplitudeValuesGet (int SocketIndex, char * PositionerName, double * CalibrationSinusAmplitude, double * CurrentSinusAmplitude, double * CalibrationCosinusAmplitude, double * CurrentCosinusAmplitude); /* Read analog interpolated encoder amplitude values */ +DLL int __stdcall HXPPositionerEncoderCalibrationParametersGet (int SocketIndex, char * PositionerName, double * SinusOffset, double * CosinusOffset, double * DifferentialGain, double * PhaseCompensation); /* Read analog interpolated encoder calibration parameters */ +DLL int __stdcall HXPPositionerErrorGet (int SocketIndex, char * PositionerName, int * ErrorCode); /* Read and clear positioner error code */ +DLL int __stdcall HXPPositionerErrorRead (int SocketIndex, char * PositionerName, int * ErrorCode); /* Read only positioner error code without clear it */ +DLL int __stdcall HXPPositionerErrorStringGet (int SocketIndex, int PositionerErrorCode, char * PositionerErrorString); /* Return the positioner status string corresponding to the positioner error code */ +DLL int __stdcall HXPPositionerHardwareStatusGet (int SocketIndex, char * PositionerName, int * HardwareStatus); /* Read positioner hardware status */ +DLL int __stdcall HXPPositionerHardwareStatusStringGet (int SocketIndex, int PositionerHardwareStatus, char * PositionerHardwareStatusString); /* Return the positioner hardware status string corresponding to the positioner error code */ +DLL int __stdcall HXPPositionerHardInterpolatorFactorGet (int SocketIndex, char * PositionerName, int * InterpolationFactor); /* Get hard interpolator parameters */ +DLL int __stdcall HXPPositionerHardInterpolatorFactorSet (int SocketIndex, char * PositionerName, int InterpolationFactor); /* Set hard interpolator parameters */ +DLL int __stdcall HXPPositionerMaximumVelocityAndAccelerationGet (int SocketIndex, char * PositionerName, double * MaximumVelocity, double * MaximumAcceleration); /* Return maximum velocity and acceleration of the positioner */ +DLL int __stdcall HXPPositionerMotionDoneGet (int SocketIndex, char * PositionerName, double * PositionWindow, double * VelocityWindow, double * CheckingTime, double * MeanPeriod, double * TimeOut); /* Read motion done parameters */ +DLL int __stdcall HXPPositionerMotionDoneSet (int SocketIndex, char * PositionerName, double PositionWindow, double VelocityWindow, double CheckingTime, double MeanPeriod, double TimeOut); /* Update motion done parameters */ +DLL int __stdcall HXPPositionerSGammaExactVelocityAjustedDisplacementGet (int SocketIndex, char * PositionerName, double DesiredDisplacement, double * AdjustedDisplacement); /* Return adjusted displacement to get exact velocity */ +DLL int __stdcall HXPPositionerSGammaParametersGet (int SocketIndex, char * PositionerName, double * Velocity, double * Acceleration, double * MinimumTjerkTime, double * MaximumTjerkTime); /* Read dynamic parameters for one axe of a group for a future displacement */ +DLL int __stdcall HXPPositionerSGammaParametersSet (int SocketIndex, char * PositionerName, double Velocity, double Acceleration, double MinimumTjerkTime, double MaximumTjerkTime); /* Update dynamic parameters for one axe of a group for a future displacement */ +DLL int __stdcall HXPPositionerSGammaPreviousMotionTimesGet (int SocketIndex, char * PositionerName, double * SettingTime, double * SettlingTime); /* Read SettingTime and SettlingTime */ +DLL int __stdcall HXPPositionerStageParameterGet (int SocketIndex, char * PositionerName, char * ParameterName, char * ParameterValue); /* Return the stage parameter */ +DLL int __stdcall HXPPositionerStageParameterSet (int SocketIndex, char * PositionerName, char * ParameterName, char * ParameterValue); /* Save the stage parameter */ +DLL int __stdcall HXPPositionerUserTravelLimitsGet (int SocketIndex, char * PositionerName, double * UserMinimumTarget, double * UserMaximumTarget); /* Read UserMinimumTarget and UserMaximumTarget */ +DLL int __stdcall HXPPositionerUserTravelLimitsSet (int SocketIndex, char * PositionerName, double UserMinimumTarget, double UserMaximumTarget); /* Update UserMinimumTarget and UserMaximumTarget */ +DLL int __stdcall HXPHexapodMoveAbsolute (int SocketIndex, char * GroupName, char * CoordinateSystem, double X, double Y, double Z, double U, double V, double W); /* Hexapod absolute move in a specific coordinate system */ +DLL int __stdcall HXPHexapodMoveIncremental (int SocketIndex, char * GroupName, char * CoordinateSystem, double dX, double dY, double dZ, double dU, double dV, double dW); /* Hexapod incremental move in a specific coordinate system */ +DLL int __stdcall HXPHexapodCoordinatesGet (int SocketIndex, char * GroupName, char * CoordinateSystemIn, char * CoordinateSystemOut, double Xin, double Yin, double Zin, double Uin, double Vin, double Win, double * Xout, double * Yout, double * Zout, double * Uout, double * Vout, double * Wout); /* Get coordinates in a specific coordinate system of a point specified in another coordinate system */ +DLL int __stdcall HXPHexapodCoordinateSystemSet (int SocketIndex, char * GroupName, char * CoordinateSystem, double X, double Y, double Z, double U, double V, double W); /* Modify the position of a coordinate system */ +DLL int __stdcall HXPHexapodCoordinateSystemGet (int SocketIndex, char * GroupName, char * CoordinateSystem, double * X, double * Y, double * Z, double * U, double * V, double * W); /* Get the position of a coordinate system */ +DLL int __stdcall HXPOptionalModuleExecute (int SocketIndex, char * ModuleFileName, char * TaskName); /* Execute an optional module */ +DLL int __stdcall HXPOptionalModuleKill (int SocketIndex, char * TaskName); /* Kill an optional module */ +DLL int __stdcall HXPControllerStatusGet (int SocketIndex, int * ControllerStatus); /* Read controller current status */ +DLL int __stdcall HXPControllerStatusStringGet (int SocketIndex, int ControllerStatusCode, char * ControllerStatusString); /* Return the controller status string corresponding to the controller status code */ +DLL int __stdcall HXPEEPROMCIESet (int SocketIndex, int CardNumber, char * ReferenceString); /* Set CIE EEPROM reference string */ +DLL int __stdcall HXPEEPROMDACOffsetCIESet (int SocketIndex, int PlugNumber, double DAC1Offset, double DAC2Offset); /* Set CIE DAC offsets */ +DLL int __stdcall HXPEEPROMDriverSet (int SocketIndex, int PlugNumber, char * ReferenceString); /* Set Driver EEPROM reference string */ +DLL int __stdcall HXPEEPROMINTSet (int SocketIndex, int CardNumber, char * ReferenceString); /* Set INT EEPROM reference string */ +DLL int __stdcall HXPCPUCoreAndBoardSupplyVoltagesGet (int SocketIndex, double * VoltageCPUCore, double * SupplyVoltage1P5V, double * SupplyVoltage3P3V, double * SupplyVoltage5V, double * SupplyVoltage12V, double * SupplyVoltageM12V, double * SupplyVoltageM5V, double * SupplyVoltage5VSB); /* Get power informations */ +DLL int __stdcall HXPCPUTemperatureAndFanSpeedGet (int SocketIndex, double * CPUTemperature, double * CPUFanSpeed); /* Get CPU temperature and fan speed */ +DLL int __stdcall HXPActionListGet (int SocketIndex, char * ActionList); /* Action list */ +DLL int __stdcall HXPActionExtendedListGet (int SocketIndex, char * ActionList); /* Action extended list */ +DLL int __stdcall HXPAPIExtendedListGet (int SocketIndex, char * Method); /* API method list */ +DLL int __stdcall HXPAPIListGet (int SocketIndex, char * Method); /* API method list without extended API */ +DLL int __stdcall HXPErrorListGet (int SocketIndex, char * ErrorsList); /* Error list */ +DLL int __stdcall HXPEventListGet (int SocketIndex, char * EventList); /* General event list */ +DLL int __stdcall HXPGatheringListGet (int SocketIndex, char * list); /* Gathering type list */ +DLL int __stdcall HXPGatheringExtendedListGet (int SocketIndex, char * list); /* Gathering type extended list */ +DLL int __stdcall HXPGatheringExternalListGet (int SocketIndex, char * list); /* External Gathering type list */ +DLL int __stdcall HXPGroupStatusListGet (int SocketIndex, char * GroupStatusList); /* Group status list */ +DLL int __stdcall HXPHardwareInternalListGet (int SocketIndex, char * InternalHardwareList); /* Internal hardware list */ +DLL int __stdcall HXPHardwareDriverAndStageGet (int SocketIndex, int PlugNumber, char * DriverName, char * StageName); /* Smart hardware */ +DLL int __stdcall HXPObjectsListGet (int SocketIndex, char * ObjectsList); /* Group name and positioner name */ +DLL int __stdcall HXPPositionerErrorListGet (int SocketIndex, char * PositionerErrorList); /* Positioner error list */ +DLL int __stdcall HXPPositionerHardwareStatusListGet (int SocketIndex, char * PositionerHardwareStatusList); /* Positioner hardware status list */ +DLL int __stdcall HXPPositionerDriverStatusListGet (int SocketIndex, char * PositionerDriverStatusList); /* Positioner driver status list */ +DLL int __stdcall HXPReferencingActionListGet (int SocketIndex, char * list); /* Get referencing action list */ +DLL int __stdcall HXPReferencingSensorListGet (int SocketIndex, char * list); /* Get referencing sensor list */ +DLL int __stdcall HXPGatheringUserDatasGet (int SocketIndex, double * UserData1, double * UserData2, double * UserData3, double * UserData4, double * UserData5, double * UserData6, double * UserData7, double * UserData8); /* Return UserDatas values */ +DLL int __stdcall HXPControllerMotionKernelPeriodMinMaxGet (int SocketIndex, double * MinimumCorrectorPeriod, double * MaximumCorrectorPeriod, double * MinimumProfilerPeriod, double * MaximumProfilerPeriod, double * MinimumServitudesPeriod, double * MaximumServitudesPeriod); /* Get controller motion kernel min/max periods */ +DLL int __stdcall HXPControllerMotionKernelPeriodMinMaxReset (int SocketIndex); /* Reset controller motion kernel min/max periods */ +DLL int __stdcall HXPTestTCP (int SocketIndex, char * InputString, char * ReturnString); /* Test TCP/IP transfert */ +DLL int __stdcall HXPPrepareForUpdate (int SocketIndex); /* Kill QNX processes for firmware update */ + + +#ifdef __cplusplus +} +#endif diff --git a/motorApp/NewportSrc/hxp_errors.h b/motorApp/NewportSrc/hxp_errors.h index 5219552..3bc40dc 100644 --- a/motorApp/NewportSrc/hxp_errors.h +++ b/motorApp/NewportSrc/hxp_errors.h @@ -1,98 +1,98 @@ -//////////////////////////////////////////////////////////////////// -// Created header file hxp_errors.h for XPS function errors -// - -// TCL interpretor error -#define ERR_TCL_INTERPRETOR_ERROR 1 - -// No error -#define SUCCESS 0 - -// XPS errors -#define ERR_TCL_INTERPRETOR_ERROR 1 -#define ERR_BUSY_SOCKET -1 -#define ERR_TCP_TIMEOUT -2 -#define ERR_STRING_TOO_LONG -3 -#define ERR_UNKNOWN_COMMAND -4 -#define ERR_POSITIONER_ERROR -5 -#define ERR_WRONG_FORMAT -7 -#define ERR_WRONG_OBJECT_TYPE -8 -#define ERR_WRONG_PARAMETERS_NUMBER -9 -#define ERR_WRONG_TYPE -10 -#define ERR_WRONG_TYPE_BIT_WORD -11 -#define ERR_WRONG_TYPE_BOOL -12 -#define ERR_WRONG_TYPE_CHAR -13 -#define ERR_WRONG_TYPE_DOUBLE -14 -#define ERR_WRONG_TYPE_INT -15 -#define ERR_WRONG_TYPE_UNSIGNEDINT -16 -#define ERR_PARAMETER_OUT_OF_RANGE -17 -#define ERR_POSITIONER_NAME -18 -#define ERR_GROUP_NAME -19 -#define ERR_FATAL_INIT -20 -#define ERR_IN_INITIALIZATION -21 -#define ERR_NOT_ALLOWED_ACTION -22 -#define ERR_POSITION_COMPARE_NOT_SET -23 -#define ERR_UNCOMPATIBLE -24 -#define ERR_FOLLOWING_ERROR -25 -#define ERR_EMERGENCY_SIGNAL -26 -#define ERR_GROUP_ABORT_MOTION -27 -#define ERR_GROUP_HOME_SEARCH_TIMEOUT -28 -#define ERR_MNEMOTYPEGATHERING -29 -#define ERR_GATHERING_NOT_STARTED -30 -#define ERR_HOME_OUT_RANGE -31 -#define ERR_GATHERING_NOT_CONFIGURED -32 -#define ERR_GROUP_MOTION_DONE_TIMEOUT -33 -#define ERR_TRAVEL_LIMITS -35 -#define ERR_UNKNOWN_TCL_FILE -36 -#define ERR_TCL_SCRIPT_KILL -38 -#define ERR_TCL_INTERPRETOR -37 -#define ERR_MNEMO_ACTION -39 -#define ERR_MNEMO_EVENT -40 -#define ERR_SLAVE_CONFIGURATION -41 -#define ERR_JOG_OUT_OF_RANGE -42 -#define ERR_GATHERING_RUNNING -43 -#define ERR_SLAVE -44 -#define ERR_END_OF_RUN -45 -#define ERR_NOT_ALLOWED_BACKLASH -46 -#define ERR_WRONG_TCL_TASKNAME -47 -#define ERR_BASE_VELOCITY -48 -#define ERR_GROUP_HOME_SEARCH_ZM_ERROR -49 -#define ERR_MOTOR_INITIALIZATION_ERROR -50 -#define ERR_WRITE_FILE -60 -#define ERR_READ_FILE -61 -#define ERR_TRAJ_ELEM_TYPE -62 -#define ERR_TRAJ_ELEM_LINE -65 -#define ERR_TRAJ_EMPTY -66 -#define ERR_TRAJ_VEL_LIMIT -68 -#define ERR_TRAJ_ACC_LIMIT -69 -#define ERR_TRAJ_FINAL_VELOCITY -70 -#define ERR_MSG_QUEUE -71 -#define ERR_TRAJ_INITIALIZATION -72 -#define ERR_END_OF_FILE -73 -#define ERR_READ_FILE_PARAMETER_KEY -74 -#define ERR_TRAJ_TIME -75 -#define ERR_EVENTS_NOT_CONFIGURED -80 -#define ERR_ACTIONS_NOT_CONFIGURED -81 -#define ERR_EVENT_BUFFER_FULL -82 -#define ERR_EVENT_ID_UNDEFINED -83 -#define ERR_HOME_SEARCH_GANTRY_TOLERANCE_ERROR -85 -#define ERR_OPTIONAL_EXTERNAL_MODULE_FILE -94 -#define ERR_OPTIONAL_EXTERNAL_MODULE_EXECUTE -95 -#define ERR_OPTIONAL_EXTERNAL_MODULE_KILL -96 -#define ERR_OPTIONAL_EXTERNAL_MODULE_LOAD -97 -#define ERR_OPTIONAL_EXTERNAL_MODULE_UNLOAD -98 -#define ERR_FATAL_EXTERNAL_MODULE_LOAD -99 -#define ERR_INTERNAL_ERROR -100 -#define ERR_RELAY_FEEDBACK_TEST_NO_OSCILLATION -101 -#define ERR_RELAY_FEEDBACK_TEST_SIGNAL_NOISY -102 -#define ERR_SIGNAL_POINTS_NOT_ENOUGH -103 -#define ERR_PID_TUNING_INITIALIZATION -104 -#define ERR_SCALING_CALIBRATION -105 -#define ERR_WRONG_USERNAME_OR_PASSWORD -106 -#define ERR_NEED_ADMINISTRATOR_RIGHTS -107 -#define ERR_SOCKET_CLOSED_BY_ADMIN -108 -#define ERR_NEED_TO_BE_HOMED_AT_LEAST_ONCE -109 -#define ERR_NOT_ALLOWED_FOR_GANTRY -110 -#define ERR_GATHERING_BUFFER_FULL -111 -#define ERR_BOTH_ENDS_OF_RUNS_ACTIVATED -113 -#define ERR_HARDWARE_FUNCTION_NOT_SUPPORTED -115 +//////////////////////////////////////////////////////////////////// +// Created header file hxp_errors.h for XPS function errors +// + +// TCL interpretor error +#define ERR_TCL_INTERPRETOR_ERROR 1 + +// No error +#define SUCCESS 0 + +// XPS errors +#define ERR_TCL_INTERPRETOR_ERROR 1 +#define ERR_BUSY_SOCKET -1 +#define ERR_TCP_TIMEOUT -2 +#define ERR_STRING_TOO_LONG -3 +#define ERR_UNKNOWN_COMMAND -4 +#define ERR_POSITIONER_ERROR -5 +#define ERR_WRONG_FORMAT -7 +#define ERR_WRONG_OBJECT_TYPE -8 +#define ERR_WRONG_PARAMETERS_NUMBER -9 +#define ERR_WRONG_TYPE -10 +#define ERR_WRONG_TYPE_BIT_WORD -11 +#define ERR_WRONG_TYPE_BOOL -12 +#define ERR_WRONG_TYPE_CHAR -13 +#define ERR_WRONG_TYPE_DOUBLE -14 +#define ERR_WRONG_TYPE_INT -15 +#define ERR_WRONG_TYPE_UNSIGNEDINT -16 +#define ERR_PARAMETER_OUT_OF_RANGE -17 +#define ERR_POSITIONER_NAME -18 +#define ERR_GROUP_NAME -19 +#define ERR_FATAL_INIT -20 +#define ERR_IN_INITIALIZATION -21 +#define ERR_NOT_ALLOWED_ACTION -22 +#define ERR_POSITION_COMPARE_NOT_SET -23 +#define ERR_UNCOMPATIBLE -24 +#define ERR_FOLLOWING_ERROR -25 +#define ERR_EMERGENCY_SIGNAL -26 +#define ERR_GROUP_ABORT_MOTION -27 +#define ERR_GROUP_HOME_SEARCH_TIMEOUT -28 +#define ERR_MNEMOTYPEGATHERING -29 +#define ERR_GATHERING_NOT_STARTED -30 +#define ERR_HOME_OUT_RANGE -31 +#define ERR_GATHERING_NOT_CONFIGURED -32 +#define ERR_GROUP_MOTION_DONE_TIMEOUT -33 +#define ERR_TRAVEL_LIMITS -35 +#define ERR_UNKNOWN_TCL_FILE -36 +#define ERR_TCL_SCRIPT_KILL -38 +#define ERR_TCL_INTERPRETOR -37 +#define ERR_MNEMO_ACTION -39 +#define ERR_MNEMO_EVENT -40 +#define ERR_SLAVE_CONFIGURATION -41 +#define ERR_JOG_OUT_OF_RANGE -42 +#define ERR_GATHERING_RUNNING -43 +#define ERR_SLAVE -44 +#define ERR_END_OF_RUN -45 +#define ERR_NOT_ALLOWED_BACKLASH -46 +#define ERR_WRONG_TCL_TASKNAME -47 +#define ERR_BASE_VELOCITY -48 +#define ERR_GROUP_HOME_SEARCH_ZM_ERROR -49 +#define ERR_MOTOR_INITIALIZATION_ERROR -50 +#define ERR_WRITE_FILE -60 +#define ERR_READ_FILE -61 +#define ERR_TRAJ_ELEM_TYPE -62 +#define ERR_TRAJ_ELEM_LINE -65 +#define ERR_TRAJ_EMPTY -66 +#define ERR_TRAJ_VEL_LIMIT -68 +#define ERR_TRAJ_ACC_LIMIT -69 +#define ERR_TRAJ_FINAL_VELOCITY -70 +#define ERR_MSG_QUEUE -71 +#define ERR_TRAJ_INITIALIZATION -72 +#define ERR_END_OF_FILE -73 +#define ERR_READ_FILE_PARAMETER_KEY -74 +#define ERR_TRAJ_TIME -75 +#define ERR_EVENTS_NOT_CONFIGURED -80 +#define ERR_ACTIONS_NOT_CONFIGURED -81 +#define ERR_EVENT_BUFFER_FULL -82 +#define ERR_EVENT_ID_UNDEFINED -83 +#define ERR_HOME_SEARCH_GANTRY_TOLERANCE_ERROR -85 +#define ERR_OPTIONAL_EXTERNAL_MODULE_FILE -94 +#define ERR_OPTIONAL_EXTERNAL_MODULE_EXECUTE -95 +#define ERR_OPTIONAL_EXTERNAL_MODULE_KILL -96 +#define ERR_OPTIONAL_EXTERNAL_MODULE_LOAD -97 +#define ERR_OPTIONAL_EXTERNAL_MODULE_UNLOAD -98 +#define ERR_FATAL_EXTERNAL_MODULE_LOAD -99 +#define ERR_INTERNAL_ERROR -100 +#define ERR_RELAY_FEEDBACK_TEST_NO_OSCILLATION -101 +#define ERR_RELAY_FEEDBACK_TEST_SIGNAL_NOISY -102 +#define ERR_SIGNAL_POINTS_NOT_ENOUGH -103 +#define ERR_PID_TUNING_INITIALIZATION -104 +#define ERR_SCALING_CALIBRATION -105 +#define ERR_WRONG_USERNAME_OR_PASSWORD -106 +#define ERR_NEED_ADMINISTRATOR_RIGHTS -107 +#define ERR_SOCKET_CLOSED_BY_ADMIN -108 +#define ERR_NEED_TO_BE_HOMED_AT_LEAST_ONCE -109 +#define ERR_NOT_ALLOWED_FOR_GANTRY -110 +#define ERR_GATHERING_BUFFER_FULL -111 +#define ERR_BOTH_ENDS_OF_RUNS_ACTIVATED -113 +#define ERR_HARDWARE_FUNCTION_NOT_SUPPORTED -115 diff --git a/motorApp/NewportSrc/tclCall.cc b/motorApp/NewportSrc/tclCall.cc index 22f5ba7..57a3ac5 100644 --- a/motorApp/NewportSrc/tclCall.cc +++ b/motorApp/NewportSrc/tclCall.cc @@ -10,11 +10,11 @@ #include -#include "XPS_C8_drivers.h" -#include "Socket.h" #define epicsExportSharedSymbols #include #include "tclCall.h" +#include "XPS_C8_drivers.h" +#include "Socket.h" #define TIMEOUT 1 diff --git a/motorApp/NewportSrc/xpsSlave.st b/motorApp/NewportSrc/xpsSlave.st index 9524e6e..690e015 100644 --- a/motorApp/NewportSrc/xpsSlave.st +++ b/motorApp/NewportSrc/xpsSlave.st @@ -8,6 +8,8 @@ option +r; /*option -w;*/ #include "seqPVmacros.h" +%%#define epicsExportSharedSymbols +%%#include %%#include "XPS_C8_drivers.h" #define PORT 5001 diff --git a/motorApp/OmsAsynSrc/omsBaseAxis.cpp b/motorApp/OmsAsynSrc/omsBaseAxis.cpp index cc6d137..119656d 100644 --- a/motorApp/OmsAsynSrc/omsBaseAxis.cpp +++ b/motorApp/OmsAsynSrc/omsBaseAxis.cpp @@ -2,10 +2,6 @@ FILENAME... omsBaseAxis.cpp USAGE... Pro-Dex OMS asyn motor base axes support -Version: $Revision$ -Modified By: $Author$ -Last Modified: $Date$ -HeadURL: $URL$ */ @@ -32,6 +28,7 @@ omsBaseAxis::omsBaseAxis(omsBaseController *pController, int axis, char axisChar stepper = 1; invertLimit = 0; lastminvelo = 0; + encoderRatio = 1.0; } asynStatus omsBaseAxis::move(double position, int relative, double min_velocity, double max_velocity, double acceleration) @@ -40,9 +37,36 @@ asynStatus omsBaseAxis::move(double position, int relative, double min_velocity, static const char *functionName = "moveAxis"; asynStatus status = asynError; + + char buff[100]; + char encoderPositionResponse[64]; + + int hasEncoder = 0; + if (pC_->getIntegerParam(axisNo_, pC_->motorStatusHasEncoder_, &hasEncoder) == asynError) + { + return asynError; + } + + if (hasEncoder != 0) + { + sprintf(buff, "A%1c;RE;", axisChar); + status = pC_->sendReceiveLock(buff, encoderPositionResponse, 64); + if (status == asynError) + { + return status; + } + + int motorPosition = static_cast(atoi(encoderPositionResponse) / encoderRatio); + asynPrint(pasynUser_, ASYN_TRACE_FLOW, + "%s:%s: Set driver %s motor position %d from encoder position %s\n", + driverName, functionName, pC_->portName, motorPosition, encoderPositionResponse); + + sprintf(buff, "A%1c;LO%d;", axisChar, motorPosition); + status = pC_->sendOnlyLock(buff); + } + epicsInt32 minvelo, velo, acc, rela, pos; char *relabs[2] = {(char *) "MA", (char *) "MR"}; - char buff[100]; if (relative) rela = 1; @@ -85,7 +109,7 @@ asynStatus omsBaseAxis::move(double position, int relative, double min_velocity, status = pC_->sendOnlyLock(buff); asynPrint(pasynUser_, ASYN_TRACE_FLOW, - "%s:%s: Set driver %s, axis %d move to %f, min vel=%f, max_vel=%f, accel=%f", + "%s:%s: Set driver %s, axis %d move to %f, min vel=%f, max_vel=%f, accel=%f\n", driverName, functionName, pC_->portName, axisNo_, position, min_velocity, max_velocity, acceleration ); return status; @@ -128,7 +152,7 @@ asynStatus omsBaseAxis::home(double min_velocity, double max_velocity, double ac homing = 1; asynPrint(pasynUser_, ASYN_TRACE_FLOW, - "%s:%s: Set driver %s, axis %d to home %s, min vel=%f, max_vel=%f, accel=%f", + "%s:%s: Set driver %s, axis %d to home %s, min vel=%f, max_vel=%f, accel=%f\n", driverName, functionName, pC_->portName, axisNo_, (forwards?"FORWARDS":"REVERSE"), min_velocity, max_velocity, acceleration ); return status; diff --git a/motorApp/OmsAsynSrc/omsBaseAxis.h b/motorApp/OmsAsynSrc/omsBaseAxis.h index 0f5dc6d..7a1658e 100644 --- a/motorApp/OmsAsynSrc/omsBaseAxis.h +++ b/motorApp/OmsAsynSrc/omsBaseAxis.h @@ -2,10 +2,6 @@ FILENAME... omsBaseAxis.h USAGE... Pro-Dex OMS asyn motor base axes support -Version: $Revision$ -Modified By: $Author$ -Last Modified: $Date$ -HeadURL: $URL$ */ /* @@ -33,11 +29,12 @@ class omsBaseAxis : public asynMotorAxis virtual asynStatus setPosition(double position); virtual asynStatus poll(bool *moving); - int getAxis(){return axisNo_;}; - int isStepper(){return stepper;}; - void setStepper(int val){stepper=val;}; - int getLimitInvert(){return invertLimit;}; - void setLimitInvert(int val){invertLimit=val;}; + int getAxis(){return axisNo_;} + int isStepper(){return stepper;} + void setStepper(int val){stepper=val;} + int getLimitInvert(){return invertLimit;} + void setLimitInvert(int val){invertLimit=val;} + virtual asynStatus setEncoderRatio(double ratio){encoderRatio=ratio; return asynSuccess;} int card; int moveDelay; char axisChar; @@ -49,6 +46,7 @@ class omsBaseAxis : public asynMotorAxis int stepper; int invertLimit; epicsInt32 lastminvelo; + double encoderRatio; friend class omsBaseController; }; diff --git a/motorApp/OmsAsynSrc/omsBaseController.cpp b/motorApp/OmsAsynSrc/omsBaseController.cpp index dfa096d..d0c26f2 100644 --- a/motorApp/OmsAsynSrc/omsBaseController.cpp +++ b/motorApp/OmsAsynSrc/omsBaseController.cpp @@ -2,10 +2,6 @@ FILENAME... omsBaseController.cpp USAGE... Pro-Dex OMS asyn motor base controller support -Version: $Revision$ -Modified By: $Author$ -Last Modified: $Date$ -HeadURL: $URL$ */ /* diff --git a/motorApp/OmsAsynSrc/omsBaseController.h b/motorApp/OmsAsynSrc/omsBaseController.h index d3290c0..8b35b6f 100644 --- a/motorApp/OmsAsynSrc/omsBaseController.h +++ b/motorApp/OmsAsynSrc/omsBaseController.h @@ -2,10 +2,6 @@ FILENAME... omsBaseController.h USAGE... Pro-Dex OMS asyn motor base controller support -Version: $Revision$ -Modified By: $Author$ -Last Modified: $Date$ -HeadURL: $URL$ */ /* diff --git a/motorApp/OmsAsynSrc/omsMAXnet.cpp b/motorApp/OmsAsynSrc/omsMAXnet.cpp index aeed780..e5eec78 100644 --- a/motorApp/OmsAsynSrc/omsMAXnet.cpp +++ b/motorApp/OmsAsynSrc/omsMAXnet.cpp @@ -2,10 +2,6 @@ FILENAME... omsMAXnet.cpp USAGE... Pro-Dex OMS MAXnet asyn motor controller support -Version: $Revision$ -Modified By: $Author$ -Last Modified: $Date$ -HeadURL: $URL$ */ /* @@ -367,6 +363,9 @@ extern "C" int omsMAXnetConfig( /* Code for iocsh registration */ +extern "C" +{ + /* omsMAXnetConfig */ static const iocshArg omsMAXnetConfigArg0 = {"asyn motor port name", iocshArgString}; static const iocshArg omsMAXnetConfigArg1 = {"number of axes", iocshArgInt}; @@ -393,3 +392,4 @@ static void OmsMAXnetAsynRegister(void) epicsExportRegistrar(OmsMAXnetAsynRegister); +} diff --git a/motorApp/OmsAsynSrc/omsMAXnet.h b/motorApp/OmsAsynSrc/omsMAXnet.h index 4701b61..12726b4 100644 --- a/motorApp/OmsAsynSrc/omsMAXnet.h +++ b/motorApp/OmsAsynSrc/omsMAXnet.h @@ -2,10 +2,6 @@ FILENAME... omsMAXnet.h USAGE... Pro-Dex OMS MAXnet asyn motor controller support -Version: $Revision$ -Modified By: $Author$ -Last Modified: $Date$ -HeadURL: $URL$ */ /* diff --git a/motorApp/OmsAsynSrc/omsMAXv.cpp b/motorApp/OmsAsynSrc/omsMAXv.cpp index 3b89423..44688af 100644 --- a/motorApp/OmsAsynSrc/omsMAXv.cpp +++ b/motorApp/OmsAsynSrc/omsMAXv.cpp @@ -2,10 +2,6 @@ FILENAME... omsMAXv.cpp USAGE... Pro-Dex OMS MAXv asyn motor controller support -Version: $Revision$ -Modified By: $Author$ -Last Modified: $Date$ -HeadURL: $URL$ */ /* @@ -593,6 +589,10 @@ extern "C" int omsMAXvConfig2( } /* Code for iocsh registration */ + +extern "C" +{ + /* omsMAXvSetup */ static const iocshArg setupArg0 = {"Max. controller count", iocshArgInt}; static const iocshArg setupArg1 = {"VME address type", iocshArgInt}; @@ -653,3 +653,4 @@ static void OmsMAXvAsynRegister(void) epicsExportRegistrar(OmsMAXvAsynRegister); +} diff --git a/motorApp/OmsAsynSrc/omsMAXv.h b/motorApp/OmsAsynSrc/omsMAXv.h index f923e39..d9d9202 100644 --- a/motorApp/OmsAsynSrc/omsMAXv.h +++ b/motorApp/OmsAsynSrc/omsMAXv.h @@ -2,10 +2,6 @@ FILENAME... omsMAXv.h USAGE... Pro-Dex OMS MAXv asyn motor controller support -Version: $Revision$ -Modified By: $Author$ -Last Modified: $Date$ -HeadURL: $URL$ */ /* diff --git a/motorApp/OmsAsynSrc/omsMAXvEncFunc.cpp b/motorApp/OmsAsynSrc/omsMAXvEncFunc.cpp index 83224a8..9d7948a 100644 --- a/motorApp/OmsAsynSrc/omsMAXvEncFunc.cpp +++ b/motorApp/OmsAsynSrc/omsMAXvEncFunc.cpp @@ -2,10 +2,6 @@ FILENAME... omsMAXvEncFunc.cpp USAGE... Pro-Dex OMS MAXv encoder asyn motor support -Version: $Revision$ -Modified By: $Author$ -Last Modified: $Date$ -HeadURL: $URL$ */ /* diff --git a/motorApp/OmsAsynSrc/omsMAXvEncFunc.h b/motorApp/OmsAsynSrc/omsMAXvEncFunc.h index 3b993db..b948949 100644 --- a/motorApp/OmsAsynSrc/omsMAXvEncFunc.h +++ b/motorApp/OmsAsynSrc/omsMAXvEncFunc.h @@ -2,10 +2,6 @@ FILENAME... omsMAXvEncFunc.h USAGE... Pro-Dex OMS MAXv encoder asyn motor support -Version: $Revision$ -Modified By: $Author$ -Last Modified: $Date$ -HeadURL: $URL$ */ /* diff --git a/motorApp/OmsSrc/README b/motorApp/OmsSrc/README index b6388c9..38417c7 100644 --- a/motorApp/OmsSrc/README +++ b/motorApp/OmsSrc/README @@ -27,13 +27,13 @@ VME space | A16 | A24 | A32 | ----------|--------|-----------|-------------| MAXv size | 0x1000 | 0x01 0000 | 0x0100 0000 | ----------|--------|-----------|-------------| -valid MAXv| 0x0000 | 0x10 0000 | 0x1000 0000 | -addresses | 0x1000 | 0x11 0000 | 0x1100 0000 | - | 0x2000 | 0x12 0000 | 0x1200 0000 | +valid MAXv| 0x0000 | 0x00 0000 | 0x0000 0000 | +addresses | 0x1000 | 0x01 0000 | 0x0100 0000 | + | 0x2000 | 0x02 0000 | 0x0200 0000 | | ... | ... | ... | - | 0xE000 | 0x1E 0000 | 0x1E00 0000 | - | 0xF000 | 0x1F 0000 | 0x1F00 0000 | - | | 0x20 0000 | 0x2000 0000 | + | 0xE000 | 0x0E 0000 | 0x0E00 0000 | + | 0xF000 | 0x0F 0000 | 0x0F00 0000 | + | | 0x10 0000 | 0x1000 0000 | | | ... | ... | | | 0xFF 0000 | 0xFF00 0000 | ----------|--------|-----------|-------------| diff --git a/motorApp/OmsSrc/devMAXv.cc b/motorApp/OmsSrc/devMAXv.cc index bacf4c2..981492c 100644 --- a/motorApp/OmsSrc/devMAXv.cc +++ b/motorApp/OmsSrc/devMAXv.cc @@ -2,10 +2,6 @@ FILENAME... devMAXV.cc USAGE... Device level support for OMS MAXv model. -Version: $Revision: 10834 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2010-04-29 12:04:39 -0500 (Thu, 29 Apr 2010) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/OmsSrc/devMAXv.cc $ */ /* @@ -39,6 +35,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- * .01 04-05-05 rls Copied from devOms58.cc */ +#include + #include "motorRecord.h" #include "devOmsCom.h" #include "epicsExport.h" @@ -47,14 +45,14 @@ extern int MAXv_num_cards; extern struct driver_table MAXv_access; /* ----------------Create the dsets for devMAXv----------------- */ -static long MAXv_init(void *); +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, MAXv_init, MAXv_init_record, NULL}, + {8, NULL, (DEVSUPFUN) MAXv_init, (DEVSUPFUN) MAXv_init_record, NULL}, motor_update_values, MAXv_start_trans, oms_build_trans, @@ -66,10 +64,8 @@ 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(void *arg) +static long MAXv_init(int after) { - int after = (arg == 0) ? 0 : 1; - if (*(MAXv_access.init_indicator) == NO) { errlogSevPrintf(errlogMinor, "%s", errmsg); diff --git a/motorApp/OmsSrc/devOms.cc b/motorApp/OmsSrc/devOms.cc index 9e61b70..018f58e 100644 --- a/motorApp/OmsSrc/devOms.cc +++ b/motorApp/OmsSrc/devOms.cc @@ -3,10 +3,6 @@ FILENAME... devOms.cc USAGE... Device level support for OMS VME8 and VME44 models. -Version: $Revision: 10834 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2010-04-29 12:04:39 -0500 (Thu, 29 Apr 2010) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/OmsSrc/devOms.cc $ */ /* @@ -68,14 +64,14 @@ extern int oms44_num_cards; extern struct driver_table oms_access; /* ----------------Create the dsets for devOMS----------------- */ -static long oms_init(void *); +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, oms_init, oms_init_record, NULL}, + {8, NULL, (DEVSUPFUN) oms_init, (DEVSUPFUN) oms_init_record, NULL}, motor_update_values, oms_start_trans, oms_build_trans, @@ -87,10 +83,8 @@ 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(void *arg) +static long oms_init(int after) { - int after = (arg == 0) ? 0 : 1; - if (*(oms_access.init_indicator) == NO) { errlogSevPrintf(errlogMinor, "%s", errmsg); diff --git a/motorApp/OmsSrc/devOms.dbd b/motorApp/OmsSrc/devOms.dbd index d0b4f55..569232b 100644 --- a/motorApp/OmsSrc/devOms.dbd +++ b/motorApp/OmsSrc/devOms.dbd @@ -5,6 +5,7 @@ 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") diff --git a/motorApp/OmsSrc/devOms58.cc b/motorApp/OmsSrc/devOms58.cc index f8e94f4..d788a06 100644 --- a/motorApp/OmsSrc/devOms58.cc +++ b/motorApp/OmsSrc/devOms58.cc @@ -2,10 +2,6 @@ FILENAME... devOms58.c USAGE... Motor record device level support for OMS VME58. -Version: $Revision: 10834 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2010-04-29 12:04:39 -0500 (Thu, 29 Apr 2010) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/OmsSrc/devOms58.cc $ */ /* @@ -66,14 +62,14 @@ extern int oms58_num_cards; extern struct driver_table oms58_access; /* ----------------Create the dsets for devOMS----------------- */ -static long oms_init(void *); +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, oms_init, oms_init_record, NULL}, + {8, NULL, (DEVSUPFUN) oms_init, (DEVSUPFUN) oms_init_record, NULL}, motor_update_values, oms_start_trans, oms_build_trans, @@ -85,10 +81,8 @@ 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(void *arg) +static long oms_init(int after) { - int after = (arg == 0) ? 0 : 1; - if (*(oms58_access.init_indicator) == NO) { errlogSevPrintf(errlogMinor, "%s", errmsg); diff --git a/motorApp/OmsSrc/devOmsCom.cc b/motorApp/OmsSrc/devOmsCom.cc index c1e4d3c..524d56d 100644 --- a/motorApp/OmsSrc/devOmsCom.cc +++ b/motorApp/OmsSrc/devOmsCom.cc @@ -2,10 +2,6 @@ FILENAME... devOmsCom.cc USAGE... Data and functions common to all OMS device level support. -Version: $Revision: 17420 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2014-05-09 16:51:25 -0500 (Fri, 09 May 2014) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/OmsSrc/devOmsCom.cc $ */ /* @@ -70,6 +66,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- * 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. * */ @@ -80,6 +78,7 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#include #include "motorRecord.h" #include "motor.h" @@ -265,7 +264,7 @@ RTN_STATUS oms_build_trans(motor_cmnd command, double *parms, struct motorRecord char respbuf[10]; (*tabptr->getmsg)(card, respbuf, -1); - (*tabptr->sendmsg)(card, "RB\r", (char) NULL); + (*tabptr->sendmsg)(card, "RB\r", (char*) NULL); (*tabptr->getmsg)(card, respbuf, 1); if (sscanf(respbuf, "%x", &response) == 0) response = 0; /* Force an error. */ @@ -311,7 +310,7 @@ RTN_STATUS oms_build_trans(motor_cmnd command, double *parms, struct motorRecord /* Use MIP to determine which acc. rate to use. */ if (mr->mip & MIP_JOG_STOP) - acc = ((mr->jar) / fabs(mr->mres)) / mr->accl; + acc = mr->jar / fabs(mr->mres); else acc = ((mr->velo - mr->vbas) / fabs(mr->mres)) / mr->accl; @@ -514,7 +513,7 @@ errorexit: errMessage(-1, "Invalid device directive"); if (MAXv == true && parms[0] == parms[1]) sprintf(buffer, " UF"); else - sprintf(buffer, " UU%f;", parms[0]/parms[1]); + sprintf(buffer, " UU%f;", fabs(parms[0]/parms[1])); strcat(motor_call->message, buffer); break; diff --git a/motorApp/OmsSrc/devOmsCom.h b/motorApp/OmsSrc/devOmsCom.h index 00f07d4..10722b2 100644 --- a/motorApp/OmsSrc/devOmsCom.h +++ b/motorApp/OmsSrc/devOmsCom.h @@ -4,10 +4,6 @@ FILENAME.. devOmsCom.h USAGE... This file contains OMS device information that is common to all OMS device support modules. -Version: $Revision: 10834 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2010-04-29 12:04:39 -0500 (Thu, 29 Apr 2010) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/OmsSrc/devOmsCom.h $ */ /* diff --git a/motorApp/OmsSrc/devOmsPC68.cc b/motorApp/OmsSrc/devOmsPC68.cc index 5757ad3..0df953c 100644 --- a/motorApp/OmsSrc/devOmsPC68.cc +++ b/motorApp/OmsSrc/devOmsPC68.cc @@ -2,10 +2,6 @@ FILENAME... devOmsPC68.c USAGE... Motor record device level support for OMS VME58. -Version: $Revision: 10834 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2010-04-29 12:04:39 -0500 (Thu, 29 Apr 2010) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/OmsSrc/devOmsPC68.cc $ */ /* @@ -63,14 +59,14 @@ extern int OmsPC68_num_cards; extern struct driver_table OmsPC68_access; /* ----------------Create the dsets for devOMS----------------- */ -STATIC long oms_init(void *); +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, oms_init, oms_init_record, NULL}, + {8, NULL, (DEVSUPFUN) oms_init, (DEVSUPFUN) oms_init_record, NULL}, motor_update_values, oms_start_trans, oms_build_trans, @@ -84,10 +80,8 @@ STATIC const char errmsg[] = {"\n\n!!!ERROR!!! - OmsPC68 driver uninitialized.\n //__________________________________________________________________________________________ -STATIC long oms_init(void *arg) +STATIC long oms_init(int after) { - int after = (arg == 0) ? 0 : 1; - if (*(OmsPC68_access.init_indicator) == NO) { errlogSevPrintf(errlogMinor, "%s", errmsg); diff --git a/motorApp/OmsSrc/drvMAXv.cc b/motorApp/OmsSrc/drvMAXv.cc index 58e1a82..29ffee4 100644 --- a/motorApp/OmsSrc/drvMAXv.cc +++ b/motorApp/OmsSrc/drvMAXv.cc @@ -2,10 +2,6 @@ FILENAME... drvMAXv.cc USAGE... Motor record driver level support for OMS model MAXv. -Version: $Revision: 17754 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2014-08-19 09:18:35 -0500 (Tue, 19 Aug 2014) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/OmsSrc/drvMAXv.cc $ */ /* @@ -97,6 +93,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- * 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. * */ @@ -114,6 +112,7 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#include #include "motorRecord.h" /* For Driver Power Monitor feature only. */ #include "motor.h" @@ -169,7 +168,7 @@ static epicsAddressType MAXv_ADDRS_TYPE; static volatile unsigned MAXvInterruptVector = 0; static volatile epicsUInt8 omsInterruptLevel = OMS_INT_LEVEL; static volatile int motionTO = 10; -static char *MAXv_axis[] = {"X", "Y", "Z", "T", "U", "V", "R", "S"}; +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 */ @@ -256,7 +255,7 @@ struct driver_table MAXv_access = query_done, NULL, &initialized, - MAXv_axis + (char **) MAXv_axis }; struct drvMAXv_drvet @@ -310,10 +309,10 @@ static void query_done(int card, int axis, struct mess_node *nodeptr) { char buffer[MAX_IDENT_LEN]; - send_recv_mess(card, DONE_QUERY, MAXv_axis[axis], buffer, 1); + send_recv_mess(card, DONE_QUERY, (char *) MAXv_axis[axis], buffer, 1); if (nodeptr->status.Bits.RA_PROBLEM) - send_mess(card, AXIS_STOP, MAXv_axis[axis]); + send_mess(card, AXIS_STOP, (char *) MAXv_axis[axis]); } @@ -374,7 +373,6 @@ static int set_status(int card, int signal) char q_buf[MAX_IDENT_LEN], outbuf[50]; int index; bool ls_active = false; - bool got_encoder; msta_field status; int absoluteAxis = (configurationFlags[card] & (1 << signal)); @@ -392,13 +390,13 @@ static int set_status(int card, int signal) MAXvCntrl = (struct MAXvController *) brdptr->DevicePrivate; if (MAXvCntrl->fwver >= 1.33) { - send_recv_mess(card, "#WS", (char) NULL, q_buf, 1); + 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); + send_mess(card, STOP_ALL, (char*) NULL); /* Disable board. */ motor_state[card] = (struct controller *) NULL; return(rtn_state = 1); /* End move. */ @@ -408,16 +406,14 @@ static int set_status(int card, int signal) if (motor_info->encoder_present == YES) { /* get 4 pieces of info from axis */ - send_recv_mess(card, "QA", MAXv_axis[signal], &q_buf[0], 1); + send_recv_mess(card, "QA", (char *) MAXv_axis[signal], &q_buf[0], 1); q_buf[4] = ','; - send_recv_mess(card, "EA", MAXv_axis[signal], &q_buf[5], 1); - got_encoder = true; + 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, MAXv_axis[signal], q_buf, 1); - got_encoder = false; + send_recv_mess(card, AXIS_INFO, (char *) MAXv_axis[signal], q_buf, 1); } for (index = 0, p = epicsStrtok_r(q_buf, ",", &tok_save); p; @@ -479,7 +475,7 @@ static int set_status(int card, int signal) if (motor_info->no_motion_count > motionTO) { status.Bits.RA_PROBLEM = 1; - send_mess(card, AXIS_STOP, MAXv_axis[signal]); + 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); @@ -493,7 +489,7 @@ static int set_status(int card, int signal) status.Bits.RA_PROBLEM = 0; /* get command velocity */ - send_recv_mess(card, "RV", MAXv_axis[signal], q_buf, 1); + send_recv_mess(card, "RV", (char *) MAXv_axis[signal], q_buf, 1); motor_info->velocity = atoi(q_buf); /* Get encoder position */ @@ -586,7 +582,7 @@ errorexit: errMessage(-1, "Invalid device directive"); strcpy(buffer, nodeptr->postmsgptr); strcpy(outbuf, buffer); - send_mess(card, outbuf, MAXv_axis[signal]); + send_mess(card, outbuf, (char *) MAXv_axis[signal]); nodeptr->postmsgptr = NULL; } @@ -895,7 +891,7 @@ 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 (1-6) */ + int int_level, /* interrupt level (2-6) */ int scan_rate) /* 1 <= polling rate <= (1/epicsThreadSleepQuantum) */ { int itera; @@ -995,9 +991,9 @@ MAXvSetup(int num_cards, /* maximum number of cards in rack */ } } - if (int_level < 1 || int_level > 6) + if (int_level < 2 || int_level > 6) { - char format[] = "%sinterrupt level = %d ***\n"; + char format[] = "%sinterrupt level = %d *** default = 5\n"; omsInterruptLevel = OMS_INT_LEVEL; errlogPrintf(format, errbase, int_level); epicsThreadSleep(5.0); @@ -1119,7 +1115,7 @@ static int motorIsrSetup(int card) status = pdevLibVirtualOS->pDevConnectInterruptVME( MAXvInterruptVector + card, -#if LT_EPICSBASE(3,14,8) +#if LT_EPICSBASE(3,14,8,0) (void (*)()) motorIsr, #else (void (*)(void *)) motorIsr, @@ -1195,6 +1191,7 @@ static int motor_init() epicsInt8 *startAddr; epicsInt8 *endAddr; bool wdtrip; + int rtn_code; Debug(2, "motor_init: card %d\n", card_index); @@ -1264,10 +1261,16 @@ static int motor_init() 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); + send_mess(card_index, ERROR_CLEAR, (char*) NULL); + send_mess(card_index, STOP_ALL, (char*) NULL); - send_recv_mess(card_index, GET_IDENT, (char) NULL, (char *) pmotorState->ident, 1); + 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. */ @@ -1278,7 +1281,7 @@ static int motor_init() if (pvtdata->fwver >= 1.33) { - send_recv_mess(card_index, "#WS", (char) NULL, axis_pos, 1); + send_recv_mess(card_index, "#WS", (char *) NULL, axis_pos, 1); if (strcmp(axis_pos, "=0") != 0) { errlogPrintf(wdctrmsg, card_index, axis_pos); @@ -1290,9 +1293,9 @@ static int motor_init() if (wdtrip == false) { - send_mess(card_index, initstring[card_index], (char) NULL); + send_mess(card_index, initstring[card_index], (char*) NULL); - send_recv_mess(card_index, ALL_POS, (char) NULL, axis_pos, 1); + 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++) @@ -1310,7 +1313,7 @@ static int motor_init() STATUS1 flag1; /* Test if motor has an encoder. */ - send_mess(card_index, ENCODER_QUERY, MAXv_axis[motor_index]); + send_mess(card_index, ENCODER_QUERY, (char *) MAXv_axis[motor_index]); while (!pmotor->status1_flag.Bits.done) /* Wait for command to complete. */ epicsThreadSleep(quantum); @@ -1329,7 +1332,7 @@ static int motor_init() } /* Test if motor has PID parameters. */ - send_mess(card_index, PID_QUERY, MAXv_axis[motor_index]); + 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) @@ -1356,9 +1359,9 @@ static int motor_init() if (pvtdata->fwver >= 1.30) { - send_recv_mess(card_index, "LM?", MAXv_axis[motor_index], axis_pos, 1); + 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", MAXv_axis[motor_index]); /* Set limit mode to "Hard". */ + send_mess(card_index, "LMH", (char *) MAXv_axis[motor_index]); /* Set limit mode to "Hard". */ } } @@ -1385,7 +1388,7 @@ static int motor_init() set_status(card_index, motor_index); /* Is this needed??? */ - send_recv_mess(card_index, DONE_QUERY, MAXv_axis[motor_index], axis_pos, 1); + send_recv_mess(card_index, DONE_QUERY, (char *) MAXv_axis[motor_index], axis_pos, 1); } Debug(2, "motor_init: Init Address=%p\n", localaddr); diff --git a/motorApp/OmsSrc/drvMAXv.h b/motorApp/OmsSrc/drvMAXv.h index d53e6ee..db648d0 100644 --- a/motorApp/OmsSrc/drvMAXv.h +++ b/motorApp/OmsSrc/drvMAXv.h @@ -3,10 +3,6 @@ FILENAME... drvMAXv.h USAGE... OMS driver level "include" information that is specific to OMS model MAXv. -Version: $Revision: 17212 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2014-02-06 15:16:54 -0600 (Thu, 06 Feb 2014) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/OmsSrc/drvMAXv.h $ */ /* diff --git a/motorApp/OmsSrc/drvOms.cc b/motorApp/OmsSrc/drvOms.cc index a213ab2..47e4494 100644 --- a/motorApp/OmsSrc/drvOms.cc +++ b/motorApp/OmsSrc/drvOms.cc @@ -2,10 +2,6 @@ FILENAME... drvOms.cc USAGE... Driver level support for OMS models VME8, VME44, VS4 and VX2. -Version: $Revision: 17104 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2013-11-15 13:44:42 -0600 (Fri, 15 Nov 2013) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/OmsSrc/drvOms.cc $ */ /* @@ -114,6 +110,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#include +#include #include "motor.h" #include "drvOms.h" @@ -924,7 +922,7 @@ static int motorIsrEnable(int card) long status; status = pdevLibVirtualOS->pDevConnectInterruptVME( omsInterruptVector + card, -#if LT_EPICSBASE(3,14,8) +#if LT_EPICSBASE(3,14,8,0) (void (*)()) motorIsr, #else (void (*)(void *)) motorIsr, @@ -1013,7 +1011,7 @@ static void motorIsrDisable(int card) /*****************************************************/ RTN_STATUS omsSetup(int num_cards, /* maximum number of cards in rack */ - void *addrs, /* Base Address(0x0-0xb000 on 4K boundary) */ + 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 */ @@ -1172,16 +1170,16 @@ static int motor_init() 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, "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); + 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); + 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); diff --git a/motorApp/OmsSrc/drvOms.h b/motorApp/OmsSrc/drvOms.h index a4c7b1e..6a86a49 100644 --- a/motorApp/OmsSrc/drvOms.h +++ b/motorApp/OmsSrc/drvOms.h @@ -3,9 +3,6 @@ FILENAME... drvOms.h USAGE... This file contains OMS driver "include" information that is specific to OMS models VME8 and VME44. -Version: $Revision: 14915 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2012-07-26 14:18:18 -0500 (Thu, 26 Jul 2012) $ */ /* diff --git a/motorApp/OmsSrc/drvOms58.cc b/motorApp/OmsSrc/drvOms58.cc index 231f16f..f2d8261 100644 --- a/motorApp/OmsSrc/drvOms58.cc +++ b/motorApp/OmsSrc/drvOms58.cc @@ -2,10 +2,6 @@ FILENAME... drvOms58.cc USAGE... Motor record driver level support for OMS model VME58. -Version: $Revision: 14914 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2012-07-26 14:04:55 -0500 (Thu, 26 Jul 2012) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/OmsSrc/drvOms58.cc $ */ /* @@ -115,6 +111,13 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- * .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. * */ @@ -129,6 +132,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#include +#include #include "motorRecord.h" /* For Driver Power Monitor feature only. */ #include "motor.h" @@ -136,6 +141,7 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include "drvOms58.h" #include "epicsExport.h" +#include "iocsh.h" #define PRIVATE_FUNCTIONS 1 /* normal:1, debug:0 */ @@ -169,6 +175,7 @@ static inline void Debug(int level, const char *format, ...) { /* Global data. */ int oms58_num_cards = 0; +int oms58_reboot_test = 0; /* Local data required for every driver; see "motordrvComCode.h" */ #include "motordrvComCode.h" @@ -722,7 +729,20 @@ static RTN_STATUS send_mess(int card, char const *com, char *name) Debug(4, "send_mess: sent card %d message:", card); Debug(4, "%s\n", outbuf); - pmotor->outPutIndex = putIndex; /* Message Sent */ + 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++) { @@ -1050,7 +1070,7 @@ static int motorIsrSetup(int card) pmotor = (struct vmex_motor *) (motor_state[card]->localaddr); status = pdevLibVirtualOS->pDevConnectInterruptVME(omsInterruptVector + card, -#if LT_EPICSBASE(3,14,8) +#if LT_EPICSBASE(3,14,8,0) (void (*)()) motorIsr, #else (void (*)(void *)) motorIsr, @@ -1176,15 +1196,15 @@ static int motor_init() 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, "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); + 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); + 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); @@ -1338,4 +1358,30 @@ static void oms_reset(void *arg) } +/* 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 index 4774bd2..bb1b85a 100644 --- a/motorApp/OmsSrc/drvOms58.h +++ b/motorApp/OmsSrc/drvOms58.h @@ -3,10 +3,6 @@ FILENAME... drvOms58.h USAGE... OMS driver level "include" information that is specific to OMS model VME58. -Version: $Revision: 12209 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-01-26 13:13:47 -0600 (Wed, 26 Jan 2011) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/OmsSrc/drvOms58.h $ */ /* diff --git a/motorApp/OmsSrc/drvOmsCom.h b/motorApp/OmsSrc/drvOmsCom.h index f6a3217..6e837de 100644 --- a/motorApp/OmsSrc/drvOmsCom.h +++ b/motorApp/OmsSrc/drvOmsCom.h @@ -3,9 +3,6 @@ FILENAME... drvOmsCom.h USAGE... This file contains OMS driver "include" information that is common to all OMS models. -Version: $Revision: 10834 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2010-04-29 12:04:39 -0500 (Thu, 29 Apr 2010) $ */ /* diff --git a/motorApp/OmsSrc/drvOmsPC68.cc b/motorApp/OmsSrc/drvOmsPC68.cc index 45b9e05..1582ccd 100644 --- a/motorApp/OmsSrc/drvOmsPC68.cc +++ b/motorApp/OmsSrc/drvOmsPC68.cc @@ -2,9 +2,6 @@ FILENAME... drvOmsPC68.cc USAGE... Motor record driver level support for OMS PC68 serial device. -Version: $Revision: 14155 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ */ /* @@ -75,6 +72,8 @@ Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ #include #include #include +#include +#include #include "motor.h" #include "drvOmsPC68Com.h" @@ -771,7 +770,7 @@ static int motor_init() /* Try 3 times to connect to controller. */ do { - send_mess (card_index, GET_IDENT, (char) NULL); + send_mess (card_index, GET_IDENT, (char*) NULL); status = recv_mess(card_index, (char *) pmotorState->ident, 1); retry++; } while (status == 0 && retry < 3); @@ -784,11 +783,11 @@ static int motor_init() 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, 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); + 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); @@ -823,7 +822,7 @@ static int motor_init() * dummy communication transaction. */ - send_mess (card_index, ALL_POS, (char) NULL); + send_mess (card_index, ALL_POS, (char*) NULL); recv_mess (card_index, axis_pos, 1); for (motor_index=0;motor_index #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -53,7 +51,7 @@ extern struct driver_table EMC18011_access; /* ----------------Create the dsets for devEMC18011----------------- */ STATIC struct driver_table *drvtabptr; -STATIC long EMC18011_init(void *); +STATIC long EMC18011_init(int); STATIC long EMC18011_init_record(void *); STATIC long EMC18011_start_trans(struct motorRecord *); STATIC RTN_STATUS EMC18011_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -107,12 +105,11 @@ static struct board_stat **EMC18011_cards; /* initialize device support for EMC18011 stepper motor */ -STATIC long EMC18011_init(void *arg) +STATIC long EMC18011_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &EMC18011_access; (drvtabptr->init)(); diff --git a/motorApp/OrielSrc/drvEMC18011.cc b/motorApp/OrielSrc/drvEMC18011.cc index 30d731f..ae1313b 100644 --- a/motorApp/OrielSrc/drvEMC18011.cc +++ b/motorApp/OrielSrc/drvEMC18011.cc @@ -3,10 +3,6 @@ FILENAME... drvEMC18011.cc USAGE... Motor record driver level support for Spectra-Physics Encoder Mike Controller (Model: 18011) -Version: $Revision: 14155 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/OrielSrc/drvEMC18011.cc $ */ /* @@ -47,6 +43,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#include +#include #include "motor.h" #include "OrielRegister.h" #include "drvEMC18011.h" @@ -383,7 +381,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strncpy(send_buff, nodeptr->postmsgptr, 80); - send_mess(card, send_buff, (char) NULL); + send_mess(card, send_buff, (char*) NULL); nodeptr->postmsgptr = NULL; } diff --git a/motorApp/OrielSrc/drvEMC18011.h b/motorApp/OrielSrc/drvEMC18011.h index 17b7700..8f0f205 100644 --- a/motorApp/OrielSrc/drvEMC18011.h +++ b/motorApp/OrielSrc/drvEMC18011.h @@ -3,9 +3,6 @@ FILENAME... drvEMC18011.h USAGE... This file contains Parker Compumotor driver "include" information that is specific to the 6K series serial controller -Version: $Revision: 1.3 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2006-11-02 21:05:56 $ */ /* diff --git a/motorApp/PC6KSrc/ParkerRegister.cc b/motorApp/PC6KSrc/ParkerRegister.cc index c5230ca..4ce21a4 100644 --- a/motorApp/PC6KSrc/ParkerRegister.cc +++ b/motorApp/PC6KSrc/ParkerRegister.cc @@ -2,9 +2,6 @@ FILENAME... ParkerRegister.cc USAGE... Register Parker/Compumotor motor device driver shell commands. -Version: $Revision: 1.2 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2006-08-31 15:42:31 $ */ /***************************************************************** diff --git a/motorApp/PC6KSrc/devPC6K.cc b/motorApp/PC6KSrc/devPC6K.cc index 963ba02..86d81c8 100644 --- a/motorApp/PC6KSrc/devPC6K.cc +++ b/motorApp/PC6KSrc/devPC6K.cc @@ -2,9 +2,6 @@ FILENAME... devPC6K.cc USAGE... Motor record device level support for Parker Compumotor drivers -Version: $Revision: 1.4 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-03-14 20:19:43 $ */ /* @@ -40,6 +37,7 @@ Last Modified: $Date: 2008-03-14 20:19:43 $ #include #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -52,7 +50,7 @@ extern struct driver_table PC6K_access; /* ----------------Create the dsets for devPC6K----------------- */ STATIC struct driver_table *drvtabptr; -STATIC long PC6K_init(void *); +STATIC long PC6K_init(int); STATIC long PC6K_init_record(void *); STATIC long PC6K_start_trans(struct motorRecord *); STATIC RTN_STATUS PC6K_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -106,12 +104,11 @@ static struct board_stat **PC6K_cards; /* initialize device support for PC6K stepper motor */ -STATIC long PC6K_init(void *arg) +STATIC long PC6K_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &PC6K_access; (drvtabptr->init)(); diff --git a/motorApp/PC6KSrc/drvPC6K.cc b/motorApp/PC6KSrc/drvPC6K.cc index cf13507..7da4fb9 100644 --- a/motorApp/PC6KSrc/drvPC6K.cc +++ b/motorApp/PC6KSrc/drvPC6K.cc @@ -3,10 +3,6 @@ FILENAME... drvPC6K.cc USAGE... Motor record driver level support for Parker Computmotor 6K Series motor controllers -Version: $Revision: 14155 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/PC6KSrc/drvPC6K.cc $ */ /* @@ -47,6 +43,8 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#include +#include #include "motor.h" #include "ParkerRegister.h" #include "drvPC6K.h" @@ -433,7 +431,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strncpy(send_buff, nodeptr->postmsgptr, 80); - send_mess(card, send_buff, (char) NULL); + send_mess(card, send_buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -706,12 +704,12 @@ PC6KUpLoad(int card, /* Controller Number */ /* Copy file into PC6K Program */ sprintf(nextLine, "DEL %s", progName); // recvCnt = send_recv_mess(card, nextLine, replyBuff); - send_mess(card, nextLine, (char) NULL); + send_mess(card, nextLine, (char*) NULL); // eos_ptr = eos_str; sprintf(nextLine, "DEF %s", progName); // recvCnt = send_recv_mess(card, nextLine, replyBuff, eos_ptr); // recvCnt = send_recv_mess(card, nextLine, replyBuff); - send_mess(card, nextLine, (char) NULL); + send_mess(card, nextLine, (char*) NULL); } while (fgets(nextLine, BUFF_SIZE, fd) != NULL) @@ -723,7 +721,7 @@ PC6KUpLoad(int card, /* Controller Number */ // recvCnt = send_recv_mess(card, nextLine, replyBuff, eos_ptr); // recvCnt = send_recv_mess(card, nextLine, replyBuff); - send_mess(card, nextLine, (char) NULL); + send_mess(card, nextLine, (char*) NULL); } fclose(fd); @@ -731,7 +729,7 @@ PC6KUpLoad(int card, /* Controller Number */ if (progName && strlen(progName)) /* End PC6K Program */ // recvCnt = send_recv_mess(card, "END", replyBuff); - send_mess(card, "END", (char) NULL); + send_mess(card, "END", (char*) NULL); return(OK); } @@ -834,7 +832,7 @@ static int motor_init() } while (!recvCnt && ++retryCnt < 3); - /* send_mess(card_index, COMEXEC_ENA, (char) NULL); */ /* Enable continuous commands */ + /* send_mess(card_index, COMEXEC_ENA, (char*) NULL); */ /* Enable continuous commands */ send_recv_mess(card_index, COMEXEC_ENA, buff); /* Enable continuous commands */ // send_recv_mess(card_index, CMD_SCALE, buff); /* Enable scaling - unary */ diff --git a/motorApp/PC6KSrc/drvPC6K.h b/motorApp/PC6KSrc/drvPC6K.h index 516b482..fe17cb8 100644 --- a/motorApp/PC6KSrc/drvPC6K.h +++ b/motorApp/PC6KSrc/drvPC6K.h @@ -3,9 +3,6 @@ FILENAME... drvPC6K.h USAGE... This file contains Parker Compumotor driver "include" information that is specific to the 6K series serial controller -Version: $Revision: 1.2 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2006-08-31 15:42:31 $ */ /* diff --git a/motorApp/PIGCS2Src/PIC702Controller.cpp b/motorApp/PIGCS2Src/PIC702Controller.cpp index 72a65cb..2478cc0 100644 --- a/motorApp/PIGCS2Src/PIC702Controller.cpp +++ b/motorApp/PIGCS2Src/PIC702Controller.cpp @@ -8,10 +8,6 @@ USAGE... * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 2$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 25.10.2013 10:43:08$ -HeadURL: $URL$ Original Author: Steffen Rau Created: January 2011 diff --git a/motorApp/PIGCS2Src/PIC702Controller.h b/motorApp/PIGCS2Src/PIC702Controller.h index ebcc269..183ce0a 100644 --- a/motorApp/PIGCS2Src/PIC702Controller.h +++ b/motorApp/PIGCS2Src/PIC702Controller.h @@ -7,10 +7,6 @@ FILENAME... PIC702Controller.h * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 2$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 25.10.2013 10:43:08$ -HeadURL: $URL$ Original Author: Steffen Rau */ diff --git a/motorApp/PIGCS2Src/PIE517Controller.cpp b/motorApp/PIGCS2Src/PIE517Controller.cpp index 0d9f764..daa59bc 100644 --- a/motorApp/PIGCS2Src/PIE517Controller.cpp +++ b/motorApp/PIGCS2Src/PIE517Controller.cpp @@ -7,10 +7,6 @@ FILENAME... PIGCSPiezoController * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 3$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 25.10.2013 10:43:08$ -HeadURL: $URL$ Original Author: Steffen Rau Created: 15.12.2010 diff --git a/motorApp/PIGCS2Src/PIE517Controller.h b/motorApp/PIGCS2Src/PIE517Controller.h index 335af9e..ddcd765 100644 --- a/motorApp/PIGCS2Src/PIE517Controller.h +++ b/motorApp/PIGCS2Src/PIE517Controller.h @@ -7,10 +7,6 @@ FILENAME... PIGCScontroller.h * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 3$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 25.10.2013 10:43:08$ -HeadURL: $URL$ Original Author: Steffen Rau Created: 15.12.2010 diff --git a/motorApp/PIGCS2Src/PIE755Controller.cpp b/motorApp/PIGCS2Src/PIE755Controller.cpp index ec56007..216af21 100644 --- a/motorApp/PIGCS2Src/PIE755Controller.cpp +++ b/motorApp/PIGCS2Src/PIE755Controller.cpp @@ -7,10 +7,6 @@ FILENAME... PIE755Controller.cpp * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 1$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 23.09.2013 14:19:03$ -HeadURL: $URL$ Original Author: Steffen Rau */ diff --git a/motorApp/PIGCS2Src/PIE755Controller.h b/motorApp/PIGCS2Src/PIE755Controller.h index b30db9f..c9caf48 100644 --- a/motorApp/PIGCS2Src/PIE755Controller.h +++ b/motorApp/PIGCS2Src/PIE755Controller.h @@ -7,10 +7,6 @@ FILENAME... PIE755Controller.h * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 2$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 25.10.2013 10:43:08$ -HeadURL: $URL$ Original Author: Steffen Rau */ diff --git a/motorApp/PIGCS2Src/PIGCS2_HexapodController.cpp b/motorApp/PIGCS2Src/PIGCS2_HexapodController.cpp index c6e4014..32c018f 100644 --- a/motorApp/PIGCS2Src/PIGCS2_HexapodController.cpp +++ b/motorApp/PIGCS2Src/PIGCS2_HexapodController.cpp @@ -7,10 +7,6 @@ FILENAME... PIHexapodController.cpp * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 1$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 05.11.2013 17:38:06$ -HeadURL: $URL$ Original Author: Steffen Rau */ diff --git a/motorApp/PIGCS2Src/PIGCS2_HexapodController.h b/motorApp/PIGCS2Src/PIGCS2_HexapodController.h index 1bdf38f..b070d24 100644 --- a/motorApp/PIGCS2Src/PIGCS2_HexapodController.h +++ b/motorApp/PIGCS2Src/PIGCS2_HexapodController.h @@ -7,10 +7,6 @@ FILENAME... PIHexapodController.h * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 1$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 05.11.2013 17:38:06$ -HeadURL: $URL$ Original Author: Steffen Rau */ diff --git a/motorApp/PIGCS2Src/PIGCSController.cpp b/motorApp/PIGCS2Src/PIGCSController.cpp index dfb537e..1184c0a 100644 --- a/motorApp/PIGCS2Src/PIGCSController.cpp +++ b/motorApp/PIGCS2Src/PIGCSController.cpp @@ -7,10 +7,6 @@ FILENAME... PIGCSController.cpp * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 6$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 05.11.2013 17:38:32$ -HeadURL: $URL$ Original Author: Steffen Rau Created: 15.12.2010 @@ -48,6 +44,10 @@ PIGCSController* PIGCSController::CreateGCSController(PIInterface* pInterface, c if ( strstr(szIDN, "C-663") != NULL || strstr(szIDN, "C-863") != NULL || strstr(szIDN, "C-867") != NULL + || strstr(szIDN, "C-884") != NULL + || strstr(szIDN, "E-861") != NULL + || strstr(szIDN, "E-871") != NULL + || strstr(szIDN, "E-873") != NULL ) { return new PIGCSMotorController(pInterface, szIDN); @@ -58,7 +58,10 @@ PIGCSController* PIGCSController::CreateGCSController(PIInterface* pInterface, c } else if ( strstr(szIDN, "E-753") != NULL || strstr(szIDN, "E-709") != NULL - ) + || strstr(szIDN, "E-712") != NULL + || strstr(szIDN, "E-725") != NULL + || strstr(szIDN, "E-727") != NULL + ) { return new PIGCSPiezoController(pInterface, szIDN); } @@ -110,6 +113,10 @@ bool PIGCSController::IsGCS2(PIInterface* pInterface) asynStatus PIGCSController::setVelocityCts( PIasynAxis* pAxis, double velocity ) { + if (!m_KnowsVELcommand) + { + return asynSuccess; + } char cmd[100]; velocity = fabs(velocity) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator; sprintf(cmd,"VEL %s %f", pAxis->m_szAxisName, velocity); @@ -246,17 +253,21 @@ int PIGCSController::getGCSError() if (0 != errorCode) { m_LastError = errorCode; - asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW, - "PIGCSController::getGCSError() GCS error code = %d\n", - errorCode); - char szErrorMsg[1024]; - if (TranslatePIError(errorCode, szErrorMsg, 1024)) - { - asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW, - "PIGCSController::getGCSError() GCS error, %s\n", - szErrorMsg); - - } + if (m_pInterface->m_pCurrentLogSink) + { + asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW, + "PIGCSController::getGCSError() GCS error code = %d\n", + errorCode); + + char szErrorMsg[1024]; + if (TranslatePIError(errorCode, szErrorMsg, 1024)) + { + asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW, + "PIGCSController::getGCSError() GCS error, %s\n", + szErrorMsg); + + } + } } return errorCode; } @@ -307,6 +318,10 @@ asynStatus PIGCSController::getAxisPosition(PIasynAxis* pAxis, double& position) */ asynStatus PIGCSController::getAxisVelocity(PIasynAxis* pAxis) { + if (!m_KnowsVELcommand) + { + return asynSuccess; + } char cmd[100]; char buf[255]; sprintf(cmd, "VEL? %s", pAxis->m_szAxisName); @@ -442,7 +457,7 @@ asynStatus PIGCSController::getAxisPositionCts(PIasynAxis* pAxis) pAxis->m_position = pos; if (pAxis->m_CPUdenominator==0 || pAxis->m_CPUnumerator==0) { - pAxis->m_positionCts = pos; + pAxis->m_positionCts = int(pos); return status; } @@ -576,7 +591,7 @@ asynStatus PIGCSController::initAxis(PIasynAxis* pAxis) asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_FLOW, "PIGCSController::initAxis() stage configuration: %s\n", buf); } - pAxis->m_movingStateMask = pow(2.0, pAxis->getAxisNo()); + pAxis->m_movingStateMask = int (pow(2.0, pAxis->getAxisNo()) ); return setServo(pAxis, 1); } @@ -584,6 +599,15 @@ asynStatus PIGCSController::initAxis(PIasynAxis* pAxis) asynStatus PIGCSController::init(void) { asynStatus status; + char buffer [1024]; + status = m_pInterface->sendAndReceive("VEL?", buffer, 1023); + m_KnowsVELcommand = ( asynSuccess == status); + if (!m_KnowsVELcommand) + { + (void) getGCSError (); + } + + status = findConnectedAxes(); return status; } diff --git a/motorApp/PIGCS2Src/PIGCSController.h b/motorApp/PIGCS2Src/PIGCSController.h index 433adee..29db5fb 100644 --- a/motorApp/PIGCS2Src/PIGCSController.h +++ b/motorApp/PIGCS2Src/PIGCSController.h @@ -7,10 +7,6 @@ FILENAME... PIGCScontroller.h * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 5$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 05.11.2013 17:38:32$ -HeadURL: $URL$ Original Author: Steffen Rau Created: 15.12.2010 @@ -113,6 +109,8 @@ class PIGCSController size_t m_nrFoundAxes; char m_allAxesIDs[255]; int m_LastError; + + bool m_KnowsVELcommand; }; #endif /* PIGCSCONTROLLER_H_ */ diff --git a/motorApp/PIGCS2Src/PIGCSMotorController.cpp b/motorApp/PIGCS2Src/PIGCSMotorController.cpp index 7bdfd36..78e320f 100644 --- a/motorApp/PIGCS2Src/PIGCSMotorController.cpp +++ b/motorApp/PIGCS2Src/PIGCSMotorController.cpp @@ -7,10 +7,6 @@ FILENAME... PIGCSMotorController.cpp * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 2$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 25.10.2013 10:43:08$ -HeadURL: $URL$ Original Author: Steffen Rau Created: 15.12.2010 @@ -28,87 +24,87 @@ Created: 15.12.2010 asynStatus PIGCSMotorController::initAxis(PIasynAxis* pAxis) { - asynStatus status = hasLimitSwitches(pAxis); - if (asynSuccess != status) - { - return status; - } - status = hasReferenceSensor(pAxis); - if (asynSuccess != status) - { - return status; - } - return PIGCSController::initAxis(pAxis); + asynStatus status = hasLimitSwitches(pAxis); + if (asynSuccess != status) + { + return status; + } + status = hasReferenceSensor(pAxis); + if (asynSuccess != status) + { + return status; + } + return PIGCSController::initAxis(pAxis); } asynStatus PIGCSMotorController::setAccelerationCts( PIasynAxis* pAxis, double accelerationCts) { - double acceleration = fabs(accelerationCts) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator; - if (acceleration == pAxis->m_acceleration) - return asynSuccess; - if (pAxis->m_maxAcceleration < 0) - { - getMaxAcceleration(pAxis); - } - if (acceleration > pAxis->m_maxAcceleration) - acceleration = pAxis->m_maxAcceleration; - - return setAcceleration(pAxis, acceleration); + double acceleration = fabs(accelerationCts) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator; + if (acceleration == pAxis->m_acceleration) + return asynSuccess; + if (pAxis->m_maxAcceleration < 0) + { + getMaxAcceleration(pAxis); + } + if (acceleration > pAxis->m_maxAcceleration) + acceleration = pAxis->m_maxAcceleration; + + return setAcceleration(pAxis, acceleration); } asynStatus PIGCSMotorController::referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards) { - asynStatus status = setServo(pAxis, 1); + asynStatus status = setServo(pAxis, 1); if (asynSuccess != status) - return status; - - char cmd[100]; - if (velocity != 0) - { - velocity = fabs(velocity) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator; - sprintf(cmd,"SPA %s 0x50 %f", pAxis->m_szAxisName, velocity); - m_pInterface->sendOnly(cmd); - } - - if (pAxis->m_bHasReference) - { - // call FRF - find reference - sprintf(cmd,"FRF %s", pAxis->m_szAxisName); - } - else if (pAxis->m_bHasLimitSwitches) - { - if (forwards) - { - // call FPL - find positive limit switch - sprintf(cmd,"FPL %s", pAxis->m_szAxisName); - } - else - { - // call FNL - find negative limit switch - sprintf(cmd,"FNL %s", pAxis->m_szAxisName); - } - } - else - { - asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_ERROR, - "PIGCSMotorController::referenceVelCts() failed - axis has no reference/limit switch\n"); - epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize, - "PIGCSMotorController::referenceVelCts() failed - axis has no reference/limit switch\n"); - return asynError; - } - status = m_pInterface->sendOnly(cmd); - if (asynSuccess != status) - return status; - int errorCode = getGCSError(); - if (errorCode == 0) - { - return asynSuccess; - } + return status; + + char cmd[100]; + if (velocity != 0) + { + velocity = fabs(velocity) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator; + sprintf(cmd,"SPA %s 0x50 %f", pAxis->m_szAxisName, velocity); + m_pInterface->sendOnly(cmd); + } + + if (pAxis->m_bHasReference) + { + // call FRF - find reference + sprintf(cmd,"FRF %s", pAxis->m_szAxisName); + } + else if (pAxis->m_bHasLimitSwitches) + { + if (forwards) + { + // call FPL - find positive limit switch + sprintf(cmd,"FPL %s", pAxis->m_szAxisName); + } + else + { + // call FNL - find negative limit switch + sprintf(cmd,"FNL %s", pAxis->m_szAxisName); + } + } + else + { + asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_ERROR, + "PIGCSMotorController::referenceVelCts() failed - axis has no reference/limit switch\n"); + epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize, + "PIGCSMotorController::referenceVelCts() failed - axis has no reference/limit switch\n"); + return asynError; + } + status = m_pInterface->sendOnly(cmd); + if (asynSuccess != status) + return status; + int errorCode = getGCSError(); + if (errorCode == 0) + { + return asynSuccess; + } asynPrint(m_pInterface->m_pCurrentLogSink, ASYN_TRACE_ERROR, - "PIGCSMotorController::referenceVelCts() failed\n"); - epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize, - "PIGCSMotorController::referenceVelCts() failed - GCS Error %d\n",errorCode); - return asynError; + "PIGCSMotorController::referenceVelCts() failed\n"); + epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize, + "PIGCSMotorController::referenceVelCts() failed - GCS Error %d\n",errorCode); + return asynError; } @@ -117,18 +113,18 @@ asynStatus PIGCSMotorController::referenceVelCts( PIasynAxis* pAxis, double velo */ asynStatus PIGCSMotorController::getResolution(PIasynAxis* pAxis, double& resolution ) { - // CPU is "Counts Per Unit" - // this is stored as two integers in the controller + // CPU is "Counts Per Unit" + // this is stored as two integers in the controller double num, denom; asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_CPU_Z, num); if (status != asynSuccess) { - return status; + return status; } status = getGCSParameter(pAxis, PI_PARA_MOT_CPU_N, denom); if (status != asynSuccess) { - return status; + return status; } pAxis->m_CPUnumerator = num; pAxis->m_CPUdenominator = denom; @@ -139,11 +135,11 @@ asynStatus PIGCSMotorController::getResolution(PIasynAxis* pAxis, double& resolu asynStatus PIGCSMotorController::getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl) { - char buf[255]; + char buf[255]; asynStatus status = m_pInterface->sendAndReceive(char(4), buf, 99); if (status != asynSuccess) { - return status; + return status; } // TODO this is for a single axis C-863/867 controller!!!! // TODO a) change it to multi-axis code. @@ -167,35 +163,43 @@ asynStatus PIGCSMotorController::getStatus(PIasynAxis* pAxis, int& homing, int& asynStatus PIGCSMotorController::getMaxAcceleration(PIasynAxis* pAxis) { - double maxAcc, maxDec; - asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_MAX_ACCEL, maxAcc); - if (asynSuccess != status) - return status; - status = getGCSParameter(pAxis, PI_PARA_MOT_MAX_DECEL, maxDec); - if (asynSuccess != status) - return status; - - if (maxAcc < maxDec) - { - pAxis->m_maxAcceleration = maxAcc; - } - else - { - pAxis->m_maxAcceleration = maxDec; - } - return status; + if (!m_KnowsVELcommand) + { + return asynSuccess; + } + double maxAcc, maxDec; + asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_MAX_ACCEL, maxAcc); + if (asynSuccess != status) + return status; + status = getGCSParameter(pAxis, PI_PARA_MOT_MAX_DECEL, maxDec); + if (asynSuccess != status) + return status; + + if (maxAcc < maxDec) + { + pAxis->m_maxAcceleration = maxAcc; + } + else + { + pAxis->m_maxAcceleration = maxDec; + } + return status; } asynStatus PIGCSMotorController::setAcceleration( PIasynAxis* pAxis, double acceleration) { - asynStatus status = setGCSParameter(pAxis, PI_PARA_MOT_CURR_ACCEL, acceleration); - if (asynSuccess != status) - return status; - status = setGCSParameter(pAxis, PI_PARA_MOT_CURR_DECEL, acceleration); - if (asynSuccess != status) - return status; - pAxis->m_acceleration = acceleration; - return status; + if (!m_KnowsVELcommand) + { + return asynSuccess; + } + asynStatus status = setGCSParameter(pAxis, PI_PARA_MOT_CURR_ACCEL, acceleration); + if (asynSuccess != status) + return status; + status = setGCSParameter(pAxis, PI_PARA_MOT_CURR_DECEL, acceleration); + if (asynSuccess != status) + return status; + pAxis->m_acceleration = acceleration; + return status; } diff --git a/motorApp/PIGCS2Src/PIGCSMotorController.h b/motorApp/PIGCS2Src/PIGCSMotorController.h index 4731a3d..4c8430a 100644 --- a/motorApp/PIGCS2Src/PIGCSMotorController.h +++ b/motorApp/PIGCS2Src/PIGCSMotorController.h @@ -7,10 +7,6 @@ FILENAME... PIGCSMotorController.h * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 2$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 25.10.2013 10:43:08$ -HeadURL: $URL$ Original Author: Steffen Rau Created: 15.12.2010 diff --git a/motorApp/PIGCS2Src/PIGCSPiezoController.cpp b/motorApp/PIGCS2Src/PIGCSPiezoController.cpp index ab486fd..6578462 100644 --- a/motorApp/PIGCS2Src/PIGCSPiezoController.cpp +++ b/motorApp/PIGCS2Src/PIGCSPiezoController.cpp @@ -7,10 +7,6 @@ FILENAME... PIGCSPiezoController.cpp * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 3$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 25.10.2013 10:43:08$ -HeadURL: $URL$ Original Author: Steffen Rau Created: 15.12.2010 diff --git a/motorApp/PIGCS2Src/PIGCSPiezoController.h b/motorApp/PIGCS2Src/PIGCSPiezoController.h index b9b343e..19ce655 100644 --- a/motorApp/PIGCS2Src/PIGCSPiezoController.h +++ b/motorApp/PIGCS2Src/PIGCSPiezoController.h @@ -7,10 +7,6 @@ FILENAME... PIGCScontroller.h * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 3$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 25.10.2013 10:43:08$ -HeadURL: $URL$ Original Author: Steffen Rau Created: 15.12.2010 diff --git a/motorApp/PIGCS2Src/PIHexapodController.cpp b/motorApp/PIGCS2Src/PIHexapodController.cpp index 62e450c..a705cae 100644 --- a/motorApp/PIGCS2Src/PIHexapodController.cpp +++ b/motorApp/PIGCS2Src/PIHexapodController.cpp @@ -7,10 +7,6 @@ FILENAME... PIHexapodController.cpp * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 5$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 05.11.2013 17:38:32$ -HeadURL: $URL$ Original Author: Steffen Rau */ diff --git a/motorApp/PIGCS2Src/PIHexapodController.h b/motorApp/PIGCS2Src/PIHexapodController.h index 1dcdb4f..fc11048 100644 --- a/motorApp/PIGCS2Src/PIHexapodController.h +++ b/motorApp/PIGCS2Src/PIHexapodController.h @@ -7,10 +7,6 @@ FILENAME... PIHexapodController.h * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 3$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 05.11.2013 17:38:32$ -HeadURL: $URL$ Original Author: Steffen Rau */ diff --git a/motorApp/PIGCS2Src/PIInterface.cpp b/motorApp/PIGCS2Src/PIInterface.cpp index dbef790..f4ec484 100644 --- a/motorApp/PIGCS2Src/PIInterface.cpp +++ b/motorApp/PIGCS2Src/PIInterface.cpp @@ -7,10 +7,6 @@ FILENAME... PIInterface.cpp * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 1$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 25.10.2013 10:42:52$ -HeadURL: $URL$ Original Author: Steffen Rau Created: 15.12.2010 diff --git a/motorApp/PIGCS2Src/PIInterface.h b/motorApp/PIGCS2Src/PIInterface.h index 659b629..47538d7 100644 --- a/motorApp/PIGCS2Src/PIInterface.h +++ b/motorApp/PIGCS2Src/PIInterface.h @@ -7,10 +7,6 @@ FILENAME... PIInterface.h * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 1$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 25.10.2013 10:42:52$ -HeadURL: $URL$ Original Author: Steffen Rau Created: 15.12.2010 diff --git a/motorApp/PIGCS2Src/PI_GCS2Support.dbd b/motorApp/PIGCS2Src/PI_GCS2Support.dbd index 0252e01..8d3ca9e 100644 --- a/motorApp/PIGCS2Src/PI_GCS2Support.dbd +++ b/motorApp/PIGCS2Src/PI_GCS2Support.dbd @@ -1,5 +1,3 @@ -include "asyn.dbd" -include "motorRecord.dbd" ##device(motor,VME_IO,devPIasyn,"PI Motor GCS2") ##driver(PIasyn) registrar(PIasynDriverRegister) diff --git a/motorApp/PIGCS2Src/PIasynAxis.cpp b/motorApp/PIGCS2Src/PIasynAxis.cpp index 3dcd191..9539e89 100644 --- a/motorApp/PIGCS2Src/PIasynAxis.cpp +++ b/motorApp/PIGCS2Src/PIasynAxis.cpp @@ -8,10 +8,6 @@ USAGE... * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 4$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 25.10.2013 10:43:08$ -HeadURL: $URL$ Original Author: Steffen Rau @@ -86,7 +82,7 @@ void PIasynAxis::Init(const char *portName) } m_pGCSController->m_pInterface->m_pCurrentLogSink = logSink; - setIntegerParam(motorAxisHasClosedLoop, 1); + setIntegerParam(pController_->motorStatusGainSupport_, 1); m_pGCSController->initAxis(this); double resolution; diff --git a/motorApp/PIGCS2Src/PIasynAxis.h b/motorApp/PIGCS2Src/PIasynAxis.h index 1e3bc20..41e4fc8 100644 --- a/motorApp/PIGCS2Src/PIasynAxis.h +++ b/motorApp/PIGCS2Src/PIasynAxis.h @@ -8,10 +8,6 @@ USAGE... PI GCS Motor Support. * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 2$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 09.10.2013 16:34:01$ -HeadURL: $URL$ Original Author: Steffen Rau Created: January 2011 diff --git a/motorApp/PIGCS2Src/PIasynController.cpp b/motorApp/PIGCS2Src/PIasynController.cpp index a627876..ca9b0e1 100644 --- a/motorApp/PIGCS2Src/PIasynController.cpp +++ b/motorApp/PIGCS2Src/PIasynController.cpp @@ -8,10 +8,6 @@ USAGE... PI GCS2 Motor Support. * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 4$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 25.10.2013 10:43:08$ -HeadURL: $URL$ Original Author: Steffen Rau Created: January 2011 @@ -401,7 +397,7 @@ asynStatus PIasynController::configAxis(PIasynAxis *pAxis) } m_pGCSController->m_pInterface->m_pCurrentLogSink = logSink; - pAxis->setIntegerParam(motorAxisHasClosedLoop, 1); + pAxis->setIntegerParam(this->motorStatusGainSupport_, 1); pAxis->callParamCallbacks(); m_pGCSController->initAxis(pAxis); diff --git a/motorApp/PIGCS2Src/PIasynController.h b/motorApp/PIGCS2Src/PIasynController.h index 4c80e79..a6961b9 100644 --- a/motorApp/PIGCS2Src/PIasynController.h +++ b/motorApp/PIGCS2Src/PIasynController.h @@ -7,10 +7,6 @@ FILENAME... PIasynController.cpp * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 1$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 23.09.2013 14:19:03$ -HeadURL: $URL$ Based on drvMotorSim.c diff --git a/motorApp/PIGCS2Src/picontrollererrors.h b/motorApp/PIGCS2Src/picontrollererrors.h index 716ba99..c417346 100644 --- a/motorApp/PIGCS2Src/picontrollererrors.h +++ b/motorApp/PIGCS2Src/picontrollererrors.h @@ -7,10 +7,6 @@ FILENAME... picontrollererrors.h * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 1$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 23.09.2013 14:19:03$ -HeadURL: $URL$ Original Author: Steffen Rau, January 2011 */ diff --git a/motorApp/PIGCS2Src/translateerror.c b/motorApp/PIGCS2Src/translateerror.c index 5dee0e7..8c1828d 100644 --- a/motorApp/PIGCS2Src/translateerror.c +++ b/motorApp/PIGCS2Src/translateerror.c @@ -7,10 +7,6 @@ FILENAME... translateerror.c * found in the file LICENSE that is included with this distribution. ************************************************************************* -Version: $Revision: 1$ -Modified By: $Author: Steffen Rau$ -Last Modified: $Date: 23.09.2013 14:19:03$ -HeadURL: $URL$ Original Author: Steffen Rau */ diff --git a/motorApp/PhytronSrc/phytronAxisMotor.cpp b/motorApp/PhytronSrc/phytronAxisMotor.cpp index 95e5f28..3323124 100644 --- a/motorApp/PhytronSrc/phytronAxisMotor.cpp +++ b/motorApp/PhytronSrc/phytronAxisMotor.cpp @@ -5,10 +5,6 @@ USAGE... Motor driver support for Phytron Axis controller. Tom Slejko & Bor Marolt Cosylab d.d. 2014 -Version: $Revision: 18549 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2015-01-07 08:56:44 -0600 (Wed, 07 Jan 2015) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/PhytronSrc/phytronAxisMotor.cpp $ */ #include @@ -19,7 +15,9 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- #include #include #include +#ifndef _WIN32 #include +#endif #include #include diff --git a/motorApp/PhytronSrc/phytronAxisMotor.h b/motorApp/PhytronSrc/phytronAxisMotor.h index d048a1e..7315e69 100644 --- a/motorApp/PhytronSrc/phytronAxisMotor.h +++ b/motorApp/PhytronSrc/phytronAxisMotor.h @@ -5,10 +5,6 @@ USAGE... Motor record support for Phytron Axis controller. Tom Slejko & Bor Marolt Cosylab d.d. 2014 -Version: $Revision: 18549 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2015-01-07 08:56:44 -0600 (Wed, 07 Jan 2015) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/PhytronSrc/phytronAxisMotor.h $ */ #include "asynMotorController.h" diff --git a/motorApp/PiJenaSrc/PIJEDS_Register.cc b/motorApp/PiJenaSrc/PIJEDS_Register.cc index c9a4120..01967de 100644 --- a/motorApp/PiJenaSrc/PIJEDS_Register.cc +++ b/motorApp/PiJenaSrc/PIJEDS_Register.cc @@ -2,9 +2,6 @@ FILENAME... PIJEDS_Register.cc USAGE... Register piezosystem jena motor device driver shell commands. -Version: $Revision: 1.1 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2007-06-14 15:56:59 $ */ /***************************************************************** diff --git a/motorApp/PiJenaSrc/devPIJEDS.cc b/motorApp/PiJenaSrc/devPIJEDS.cc index c3f79a9..4ceb774 100644 --- a/motorApp/PiJenaSrc/devPIJEDS.cc +++ b/motorApp/PiJenaSrc/devPIJEDS.cc @@ -3,9 +3,6 @@ FILENAME... devPIJEDS.cc USAGE... Motor record device level support for Physik Instrumente (PI) GmbH & Co. E-516 motor controller. -Version: $Revision: 1.2 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-03-14 20:20:03 $ */ /* @@ -40,6 +37,7 @@ Last Modified: $Date: 2008-03-14 20:20:03 $ #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -50,7 +48,7 @@ extern struct driver_table PIJEDS_access; /* ----------------Create the dsets for devPIJEDS----------------- */ static struct driver_table *drvtabptr; -static long PIJEDS_init(void *); +static long PIJEDS_init(int); static long PIJEDS_init_record(void *); static long PIJEDS_start_trans(struct motorRecord *); static RTN_STATUS PIJEDS_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -104,12 +102,11 @@ static struct board_stat **PIJEDS_cards; /* initialize device support for PIJEDS stepper motor */ -static long PIJEDS_init(void *arg) +static long PIJEDS_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &PIJEDS_access; (drvtabptr->init)(); diff --git a/motorApp/PiJenaSrc/drvPIJEDS.cc b/motorApp/PiJenaSrc/drvPIJEDS.cc index aed0d63..9f18c38 100644 --- a/motorApp/PiJenaSrc/drvPIJEDS.cc +++ b/motorApp/PiJenaSrc/drvPIJEDS.cc @@ -3,10 +3,6 @@ FILENAME... drvPIJEDS.cc USAGE... Motor record driver level support for piezosystem jena GmbH & Co. E-516 motor controller. -Version: $Revision: 14155 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/PiJenaSrc/drvPIJEDS.cc $*/ /* * Original Author: Joe Sullivan @@ -48,6 +44,8 @@ DESIGN LIMITATIONS... #include #include #include +#include +#include #include "motorRecord.h" #include "motor.h" #include "drvPIJEDS.h" @@ -392,7 +390,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -614,7 +612,7 @@ static int motor_init() { online = false; /* Set Controller to ONLINE mode */ - send_mess(card_index, GET_IDENT, (char) NULL); + send_mess(card_index, GET_IDENT, (char*) NULL); if ((status = recv_mess(card_index, buff, 1))) online = (strstr(buff,"DSM")) ? true : false; else diff --git a/motorApp/PiSrc/Makefile b/motorApp/PiSrc/Makefile index b38e4d2..4a380b0 100644 --- a/motorApp/PiSrc/Makefile +++ b/motorApp/PiSrc/Makefile @@ -19,6 +19,7 @@ SRCS += devPIC862.cc drvPIC862.cc PIC862Register.cc SRCS += devPIC663.cc drvPIC663.cc PIC663Register.cc SRCS += devPIE710.cc drvPIE710.cc PIE710Register.cc SRCS += devPIE516.cc drvPIE516.cc PIE516Register.cc +SRCS += devPIE517.cc drvPIE517.cc PIE517Register.cc SRCS += devPIE816.cc drvPIE816.cc PIE816Register.cc diff --git a/motorApp/PiSrc/PIC662Register.cc b/motorApp/PiSrc/PIC662Register.cc index 1622ae1..b6f0a4f 100644 --- a/motorApp/PiSrc/PIC662Register.cc +++ b/motorApp/PiSrc/PIC662Register.cc @@ -2,9 +2,6 @@ FILENAME... PiRegister.cc USAGE... Register IMS motor device driver shell commands. -Version: $Revision: 1.1 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2006-04-14 20:34:42 $ */ /***************************************************************** diff --git a/motorApp/PiSrc/PIC848Register.cc b/motorApp/PiSrc/PIC848Register.cc index 92324e2..2f2712e 100644 --- a/motorApp/PiSrc/PIC848Register.cc +++ b/motorApp/PiSrc/PIC848Register.cc @@ -2,9 +2,6 @@ FILENAME... PIC848Register.cc USAGE... Register PI motor device driver shell commands. -Version: $Revision: 1.1 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2005-10-04 19:45:52 $ */ /***************************************************************** diff --git a/motorApp/PiSrc/PIE516Register.cc b/motorApp/PiSrc/PIE516Register.cc index 4ad14a9..8876211 100644 --- a/motorApp/PiSrc/PIE516Register.cc +++ b/motorApp/PiSrc/PIE516Register.cc @@ -2,9 +2,6 @@ FILENAME... PIE516Register.cc USAGE... Register PI motor device driver shell commands. -Version: $Revision: 1.1 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2007-03-30 20:01:05 $ */ /***************************************************************** diff --git a/motorApp/PiSrc/PIE517Register.cc b/motorApp/PiSrc/PIE517Register.cc new file mode 100755 index 0000000..63ea618 --- /dev/null +++ b/motorApp/PiSrc/PIE517Register.cc @@ -0,0 +1,68 @@ +/* +FILENAME... PIE517Register.cc +USAGE... Register PI motor device driver shell commands. + +Version: $Revision: 1.1 $ +Modified By: $Author: sullivan $ +Last Modified: $Date: 2007-03-30 20:01:05 $ +*/ + +/***************************************************************** + COPYRIGHT NOTIFICATION +***************************************************************** + +(C) COPYRIGHT 1993 UNIVERSITY OF CHICAGO + +This software was developed under a United States Government license +described on the COPYRIGHT_UniversityOfChicago file included as part +of this distribution. +**********************************************************************/ + +#include +#include +#include +#include +#include +#include "motor.h" +#include "drvPIE517.h" +#include "epicsExport.h" + +extern "C" +{ + +// Pi Setup arguments +static const iocshArg setupArg0 = {"Max. controller count", iocshArgInt}; +static const iocshArg setupArg1 = {"Polling rate", iocshArgInt}; +// Pi Config arguments +static const iocshArg configArg0 = {"Card being configured", iocshArgInt}; +static const iocshArg configArg1 = {"asyn port name", iocshArgString}; +static const iocshArg configArg2 = {"asyn address (GPIB)", iocshArgInt}; + +static const iocshArg * const PIE517SetupArgs[2] = {&setupArg0, &setupArg1}; +static const iocshArg * const PIE517ConfigArgs[3] = {&configArg0, &configArg1, + &configArg2}; + +static const iocshFuncDef setupPIE517 = {"PIE517Setup", 2, PIE517SetupArgs}; +static const iocshFuncDef configPIE517 = {"PIE517Config", 3, PIE517ConfigArgs}; + +static void setupPIE517CallFunc(const iocshArgBuf *args) +{ + PIE517Setup(args[0].ival, args[1].ival); +} + + +static void configPIE517CallFunc(const iocshArgBuf *args) +{ + PIE517Config(args[0].ival, args[1].sval, args[2].ival); +} + + +static void PIE517motorRegister(void) +{ + iocshRegister(&setupPIE517, setupPIE517CallFunc); + iocshRegister(&configPIE517, configPIE517CallFunc); +} + +epicsExportRegistrar(PIE517motorRegister); + +} // extern "C" diff --git a/motorApp/PiSrc/PIE710Register.cc b/motorApp/PiSrc/PIE710Register.cc index 5e6428a..04c50a7 100644 --- a/motorApp/PiSrc/PIE710Register.cc +++ b/motorApp/PiSrc/PIE710Register.cc @@ -2,9 +2,6 @@ FILENAME... PIE710Register.cc USAGE... Register PI motor device driver shell commands. -Version: $Revision: 1.1 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2006-10-06 18:18:21 $ */ /***************************************************************** diff --git a/motorApp/PiSrc/PiRegister.cc b/motorApp/PiSrc/PiRegister.cc index f1d744f..6483940 100644 --- a/motorApp/PiSrc/PiRegister.cc +++ b/motorApp/PiSrc/PiRegister.cc @@ -2,9 +2,6 @@ FILENAME... PiRegister.cc USAGE... Register IMS motor device driver shell commands. -Version: $Revision: 1.3 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2004-12-20 21:30:38 $ */ /***************************************************************** diff --git a/motorApp/PiSrc/devPIC630.cc b/motorApp/PiSrc/devPIC630.cc index b4b0470..95e7afb 100644 --- a/motorApp/PiSrc/devPIC630.cc +++ b/motorApp/PiSrc/devPIC630.cc @@ -50,7 +50,7 @@ extern struct driver_table PIC630_access; /* ----------------Create the dsets for devPIC630----------------- */ static struct driver_table *drvtabptr; -static long PIC630_init(void *); +static long PIC630_init(int); static long PIC630_init_record(void *); static long PIC630_start_trans(struct motorRecord *); static RTN_STATUS PIC630_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -102,13 +102,12 @@ static struct board_stat **PIC630_cards; /* initialize device support for PIC630 stepper motor */ -static long PIC630_init(void *arg) +static long PIC630_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; Debug(5, "PIC630_init: entry\n"); - if (after == 0) + if (!after) { drvtabptr = &PIC630_access; (drvtabptr->init)(); diff --git a/motorApp/PiSrc/devPIC662.cc b/motorApp/PiSrc/devPIC662.cc index 713e0ca..9226fc9 100644 --- a/motorApp/PiSrc/devPIC662.cc +++ b/motorApp/PiSrc/devPIC662.cc @@ -3,9 +3,6 @@ FILENAME... devPIC662.cc USAGE... Motor record device level support for Physik Instrumente (PI) GmbH & Co. C-844 motor controller. -Version: $Revision: 1.2 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-03-14 20:21:36 $ */ /* @@ -40,6 +37,7 @@ Last Modified: $Date: 2008-03-14 20:21:36 $ #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -50,7 +48,7 @@ extern struct driver_table PIC662_access; /* ----------------Create the dsets for devPIC662----------------- */ static struct driver_table *drvtabptr; -static long PIC662_init(void *); +static long PIC662_init(int); static long PIC662_init_record(void *); static long PIC662_start_trans(struct motorRecord *); static RTN_STATUS PIC662_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -104,12 +102,11 @@ static struct board_stat **PIC662_cards; /* initialize device support for PIC662 stepper motor */ -static long PIC662_init(void *arg) +static long PIC662_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &PIC662_access; (drvtabptr->init)(); diff --git a/motorApp/PiSrc/devPIC663.cc b/motorApp/PiSrc/devPIC663.cc index f85c918..4843a4e 100644 --- a/motorApp/PiSrc/devPIC663.cc +++ b/motorApp/PiSrc/devPIC663.cc @@ -15,6 +15,8 @@ USAGE... Motor record device level support for Physik Instrumente (PI) #include #include +#include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -25,7 +27,7 @@ extern struct driver_table PIC663_access; /* ----------------Create the dsets for devPIC663----------------- */ static struct driver_table *drvtabptr; -static long PIC663_init(void *); +static long PIC663_init(int); static long PIC663_init_record(void *); static long PIC663_start_trans(struct motorRecord *); static RTN_STATUS PIC663_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -79,12 +81,11 @@ static struct board_stat **PIC663_cards; /* initialize device support for PIC663 servo motor */ -static long PIC663_init(void *arg) +static long PIC663_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &PIC663_access; (drvtabptr->init)(); diff --git a/motorApp/PiSrc/devPIC844.cc b/motorApp/PiSrc/devPIC844.cc index f566004..429c101 100644 --- a/motorApp/PiSrc/devPIC844.cc +++ b/motorApp/PiSrc/devPIC844.cc @@ -3,9 +3,6 @@ FILENAME... devPIC844.cc USAGE... Motor record device level support for Physik Instrumente (PI) GmbH & Co. C-844 motor controller. -Version: $Revision: 1.6 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-03-14 20:21:36 $ */ /* @@ -41,6 +38,7 @@ Last Modified: $Date: 2008-03-14 20:21:36 $ #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -50,7 +48,7 @@ extern struct driver_table PIC844_access; /* ----------------Create the dsets for devPIC844----------------- */ static struct driver_table *drvtabptr; -static long PIC844_init(void *); +static long PIC844_init(int); static long PIC844_init_record(void *); static long PIC844_start_trans(struct motorRecord *); static RTN_STATUS PIC844_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -104,12 +102,11 @@ static struct board_stat **PIC844_cards; /* initialize device support for PIC844 stepper motor */ -static long PIC844_init(void *arg) +static long PIC844_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &PIC844_access; (drvtabptr->init)(); diff --git a/motorApp/PiSrc/devPIC848.cc b/motorApp/PiSrc/devPIC848.cc index e3c62bf..74800db 100644 --- a/motorApp/PiSrc/devPIC848.cc +++ b/motorApp/PiSrc/devPIC848.cc @@ -3,9 +3,6 @@ FILENAME... devPIC848.cc USAGE... Motor record device level support for Physik Instrumente (PI) GmbH & Co. C-848 motor controller. -Version: $Revision: 1.3 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-03-14 20:21:37 $ */ /* @@ -44,6 +41,7 @@ Last Modified: $Date: 2008-03-14 20:21:37 $ #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -54,7 +52,7 @@ extern struct driver_table PIC848_access; /* ----------------Create the dsets for devPIC848----------------- */ static struct driver_table *drvtabptr; -static long PIC848_init(void *); +static long PIC848_init(int); static long PIC848_init_record(void *); static long PIC848_start_trans(struct motorRecord *); static RTN_STATUS PIC848_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -108,12 +106,11 @@ static struct board_stat **PIC848_cards; /* initialize device support for PIC848 stepper motor */ -static long PIC848_init(void *arg) +static long PIC848_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &PIC848_access; (drvtabptr->init)(); diff --git a/motorApp/PiSrc/devPIC862.cc b/motorApp/PiSrc/devPIC862.cc index e4bfa67..bbd9272 100644 --- a/motorApp/PiSrc/devPIC862.cc +++ b/motorApp/PiSrc/devPIC862.cc @@ -19,6 +19,8 @@ USAGE... Motor record device level support for Physik Instrumente (PI) #include #include +#include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -29,7 +31,7 @@ extern struct driver_table PIC862_access; /* ----------------Create the dsets for devPIC862----------------- */ static struct driver_table *drvtabptr; -static long PIC862_init(void *); +static long PIC862_init(int); static long PIC862_init_record(void *); static long PIC862_start_trans(struct motorRecord *); static RTN_STATUS PIC862_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -83,12 +85,11 @@ static struct board_stat **PIC862_cards; /* initialize device support for PIC862 servo motor */ -static long PIC862_init(void *arg) +static long PIC862_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &PIC862_access; (drvtabptr->init)(); diff --git a/motorApp/PiSrc/devPIE516.cc b/motorApp/PiSrc/devPIE516.cc index e70afd9..1aef91b 100644 --- a/motorApp/PiSrc/devPIE516.cc +++ b/motorApp/PiSrc/devPIE516.cc @@ -3,9 +3,6 @@ FILENAME... devPIE516.cc USAGE... Motor record device level support for Physik Instrumente (PI) GmbH & Co. E-516 motor controller. -Version: $Revision: 1.2 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-03-14 20:21:37 $ */ /* @@ -41,6 +38,7 @@ Last Modified: $Date: 2008-03-14 20:21:37 $ #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -51,7 +49,7 @@ extern struct driver_table PIE516_access; /* ----------------Create the dsets for devPIE516----------------- */ static struct driver_table *drvtabptr; -static long PIE516_init(void *); +static long PIE516_init(int); static long PIE516_init_record(void *); static long PIE516_start_trans(struct motorRecord *); static RTN_STATUS PIE516_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -105,12 +103,11 @@ static struct board_stat **PIE516_cards; /* initialize device support for PIE516 stepper motor */ -static long PIE516_init(void *arg) +static long PIE516_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &PIE516_access; (drvtabptr->init)(); diff --git a/motorApp/PiSrc/devPIE517.cc b/motorApp/PiSrc/devPIE517.cc new file mode 100755 index 0000000..701fd4e --- /dev/null +++ b/motorApp/PiSrc/devPIE517.cc @@ -0,0 +1,317 @@ +/* +FILENAME... devPIE517.cc +USAGE... Motor record device level support for Physik Instrumente (PI) + GmbH & Co. E-516 motor controller. + +Version: $Revision: 1.2 $ +Modified By: $Author: sluiter $ +Last Modified: $Date: 2008-03-14 20:21:37 $ +*/ + +/* + * Original Author: Ron Sluiter + * Date: 12/17/03 + * Current Author: Joe Sullivan + * + * 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 08/10/16 Bruno Luvizotto (brunoluvizotto@gmail.com) - copied from devPIE516.cc + * .02 08/10/16 Bruno Luvizotto (brunoluvizotto@gmail.com) - edited the files for the E517 controller + */ + + +#include +#include +#include +#include "motorRecord.h" +#include "motor.h" +#include "motordevCom.h" +#include "drvPIE517.h" +#include "epicsExport.h" + +extern struct driver_table PIE517_access; + +/* ----------------Create the dsets for devPIE517----------------- */ +static struct driver_table *drvtabptr; +static long PIE517_init(int); +static long PIE517_init_record(void *); +static long PIE517_start_trans(struct motorRecord *); +static RTN_STATUS PIE517_build_trans(motor_cmnd, double *, struct motorRecord *); +static RTN_STATUS PIE517_end_trans(struct motorRecord *); + +struct motor_dset devPIE517 = +{ + {8, NULL, (DEVSUPFUN) PIE517_init, (DEVSUPFUN) PIE517_init_record, NULL}, + motor_update_values, + PIE517_start_trans, + PIE517_build_trans, + PIE517_end_trans +}; + +extern "C" {epicsExportAddress(dset,devPIE517);} + +/* --------------------------- program data --------------------- */ + +/* This table is used to define the command types */ +/* WARNING! this must match "motor_cmnd" in motor.h */ + +static msg_types PIE517_table[] = { + MOTION, /* MOVE_ABS */ + MOTION, /* MOVE_REL */ + MOTION, /* HOME_FOR */ + MOTION, /* HOME_REV */ + IMMEDIATE, /* LOAD_POS */ + IMMEDIATE, /* SET_VEL_BASE */ + IMMEDIATE, /* SET_VELOCITY */ + IMMEDIATE, /* SET_ACCEL */ + IMMEDIATE, /* GO */ + IMMEDIATE, /* SET_ENC_RATIO */ + INFO, /* GET_INFO */ + MOVE_TERM, /* STOP_AXIS */ + VELOCITY, /* JOG */ + IMMEDIATE, /* SET_PGAIN */ + IMMEDIATE, /* SET_IGAIN */ + IMMEDIATE, /* SET_DGAIN */ + IMMEDIATE, /* ENABLE_TORQUE */ + IMMEDIATE, /* DISABL_TORQUE */ + IMMEDIATE, /* PRIMITIVE */ + IMMEDIATE, /* SET_HIGH_LIMIT */ + IMMEDIATE, /* SET_LOW_LIMIT */ + VELOCITY /* JOG_VELOCITY */ +}; + + +static struct board_stat **PIE517_cards; + +/* --------------------------- program data --------------------- */ + + +/* initialize device support for PIE517 stepper motor */ +static long PIE517_init(int after) +{ + long rtnval; + + if (!after) + { + drvtabptr = &PIE517_access; + (drvtabptr->init)(); + } + + rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &PIE517_cards); + return(rtnval); +} + + +/* initialize a record instance */ +static long PIE517_init_record(void *arg) +{ + struct motorRecord *mr = (struct motorRecord *) arg; + /* Disable change of direction testing in record support */ + /* This is a closed-loop device */ + mr->ntm = menuYesNoNO; + return(motor_init_record_com(mr, *drvtabptr->cardcnt_ptr, drvtabptr, PIE517_cards)); +} + + +/* start building a transaction */ +static long PIE517_start_trans(struct motorRecord *mr) +{ + motor_start_trans_com(mr, PIE517_cards); + return(OK); +} + + +/* end building a transaction */ +static RTN_STATUS PIE517_end_trans(struct motorRecord *mr) +{ + motor_end_trans_com(mr, drvtabptr); + return(OK); +} + + +/* add a part to the transaction */ +static RTN_STATUS PIE517_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 PIE517controller *cntrl; + char buff[110]; + int card, maxdigits; + unsigned int size; + double dval, cntrl_units, res; + RTN_STATUS rtnval; + bool send; + + send = true; /* Default to send motor command. */ + rtnval = OK; + buff[0] = '\0'; + + /* Protect against NULL pointer with WRTITE_MSG(GO/STOP_AXIS/GET_INFO, NULL). */ + dval = (parms == NULL) ? 0.0 : *parms; + + rtnval = (RTN_STATUS) motor_start_trans_com(mr, PIE517_cards); + + motor_call = &(trans->motor_call); + card = motor_call->card; + brdptr = (*trans->tabptr->card_array)[card]; + if (brdptr == NULL) + return(rtnval = ERROR); + + cntrl = (struct PIE517controller *) brdptr->DevicePrivate; + res = cntrl->drive_resolution[motor_call->signal]; + cntrl_units = dval; + maxdigits = 3; + + if (PIE517_table[command] > motor_call->type) + motor_call->type = PIE517_table[command]; + + if (trans->state != BUILD_STATE) + return(rtnval = ERROR); + + if (command == PRIMITIVE && mr->init != NULL && strlen(mr->init) != 0) + strcat(motor_call->message, mr->init); + + switch (command) + { + case MOVE_ABS: + case MOVE_REL: + case HOME_FOR: + case HOME_REV: + case JOG: + if (strlen(mr->prem) != 0) + { + strcat(motor_call->message, mr->prem); + strcat(motor_call->message, EOL_E517); + } + if (strlen(mr->post) != 0) + motor_call->postmsgptr = (char *) &mr->post; + break; + + default: + break; + } + + + switch (command) + { + case MOVE_ABS: + sprintf(buff, "MOV # %.*f", maxdigits, (cntrl_units * res)); + strcat(buff, EOL_E517); + break; + + case MOVE_REL: + sprintf(buff, "MVR # %.*f", maxdigits, (cntrl_units * res)); + strcat(buff, EOL_E517); + break; + + case HOME_FOR: + case HOME_REV: + rtnval = ERROR; + break; + + case LOAD_POS: + rtnval = ERROR; + break; + + case SET_VEL_BASE: + send = false; /* DC motor; not base velocity. */ + break; + + case SET_VELOCITY: + sprintf(buff, "VEL # %.*f", maxdigits, (cntrl_units * res)); + strcat(buff, EOL_E517); + break; + + case ENABLE_TORQUE: + strcpy(buff, "SVO #1"); + strcat(buff, EOL_E517); + break; + + case DISABL_TORQUE: + strcpy(buff, "SVO #0"); + strcat(buff, EOL_E517); + break; + + case SET_ACCEL: + /* The PIE517 does not support acceleration commands. */ + case GO: + /* The PIE517 starts moving immediately on move commands, GO command + * does nothing. */ + send = false; + break; + + case PRIMITIVE: + case GET_INFO: + /* These commands are not actually done by sending a message, but + rather they will indirectly cause the driver to read the status + of all motors */ + break; + + case STOP_AXIS: + /* No stop command available - use move relative 0 */ + sprintf(buff, "STP #"); + strcat(buff, EOL_E517); + break; + + case JOG_VELOCITY: + case JOG: + sprintf(buff, "VEL # %.*f", maxdigits, cntrl_units); + strcat(buff, EOL_E517); + break; + + case SET_PGAIN: + send = false; + break; + case SET_IGAIN: + send = false; + break; + case SET_DGAIN: + send = false; + break; + + case SET_HIGH_LIMIT: + case SET_LOW_LIMIT: + case SET_ENC_RATIO: + trans->state = IDLE_STATE; /* No command sent to the controller. */ + send = false; + break; + + default: + send = false; + rtnval = ERROR; + } + + size = strlen(buff); + if (send == false) + return(rtnval); + else if (size > sizeof(buff) || (strlen(motor_call->message) + size) > MAX_MSG_SIZE) + errlogMessage("PIE517_build_trans(): buffer overflow.\n"); + else + { + strcat(motor_call->message, buff); + rtnval = motor_end_trans_com(mr, drvtabptr); + } + return(rtnval); +} diff --git a/motorApp/PiSrc/devPIE710.cc b/motorApp/PiSrc/devPIE710.cc index 636eb21..cde406e 100644 --- a/motorApp/PiSrc/devPIE710.cc +++ b/motorApp/PiSrc/devPIE710.cc @@ -3,9 +3,6 @@ FILENAME... devPIE710.cc USAGE... Motor record device level support for Physik Instrumente (PI) GmbH & Co. E-710 motor controller. -Version: $Revision: 1.3 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-03-14 20:21:36 $ */ /* @@ -41,6 +38,7 @@ Last Modified: $Date: 2008-03-14 20:21:36 $ #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -51,7 +49,7 @@ extern struct driver_table PIE710_access; /* ----------------Create the dsets for devPIE710----------------- */ static struct driver_table *drvtabptr; -static long PIE710_init(void *); +static long PIE710_init(int); static long PIE710_init_record(void *); static long PIE710_start_trans(struct motorRecord *); static RTN_STATUS PIE710_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -105,12 +103,11 @@ static struct board_stat **PIE710_cards; /* initialize device support for PIE710 stepper motor */ -static long PIE710_init(void *arg) +static long PIE710_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &PIE710_access; (drvtabptr->init)(); diff --git a/motorApp/PiSrc/devPIE816.cc b/motorApp/PiSrc/devPIE816.cc index ff6ca3d..5651251 100644 --- a/motorApp/PiSrc/devPIE816.cc +++ b/motorApp/PiSrc/devPIE816.cc @@ -41,6 +41,7 @@ Last Modified: 2007/03/30 20:01:05 #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -51,7 +52,7 @@ extern struct driver_table PIE816_access; /* ----------------Create the dsets for devPIE816----------------- */ static struct driver_table *drvtabptr; -static long PIE816_init(void *); +static long PIE816_init(int); static long PIE816_init_record(void *); static long PIE816_start_trans(struct motorRecord *); static RTN_STATUS PIE816_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -105,12 +106,11 @@ static struct board_stat **PIE816_cards; /* initialize device support for PIE816 stepper motor */ -static long PIE816_init(void *arg) +static long PIE816_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &PIE816_access; (drvtabptr->init)(); diff --git a/motorApp/PiSrc/devPIMotor.dbd b/motorApp/PiSrc/devPIMotor.dbd index 6758499..04e0c06 100644 --- a/motorApp/PiSrc/devPIMotor.dbd +++ b/motorApp/PiSrc/devPIMotor.dbd @@ -46,6 +46,12 @@ driver(drvPIE516) registrar(PIE516motorRegister) variable(drvPIE516debug) +# Physik Instrumente (PI) GmbH & Co. E-517 driver support. +device(motor,VME_IO,devPIE517,"PIE517") +driver(drvPIE517) +registrar(PIE517motorRegister) +variable(drvPIE517debug) + # Physik Instrumente (PI) GmbH & Co. E-816 driver support. device(motor,VME_IO,devPIE816,"PIE816") driver(drvPIE816) diff --git a/motorApp/PiSrc/drvPI.h b/motorApp/PiSrc/drvPI.h index 947b9e2..0de27ed 100644 --- a/motorApp/PiSrc/drvPI.h +++ b/motorApp/PiSrc/drvPI.h @@ -3,9 +3,6 @@ FILENAME... drvPI.h USAGE... This file contains driver "include" information that is specific to Physik Instrumente (PI) GmbH & Co. motor controller driver support. -Version: $Revision: 1.3 $ -Modified By: $Author: rivers $ -Last Modified: $Date: 2004-08-17 21:29:52 $ */ /* diff --git a/motorApp/PiSrc/drvPIC630.cc b/motorApp/PiSrc/drvPIC630.cc index a01bbeb..d222c6e 100644 --- a/motorApp/PiSrc/drvPIC630.cc +++ b/motorApp/PiSrc/drvPIC630.cc @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "motor.h" #include "drvPIC630.h" #include "asynOctetSyncIO.h" diff --git a/motorApp/PiSrc/drvPIC662.cc b/motorApp/PiSrc/drvPIC662.cc index 1a3b175..9300421 100644 --- a/motorApp/PiSrc/drvPIC662.cc +++ b/motorApp/PiSrc/drvPIC662.cc @@ -3,9 +3,6 @@ FILENAME... drvPIC662.cc USAGE... Motor record driver level support for Physik Instrumente (PI) GmbH & Co. C-844 motor controller. -Version: $Revision: 1.1 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2006-04-14 20:34:42 $ */ /* @@ -51,6 +48,8 @@ DESIGN LIMITATIONS... #include #include #include +#include +#include #include "motor.h" #include "drvPIC662.h" #include "epicsExport.h" @@ -232,7 +231,7 @@ static int set_status(int card, int signal) nodeptr = motor_info->motor_motion; status.All = motor_info->status.All; - send_mess(card, GET_STATUS, (char) NULL); + send_mess(card, GET_STATUS, (char*) NULL); comm_status = recv_mess(card, buff, 1); if (comm_status == 0) { @@ -271,7 +270,7 @@ static int set_status(int card, int signal) * Skip to substring for this motor, convert to double */ - send_mess(card, GET_POS, (char) NULL); + send_mess(card, GET_POS, (char*) NULL); recv_mess(card, buff, 1); motorData = NINT (atof(buff) / cntrl->drive_resolution); @@ -340,7 +339,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -539,7 +538,7 @@ static int motor_init() do { - send_mess(card_index, GET_IDENT, (char) NULL); + send_mess(card_index, GET_IDENT, (char*) NULL); status = recv_mess(card_index, buff, 1); retry++; } while (status == 0 && retry < 3); @@ -558,7 +557,7 @@ static int motor_init() /* Set Controller to REMOTE mode */ - send_mess(card_index, REMOTE_MODE, (char) NULL); + send_mess(card_index, REMOTE_MODE, (char*) NULL); { struct mess_info *motor_info = &brdptr->motor_info[0]; diff --git a/motorApp/PiSrc/drvPIC662.h b/motorApp/PiSrc/drvPIC662.h index f45d40c..1d67e9d 100644 --- a/motorApp/PiSrc/drvPIC662.h +++ b/motorApp/PiSrc/drvPIC662.h @@ -3,9 +3,6 @@ FILENAME... drvPIC662.h USAGE... This file contains driver "include" information that is specific to Physik Instrumente (PI) GmbH & Co. motor controller driver support. -Version: $Revision: 1.1 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2006-04-14 20:34:42 $ */ /* diff --git a/motorApp/PiSrc/drvPIC663.cc b/motorApp/PiSrc/drvPIC663.cc index 666130f..532494f 100644 --- a/motorApp/PiSrc/drvPIC663.cc +++ b/motorApp/PiSrc/drvPIC663.cc @@ -22,6 +22,8 @@ DESIGN LIMITATIONS... #include #include #include +#include +#include #include "motorRecord.h" #include "motor.h" #include "drvPIC663.h" @@ -212,7 +214,7 @@ static int set_status(int card, int signal) if (cntrl->status != NORMAL) charcnt = recv_mess(card, buff, FLUSH); - send_mess(card, "TS", (char) NULL); /* Tell Status */ + send_mess(card, "TS", (char*) NULL); /* Tell Status */ charcnt = recv_mess(card, buff, 1); if (charcnt > 9) convert_cnt = sscanf(buff, "S:%2hx %2hx %2hx\n", @@ -253,7 +255,7 @@ static int set_status(int card, int signal) minusLS = mstat2.Bits.lo_limit ? 0 : 1; /* Parse motor position */ - send_mess(card, "TP", (char) NULL); /* Tell Position */ + send_mess(card, "TP", (char*) NULL); /* Tell Position */ recv_mess(card, buff, 1); motorData = NINT(atof(&buff[2])); @@ -307,7 +309,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -519,7 +521,7 @@ static int motor_init() do { sprintf(buff,"\001%1XVE", cntrl->asyn_address); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); status = recv_mess(card_index, buff, 1); retry++; } while (status == 0 && retry < 3); diff --git a/motorApp/PiSrc/drvPIC844.cc b/motorApp/PiSrc/drvPIC844.cc index 0de16ba..ae87380 100644 --- a/motorApp/PiSrc/drvPIC844.cc +++ b/motorApp/PiSrc/drvPIC844.cc @@ -3,9 +3,6 @@ FILENAME... drvPIC844.cc USAGE... Motor record driver level support for Physik Instrumente (PI) GmbH & Co. C-844 motor controller. -Version: $Revision: 1.15 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2006-01-31 22:10:04 $ */ /* @@ -61,6 +58,8 @@ DESIGN LIMITATIONS... #include #include #include +#include +#include #include "motor.h" #include "drvPI.h" #include "epicsExport.h" @@ -265,7 +264,7 @@ static int set_status(int card, int signal) cntrl->status = NORMAL; status.Bits.CNTRL_COMM_ERR = 0; - send_mess(card, "MOT:COND?", (char) NULL); + send_mess(card, "MOT:COND?", (char*) NULL); recv_mess(card, buff, 1); mstat.All = atoi(&buff[0]); @@ -296,7 +295,7 @@ static int set_status(int card, int signal) * Skip to substring for this motor, convert to double */ - send_mess(card, "CURR:TPOS?", (char) NULL); + send_mess(card, "CURR:TPOS?", (char*) NULL); recv_mess(card, buff, 1); motorData = atof(buff); @@ -365,7 +364,7 @@ static int set_status(int card, int signal) status.Bits.EA_SLIP_STALL = 0; status.Bits.EA_HOME = 0; - send_mess(card, "AXIS:POS?", (char) NULL); + send_mess(card, "AXIS:POS?", (char*) NULL); recv_mess(card, buff, 1); motorData = atof(buff); motor_info->encoder_position = (epicsInt32) motorData; @@ -388,7 +387,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -597,7 +596,7 @@ static int motor_init() do { - send_mess(card_index, GET_IDENT, (char) NULL); + send_mess(card_index, GET_IDENT, (char*) NULL); status = recv_mess(card_index, buff, 1); retry++; } while (status == 0 && retry < 3); diff --git a/motorApp/PiSrc/drvPIC848.cc b/motorApp/PiSrc/drvPIC848.cc index 86a8952..8aba08c 100644 --- a/motorApp/PiSrc/drvPIC848.cc +++ b/motorApp/PiSrc/drvPIC848.cc @@ -3,10 +3,6 @@ FILENAME... drvPIC848.cc USAGE... Motor record driver level support for Physik Instrumente (PI) GmbH & Co. C-848 motor controller. -Version: $Revision: 14157 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-11-29 15:52:25 -0600 (Tue, 29 Nov 2011) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/PiSrc/drvPIC848.cc $ */ /* @@ -50,6 +46,8 @@ DESIGN LIMITATIONS... #include #include #include +#include +#include #include "motorRecord.h" #include "motor.h" #include "drvPIC848.h" @@ -343,7 +341,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -550,7 +548,7 @@ static int motor_init() do { - send_mess(card_index, GET_IDENT, (char) NULL); + send_mess(card_index, GET_IDENT, (char*) NULL); status = recv_mess(card_index, buff, 1); retry++; } while (status == 0 && retry < 3); diff --git a/motorApp/PiSrc/drvPIC862.cc b/motorApp/PiSrc/drvPIC862.cc index a650f4e..241e008 100644 --- a/motorApp/PiSrc/drvPIC862.cc +++ b/motorApp/PiSrc/drvPIC862.cc @@ -31,6 +31,8 @@ DESIGN LIMITATIONS... #include #include #include +#include +#include #include "motorRecord.h" #include "motor.h" #include "drvPIC862.h" @@ -223,7 +225,7 @@ static int set_status(int card, int signal) if (cntrl->status != NORMAL) charcnt = recv_mess(card, buff, FLUSH); - send_mess(card, "TS", (char) NULL); /* Tell Status */ + send_mess(card, "TS", (char*) NULL); /* Tell Status */ charcnt = recv_mess(card, buff, 1); if (charcnt > 18) convert_cnt = sscanf(buff, "S:%2hx %2hx %2hx %2hx %2hx %2hx\n", @@ -279,7 +281,7 @@ static int set_status(int card, int signal) /* Parse motor position */ - send_mess(card, "TP", (char) NULL); /* Tell Position */ + send_mess(card, "TP", (char*) NULL); /* Tell Position */ recv_mess(card, buff, 1); motorData = NINT(atof(&buff[2])); @@ -333,7 +335,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -545,7 +547,7 @@ static int motor_init() do { sprintf(buff,"\001%1XVE", cntrl->asyn_address); - send_mess(card_index, buff, (char) NULL); + send_mess(card_index, buff, (char*) NULL); status = recv_mess(card_index, buff, 1); retry++; } while (status == 0 && retry < 3); diff --git a/motorApp/PiSrc/drvPIE516.cc b/motorApp/PiSrc/drvPIE516.cc index d8f8be5..847db29 100644 --- a/motorApp/PiSrc/drvPIE516.cc +++ b/motorApp/PiSrc/drvPIE516.cc @@ -3,9 +3,6 @@ FILENAME... drvPIE516.cc USAGE... Motor record driver level support for Physik Instrumente (PI) GmbH & Co. E-516 motor controller. -Version: $Revision: 1.1 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2007-03-30 20:01:05 $ */ /* @@ -48,6 +45,8 @@ DESIGN LIMITATIONS... #include #include #include +#include +#include #include "motorRecord.h" #include "motor.h" #include "drvPIE516.h" @@ -244,14 +243,14 @@ static int set_status(int card, int signal) recv_mess(card, buff, FLUSH); readOK = false; - send_mess(card, READ_ONLINE, (char) NULL); + send_mess(card, READ_ONLINE, (char*) NULL); if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &online_status)) { if (!online_status) { /* Assume Controller Reboot - Set ONLINE and Velocity Control ON */ - send_mess(card, SET_ONLINE, (char) NULL); - send_mess(card, SET_VELCTRL, (char) NULL); + send_mess(card, SET_ONLINE, (char*) NULL); + send_mess(card, SET_VELCTRL, (char*) NULL); } send_mess(card, READ_ONTARGET, PIE516_axis[signal]); @@ -368,7 +367,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -586,15 +585,15 @@ static int motor_init() { online = false; /* Set Controller to ONLINE mode */ - send_mess(card_index, SET_ONLINE, (char) NULL); - send_mess(card_index, READ_ONLINE, (char) NULL); + send_mess(card_index, SET_ONLINE, (char*) NULL); + send_mess(card_index, READ_ONLINE, (char*) NULL); if ((status = recv_mess(card_index, buff, 1))) online = (atoi(buff)==1) ? true : false; else retry++; } while (online == false && retry < 3); - send_mess(card_index, GET_IDENT, (char) NULL); + send_mess(card_index, GET_IDENT, (char*) NULL); status = recv_mess(card_index, buff, 1); /* Parse out E516 revision (2 decimal places) and convert to int */ @@ -627,7 +626,7 @@ static int motor_init() brdptr->total_axis = total_axis; /* Turn ON velocity control mode - All axis */ - send_mess(card_index, SET_VELCTRL, (char) NULL); + send_mess(card_index, SET_VELCTRL, (char*) NULL); for (motor_index = 0; motor_index < total_axis; motor_index++) { diff --git a/motorApp/PiSrc/drvPIE517.cc b/motorApp/PiSrc/drvPIE517.cc new file mode 100755 index 0000000..c82b3d9 --- /dev/null +++ b/motorApp/PiSrc/drvPIE517.cc @@ -0,0 +1,682 @@ +/* +FILENAME... drvPIE517.cc +USAGE... Motor record driver level support for Physik Instrumente (PI) + GmbH & Co. E-516 motor controller. + +Version: $Revision: 1.1 $ +Modified By: $Author: sullivan $ +Last Modified: $Date: 2007-03-30 20:01:05 $ +*/ + +/* + * Original Author: Ron Sluiter + * Date: 10/18/05 + * Current Author: Joe Sullivan + * + * 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 08/10/16 Bruno Luvizotto (brunoluvizotto@gmail.com) - copied from devPIE516.cc. + * .02 08/10/16 Bruno Luvizotto (brunoluvizotto@gmail.com) - edited the files for the E517 controller. + * Tested on PI VER: + * FW_DSP: 02.034 + * FW_FPGA: 02.040 + * FW_MCU: 1.22.6 + */ + +/* +DESIGN LIMITATIONS... + 1 - Like all controllers, the PIE517 must be powered-on when EPICS is first + booted up. +*/ + +#include +#include +#include +#include +#include +#include "motorRecord.h" +#include "motor.h" +#include "drvPIE517.h" +#include "epicsExport.h" + +#define GET_IDENT "VER?" +#define SET_ONLINE "ONL # 1" /* Set Online Mode ON */ +#define SET_VELCTRL "VCO # 1" /* Set Velocity Control Mode - Required for DONE */ +#define READ_ONLINE "ONL? #" /* Read Online Mode */ +#define READ_POS "POS? #" /* Read position */ +#define READ_OVERFLOW "OVF? #" /* Read Servo Overflow Status */ +#define READ_ONTARGET "ONT? #" /* Read Position ON Target */ +#define READ_SERVO "SVO? #" /* Read Servo Enable Status */ + + +#define PIE517_NUM_CARDS 10 +#define MAX_AXES 3 +#define BUFF_SIZE 100 /* Maximum length of string to/from PIE517 */ + +/*----------------debugging-----------------*/ +volatile int drvPIE517debug = 0; +extern "C" {epicsExportAddress(int, drvPIE517debug);} +static inline void Debug(int level, const char *format, ...) { + #ifdef DEBUG + if (level < drvPIE517debug) { + va_list pVar; + va_start(pVar, format); + vprintf(format, pVar); + va_end(pVar); + } + #endif +} + +/* --- Local data. --- */ +int PIE517_num_cards = 0; +static char *PIE517_axis[] = {"1 ", "2 ", "3 "}; //{"A", "B", "C"}; + +/* Local data required for every driver; see "motordrvComCode.h" */ +#include "motordrvComCode.h" + + +/*----------------functions-----------------*/ +static int recv_mess(int, char *, int); +static RTN_STATUS send_mess(int, char const *, char *); +static int set_status(int, int); +static long report(int); +static long init(); +static int motor_init(); +static void query_done(int, int, struct mess_node *); + +/*----------------functions-----------------*/ + +struct driver_table PIE517_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, + NULL, + &initialized, + PIE517_axis +}; + +struct +{ + long number; + long (*report) (int); + long (*init) (void); +} drvPIE517 = {2, report, init}; + +extern "C" {epicsExportAddress(drvet, drvPIE517);} + +static struct thread_args targs = {SCAN_RATE, &PIE517_access, 0.0}; + +/********************************************************* + * Print out driver status report + *********************************************************/ +static long report(int level) +{ + int card; + + if (PIE517_num_cards <=0) + printf(" No PIE517 controllers configured.\n"); + else + { + for (card = 0; card < PIE517_num_cards; card++) + { + struct controller *brdptr = motor_state[card]; + + if (brdptr == NULL) + printf(" PIE517 controller %d connection failed.\n", card); + else + { + struct PIE517controller *cntrl; + + cntrl = (struct PIE517controller *) brdptr->DevicePrivate; + printf(" PIE517 controller #%d, port=%s, id: %s \n", card, + cntrl->asyn_port, brdptr->ident); + } + } + } + return(OK); +} + + +static long init() +{ + /* + * We cannot call motor_init() here, because that function can do GPIB I/O, + * and hence requires that the drvGPIB have already been initialized. + * That cannot be guaranteed, so we need to call motor_init from device + * support + */ + /* Check for setup */ + if (PIE517_num_cards <= 0) + { + Debug(1, "init(): PIE517 driver disabled. PIE517Setup() missing from startup script.\n"); + } + return((long) 0); +} + + +static void query_done(int card, int axis, struct mess_node *nodeptr) +{ +} + + +/******************************************************************************** +* * +* FUNCTION NAME: set_status * +* * +* LOGIC: * +* Initialize. * +* Send "Moving Status" query. * +* Read response. * +* IF normal response to query. * +* Set communication status to NORMAL. * +* ELSE * +* IF communication status is NORMAL. * +* Set communication status to RETRY. * +* NORMAL EXIT. * +* ELSE * +* Set communication status error. * +* ERROR EXIT. * +* ENDIF * +* ENDIF * +* * +* IF "Moving Status" indicates any motion (i.e. status != 0). * +* Clear "Done Moving" status bit. * +* ELSE * +* Set "Done Moving" status bit. * +* ENDIF * +* * +* * +********************************************************************************/ + +static int set_status(int card, int signal) +{ + struct PIE517controller *cntrl; + struct mess_node *nodeptr; + struct mess_info *motor_info; + struct motorRecord *mr; + /* Message parsing variables */ + char buff[BUFF_SIZE]; + int rtn_state; + unsigned int overflow_status, ontarget_status, servo_status, online_status; + epicsInt32 motorData; + bool plusdir, ls_active, plusLS, minusLS; + bool readOK; + msta_field status; + + cntrl = (struct PIE517controller *) motor_state[card]->DevicePrivate; + motor_info = &(motor_state[card]->motor_info[signal]); + nodeptr = motor_info->motor_motion; + if (nodeptr != NULL) + mr = (struct motorRecord *) nodeptr->mrecord; + else + mr = NULL; + status.All = motor_info->status.All; + + recv_mess(card, buff, FLUSH); + + readOK = false; +// send_mess(card, READ_ONLINE, PIE517_axis[signal]); +// if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &online_status)) +// { +// if (!online_status) +// { +// /* Assume Controller Reboot - Set ONLINE and Velocity Control ON */ +// send_mess(card, SET_ONLINE, PIE517_axis[signal]); +// //send_mess(card, SET_VELCTRL, (char*) NULL); +// } + + send_mess(card, READ_ONTARGET, PIE517_axis[signal]); + if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &ontarget_status)) + { + send_mess(card, READ_OVERFLOW, PIE517_axis[signal]); + if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &overflow_status)) + { + send_mess(card, READ_SERVO, PIE517_axis[signal]); + if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &servo_status)) + { + send_mess(card, READ_POS, PIE517_axis[signal]); + if (recv_mess(card, buff, 1)) + { + motorData = NINT(atof(buff) / cntrl->drive_resolution[signal]); + readOK = true; + } + } + } + } +// } + + if (readOK) + { + 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; + } + } + + + /* Always DONE if torque disabled */ + status.Bits.RA_DONE = (ontarget_status) ? 1 : 0; + status.Bits.RA_HOME = status.Bits.RA_DONE; + + status.Bits.EA_POSITION = (servo_status) ? 1 : 0; /* Torgue disabled flag */ + + ls_active = plusLS = minusLS = false; + + /* LS status may be true but servo is not within position error - keep updating */ + /* No Limit switches but if the Servo Controller overflows indicate with a + LS */ + if (status.Bits.RA_DONE) + plusLS = overflow_status ? true : false; + + if (motorData == motor_info->position) + { + if (nodeptr != 0) /* Increment counter only if motor is moving. */ + motor_info->no_motion_count++; + } + else + { + status.Bits.RA_DIRECTION = (motorData >= motor_info->position) ? 1 : 0; + motor_info->position = motor_info->encoder_position = motorData; + motor_info->no_motion_count = 0; + } + + plusdir = (status.Bits.RA_DIRECTION) ? true : false; + + /* Set limit switch error indicators. */ + if (plusLS == true) + { + status.Bits.RA_PLUS_LS = 1; + if (plusdir == true) + ls_active = true; + } + else + status.Bits.RA_PLUS_LS = 0; + + if (minusLS == true) + { + status.Bits.RA_MINUS_LS = 1; + if (plusdir == false) + ls_active = true; + } + else + status.Bits.RA_MINUS_LS = 0; + + /* encoder status */ + status.Bits.EA_SLIP = 0; + status.Bits.EA_SLIP_STALL = 0; + status.Bits.EA_HOME = 0; + + status.Bits.RA_PROBLEM = 0; + + /* Parse motor velocity? */ + /* NEEDS WORK */ + + motor_info->velocity = 0; + + 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) + { + strcpy(buff, nodeptr->postmsgptr); + send_mess(card, buff, (char*) NULL); + nodeptr->postmsgptr = NULL; + } + +exit: + motor_info->status.All = status.All; + return(rtn_state); +} + + +/*****************************************************/ +/* send a message to the PIE517 board */ +/* send_mess() */ +/*****************************************************/ +static RTN_STATUS send_mess(int card, char const *com, char *name) +{ + char local_buff[MAX_MSG_SIZE]; + char *pbuff; + struct PIE517controller *cntrl; + int comsize, namesize; + size_t nwrite; + + comsize = (com == NULL) ? 0 : strlen(com); + namesize = (name == NULL) ? 0 : strlen(name); + + if ((comsize + namesize) > MAX_MSG_SIZE) + { + errlogMessage("drvPIE517.cc:send_mess(); message size violation.\n"); + return(ERROR); + } + else if (comsize == 0) /* Normal exit on empty input message. */ + return(OK); + + if (!motor_state[card]) + { + errlogPrintf("drvPIE517.cc:send_mess() - invalid card #%d\n", card); + return(ERROR); + } + + local_buff[0] = (char) NULL; /* Terminate local buffer. */ + + if (name == NULL) + strcat(local_buff, com); /* Make a local copy of the string. */ + else + { + strcpy(local_buff, com); + pbuff = strchr(local_buff, '#'); + if (pbuff != NULL) + *pbuff = *name; + else + Debug(1, "send_mess(): NAME ERROR: message = %s\n", local_buff); + } + + Debug(2, "send_mess(): message = %s\n", local_buff); + + cntrl = (struct PIE517controller *) motor_state[card]->DevicePrivate; + pasynOctetSyncIO->write(cntrl->pasynUser, local_buff, strlen(local_buff), + COMM_TIMEOUT, &nwrite); + + return(OK); +} + + +/*****************************************************/ +/* receive a message from the PIE517 board */ +/* recv_mess() */ +/*****************************************************/ +static int recv_mess(int card, char *com, int flag) +{ + struct PIE517controller *cntrl; + size_t nread = 0; + asynStatus status = asynError; + int eomReason; + char *pos; + + /* Check that card exists */ + if (!motor_state[card]) + return(ERROR); + + cntrl = (struct PIE517controller *) motor_state[card]->DevicePrivate; + + if (flag == FLUSH) + pasynOctetSyncIO->flush(cntrl->pasynUser); + else + status = pasynOctetSyncIO->read(cntrl->pasynUser, com, BUFF_SIZE, + COMM_TIMEOUT, &nread, &eomReason); + pos=strchr(com,'='); + if(pos != NULL) + strcpy(com,&pos[1]); + + if ((status != asynSuccess) || (nread <= 0)) + { + com[0] = '\0'; + nread = 0; + } + + Debug(2, "recv_mess(): message = \"%s\"\n", com); + return(nread); +} + + +/*****************************************************/ +/* Setup system configuration */ +/* PIE517Setup() */ +/*****************************************************/ +RTN_STATUS +PIE517Setup(int num_cards, /* maximum number of controllers in system. */ + int scan_rate) /* polling rate - 1/60 sec units. */ +{ + int itera; + + if (num_cards < 1 || num_cards > PIE517_NUM_CARDS) + PIE517_num_cards = PIE517_NUM_CARDS; + else + PIE517_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 PIE517Config 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(PIE517_num_cards * + sizeof(struct controller *)); + + for (itera = 0; itera < PIE517_num_cards; itera++) + motor_state[itera] = (struct controller *) NULL; + + return(OK); +} + + +/*****************************************************/ +/* Configure a controller */ +/* PIE517Config() */ +/*****************************************************/ +RTN_STATUS +PIE517Config(int card, /* card being configured */ + const char *name, /* asyn port name */ + int addr) /* asyn address (GPIB) */ +{ + struct PIE517controller *cntrl; + + if (card < 0 || card >= PIE517_num_cards) + return(ERROR); + + motor_state[card] = (struct controller *) malloc(sizeof(struct controller)); + motor_state[card]->DevicePrivate = malloc(sizeof(struct PIE517controller)); + cntrl = (struct PIE517controller *) motor_state[card]->DevicePrivate; + + strcpy(cntrl->asyn_port, name); + cntrl->asyn_address = addr; + return(OK); +} + + +/*****************************************************/ +/* initialize all software and hardware */ +/* This is called from the initialization routine in */ +/* device support. */ +/* motor_init() */ +/*****************************************************/ +static int motor_init() +{ + struct controller *brdptr; + struct PIE517controller *cntrl; + int card_index, motor_index; + char buff[BUFF_SIZE], *pbuff; + int total_axis; + int status; + int version; + bool online; + asynStatus success_rtn; + static const char output_terminator[] = EOL_E517; + static const char input_terminator[] = EOL_E517; + + initialized = true; /* Indicate that driver is initialized. */ + + /* Check for setup */ + if (PIE517_num_cards <= 0) + return(ERROR); + + for (card_index = 0; card_index < PIE517_num_cards; card_index++) + { + if (!motor_state[card_index]) + continue; + + brdptr = motor_state[card_index]; + brdptr->ident[0] = (char) NULL; /* No controller identification message. */ + brdptr->cmnd_response = false; + total_cards = card_index + 1; + cntrl = (struct PIE517controller *) brdptr->DevicePrivate; + + status = version = 0; + + /* Initialize communications channel */ + success_rtn = pasynOctetSyncIO->connect(cntrl->asyn_port, 0, + &cntrl->pasynUser, NULL); + if (success_rtn == asynSuccess) + { + //int retry = 0; + + pasynOctetSyncIO->setOutputEos(cntrl->pasynUser, output_terminator, + strlen(output_terminator)); + pasynOctetSyncIO->setInputEos(cntrl->pasynUser, input_terminator, + strlen(input_terminator)); + + /* Send a message to the board, see if it exists */ + /* flush any junk at input port - should not be any data available */ + pasynOctetSyncIO->flush(cntrl->pasynUser); + + /* Assure that Controller is ONLINE */ + online = true; + //do + //{ + // online = false; + // /* Set Controller to ONLINE mode */ + // send_mess(card_index, SET_ONLINE, (char*) NULL); + // send_mess(card_index, READ_ONLINE, (char*) NULL); + // if ((status = recv_mess(card_index, buff, 1))) + //online = (atoi(buff)==1) ? true : false; + // else + //retry++; + //} while (online == false && retry < 3); + + //send_mess(card_index, GET_IDENT, (char*) NULL); + //status = recv_mess(card_index, buff, 1); + + /* Parse out E517 revision (2 decimal places) and convert to int */ + if ((pbuff = strchr(buff, 'V'))) + version = NINT(atof(pbuff+1) * 100); + else + version = 0; + } + + if (success_rtn == asynSuccess && online == true) + { + strcpy(brdptr->ident, buff); + brdptr->localaddr = (char *) NULL; + brdptr->motor_in_motion = 0; + + /* Check for E517 versions that need the status word shifted up 8 bits */ + /*if (version >= 311) + cntrl->versionSupport = true; + else + cntrl->versionSupport = false;*/ + + /* Determine # of axes. Request stage name. See if it responds */ + for (total_axis = 0; total_axis < MAX_AXES; total_axis++) + { + send_mess(card_index, READ_POS, PIE517_axis[total_axis]); + status = recv_mess(card_index, buff, 1); + if (!status) + break; + } + brdptr->total_axis = total_axis; + + /* Turn ON velocity control mode - All axis */ + //send_mess(card_index, SET_VELCTRL, (char*) NULL); + + for (motor_index = 0; motor_index < total_axis; motor_index++) + { + struct mess_info *motor_info = &brdptr->motor_info[motor_index]; + + motor_info->status.All = 0; + motor_info->no_motion_count = 0; + motor_info->encoder_position = 0; + motor_info->position = 0; + brdptr->motor_info[motor_index].motor_motion = NULL; + /* PIE517 has DC motor support only */ + motor_info->encoder_present = YES; + motor_info->status.Bits.EA_PRESENT = 1; + motor_info->pid_present = NO; + motor_info->status.Bits.GAIN_SUPPORT = 1; + + cntrl->drive_resolution[motor_index] = POS_RES; + + set_status(card_index, motor_index); /* Read status of each motor */ + } + } + 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; + + epicsThreadCreate((char *) "PIE517_motor", epicsThreadPriorityMedium, + epicsThreadGetStackSize(epicsThreadStackMedium), + (EPICSTHREADFUNC) motor_task, (void *) &targs); + + return(OK); +} + + diff --git a/motorApp/PiSrc/drvPIE517.h b/motorApp/PiSrc/drvPIE517.h new file mode 100755 index 0000000..3d1c942 --- /dev/null +++ b/motorApp/PiSrc/drvPIE517.h @@ -0,0 +1,75 @@ +/* File: drvPIE516.h */ + + +/* Device Driver Support definitions for motor */ +/* + * Original Author: Ron Sluiter + * Current Author: Joe Sullivan + * Date: 09/20/2005 + * + * Modification Log: + * ----------------- + * .01 08/10/16 Bruno Luvizotto (brunoluvizotto@gmail.com) - copied from drvPIE516.h + * .02 08/10/16 Bruno Luvizotto (brunoluvizotto@gmail.com) - edited the files for the E517 controller + */ + +#ifndef INCdrvPIE517h +#define INCdrvPIE517h 1 + +#include "motordrvCom.h" +#include "asynDriver.h" +#include "asynDriver.h" +#include "asynOctetSyncIO.h" + +#define COMM_TIMEOUT 2 /* Timeout in seconds. */ +#define POS_RES 0.001 /* Position resolution. */ + +#define EOL_E517 "\n" /* Command End-Of-Line = LF (0x10) */ + +struct PIE517controller +{ + asynUser *pasynUser; /* asynUser structure */ + int asyn_address; /* Use for GPIB or other address with asyn */ + CommStatus status; /* Controller communication status. */ + double drive_resolution[4]; + bool versionSupport; /* Track supported Versions - include in Report */ + char asyn_port[80]; /* asyn port name */ +}; + + +typedef union +{ + epicsUInt16 All; + struct + { +#ifdef MSB_First + unsigned int cmnd_err :1; /* 15 - Command Error */ + unsigned int na6 :1; /* 14 - */ + unsigned int autozero :1; /* 13 - AutoZero function is running */ + unsigned int plus_ls :1; /* 12 - Positive limit switch flag. */ + unsigned int minus_ls :1; /* 11 - Negative limit switch flag. */ + unsigned int moving :1; /* 10 - Moving indicator - position error outside tolerance */ + unsigned int volt_limit :1; /* 9 - piezo voltage limit reached */ + unsigned int torque :1; /* 8 - Servo-control status */ + unsigned int nabyte :8; + +#else + unsigned int nabyte :8; + unsigned int torque :1; /* 8 - Servo-control status */ + unsigned int volt_limit :1; /* 9 - piezo voltage limit reached */ + unsigned int moving :1; /* 10 - Moving indicator - position error outside tolerance */ + unsigned int minus_ls :1; /* 11 - Negative limit switch flag. */ + unsigned int plus_ls :1; /* 12 - Positive limit switch flag. */ + unsigned int autozero :1; /* 13 - AutoZero function is running */ + unsigned int na6 :1; /* 14 - */ + unsigned int cmnd_err :1; /* 15 - Command Error */ +#endif + } Bits; +} E517_Status_Reg; + + +/* Function prototypes. */ +extern RTN_STATUS PIE517Setup(int, int); +extern RTN_STATUS PIE517Config(int, const char *, int); + +#endif /* INCdrvPIE517h */ diff --git a/motorApp/PiSrc/drvPIE710.cc b/motorApp/PiSrc/drvPIE710.cc index 3fd920c..d5221b4 100644 --- a/motorApp/PiSrc/drvPIE710.cc +++ b/motorApp/PiSrc/drvPIE710.cc @@ -3,9 +3,6 @@ FILENAME... drvPIE710.cc USAGE... Motor record driver level support for Physik Instrumente (PI) GmbH & Co. E-710 motor controller. -Version: $Revision: 1.1 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2006-10-06 18:18:22 $ */ /* @@ -48,6 +45,8 @@ DESIGN LIMITATIONS... #include #include #include +#include +#include #include "motorRecord.h" #include "motor.h" #include "drvPIE710.h" @@ -352,7 +351,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -561,7 +560,7 @@ static int motor_init() do { - send_mess(card_index, GET_IDENT, (char) NULL); + send_mess(card_index, GET_IDENT, (char*) NULL); status = recv_mess(card_index, buff[0], 1); /* Parse out E710 revision (3 decimal places) and convert to int */ diff --git a/motorApp/PiSrc/drvPIE816.cc b/motorApp/PiSrc/drvPIE816.cc index 185a81b..d08d011 100644 --- a/motorApp/PiSrc/drvPIE816.cc +++ b/motorApp/PiSrc/drvPIE816.cc @@ -53,6 +53,8 @@ DESIGN LIMITATIONS... #include #include #include +#include +#include #include "motorRecord.h" #include "motor.h" #include "drvPIE816.h" @@ -250,14 +252,14 @@ static int set_status(int card, int signal) recv_mess(card, buff, FLUSH); readOK = false; - //send_mess(card, READ_ONLINE, (char) NULL); + //send_mess(card, READ_ONLINE, (char*) NULL); /* if (recv_mess(card, buff, 1) && sscanf(buff, "%d", &online_status)) { if (!online_status) { *//* Assume Controller Reboot - Set ONLINE and Velocity Control ON */ - /*send_mess(card, SET_ONLINE, (char) NULL); - send_mess(card, SET_VELCTRL, (char) NULL); + /*send_mess(card, SET_ONLINE, (char*) NULL); + send_mess(card, SET_VELCTRL, (char*) NULL); } */ send_mess(card, READ_ONTARGET, PIE816_axis[signal]); @@ -375,7 +377,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strcpy(buff, nodeptr->postmsgptr); - send_mess(card, buff, (char) NULL); + send_mess(card, buff, (char*) NULL); nodeptr->postmsgptr = NULL; } @@ -595,15 +597,15 @@ static int motor_init() online = false; */ /* Set Controller to ONLINE mode */ -/* send_mess(card_index, SET_ONLINE, (char) NULL); - send_mess(card_index, READ_ONLINE, (char) NULL); +/* send_mess(card_index, SET_ONLINE, (char*) NULL); + send_mess(card_index, READ_ONLINE, (char*) NULL); if ((status = recv_mess(card_index, buff, 1))) online = (atoi(buff)==1) ? true : false; else retry++; } while (online == false && retry < 3); */ - send_mess(card_index, GET_IDENT, (char) NULL); + send_mess(card_index, GET_IDENT, (char*) NULL); status = recv_mess(card_index, buff, 1); /* Parse out E816 revision (2 decimal places) and convert to int */ @@ -637,7 +639,7 @@ static int motor_init() brdptr->total_axis = total_axis; /* Turn ON velocity control mode - All axis */ - /*send_mess(card_index, SET_VELCTRL, (char) NULL);*/ + /*send_mess(card_index, SET_VELCTRL, (char*) NULL);*/ for (motor_index = 0; motor_index < total_axis; motor_index++) { diff --git a/motorApp/ScriptMotorSrc/Makefile b/motorApp/ScriptMotorSrc/Makefile new file mode 100644 index 0000000..37157cf --- /dev/null +++ b/motorApp/ScriptMotorSrc/Makefile @@ -0,0 +1,30 @@ +# Makefile +TOP=../.. + +include $(TOP)/configure/CONFIG +#---------------------------------------- +# ADD MACRO DEFINITIONS AFTER THIS LINE +#============================= + +#================================================== +# Build an IOC support library +LIBRARY_IOC = ScriptMotor + +# motorRecord.h will be created from motorRecord.dbd +# install devMotorSoft.dbd into /dbd +DBD += ScriptMotorDriver.dbd + +INC += ScriptMotorDriver.h + +# The following are compiled and added to the Support library +ScriptMotor_SRCS += ScriptMotorDriver.cpp + +ScriptMotor_LIBS += motor +ScriptMotor_LIBS += asyn +ScriptMotor_LIBS += lua +ScriptMotor_LIBS += $(EPICS_BASE_IOC_LIBS) + +include $(TOP)/configure/RULES +#---------------------------------------- +# ADD RULES AFTER THIS LINE + diff --git a/motorApp/ScriptMotorSrc/ScriptMotorDriver.cpp b/motorApp/ScriptMotorSrc/ScriptMotorDriver.cpp new file mode 100644 index 0000000..93b8e3d --- /dev/null +++ b/motorApp/ScriptMotorSrc/ScriptMotorDriver.cpp @@ -0,0 +1,859 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "asynMotorController.h" +#include "asynMotorAxis.h" + +#include +#include "ScriptMotorDriver.h" + +#define NINT(f) (int)((f)>0 ? (f)+0.5 : (f)-0.5) + + +/************************************************ + * These are the ScriptMotorController methods * + ************************************************/ + + +/** Creates a new ScriptMotorController object. + * \param[in] asyn_port The name of the asyn port that will be created for this driver + * \param[in] serial_port The name of the drvAsynSerialPort that was created previously to connect to the VirtualMotor controller + * \param[in] max_axes The number of axes that this controller supports + * \param[in] script_file + * \param[in] params + */ +ScriptMotorController::ScriptMotorController(const char* asyn_port, + int max_axes, + const char* script_file, + const char* params) + : asynMotorController(asyn_port, + max_axes, + 1, // No. ScriptMotorController asyn parameters + 0, // No. additional interfaces beyond those in base class + 0, // No. additional callback interfaces beyond those in base class + ASYN_CANBLOCK | ASYN_MULTIDEVICE, + 1, // autoconnect + 0, // Default priority + 0) // Default stack size +{ + this->script = std::string(script_file); + + if (params) { this->init_params = std::string(params); } + else { this->init_params = std::string(""); } + + this->createParam("RELOAD_SCRIPT", asynParamInt32, &this->ScriptMotorReload); + + for (int axis = 0; axis < max_axes; axis += 1) + { + new ScriptMotorAxis(this, axis, script_file, params); + } + + this->startPoller(this->movingPollPeriod_, this->idlePollPeriod_, this->forcedFastPolls_); +} + +void ScriptMotorController::reload() +{ + this->lock(); + for (int index = 0; index < this->numAxes_; index += 1) + { + ScriptMotorAxis* axis = this->getAxis(index); + axis->reload(this->script.c_str(), this->init_params.c_str()); + } + this->unlock(); + + printf("Controller %s reloaded %s.\n", this->portName, this->script.c_str()); +} + +/** Creates a new ScriptMotorController object. + * Configuration command, called directly or from iocsh + * \param[in] asyn_port The name of the asyn port that will be created for this driver + * \param[in] max_axes The number of axes that this controller supports + * \param[in] script_file + * \param[in] params + */ +extern "C" int ScriptControllerConfig(const char* asyn_port, + int max_axes, + const char* script_file, + const char* params) +{ + new ScriptMotorController(asyn_port, max_axes, script_file, params); + return(asynSuccess); +} + + +/** Reports on status of the driver + * \param[in] fp The file pointer on which report information will be written + * \param[in] level The level of report detail desired + * + * If details > 0 then information is printed about each axis. + * After printing controller-specific information it calls asynMotorController::report() + */ +void ScriptMotorController::report(FILE *fp, int level) +{ + fprintf(fp, "Script Motor Controller driver %s\n", this->portName); + fprintf(fp, " numAxes=%d\n", numAxes_); + fprintf(fp, " moving poll period=%f\n", movingPollPeriod_); + fprintf(fp, " idle poll period=%f\n", idlePollPeriod_); + + // Call the base class method + asynMotorController::report(fp, level); +} + +asynStatus ScriptMotorController::writeInt32(asynUser *pasynUser, epicsInt32 value) +{ + int function = pasynUser->reason; + + if (function == this->ScriptMotorReload) + { + if (value == 1) { this->reload(); } + return asynSuccess; + } + else + { + return asynMotorController::writeInt32(pasynUser, value); + } +} + +asynStatus ScriptMotorController::setIntegerParam(int list, int function, int value) +{ + if (function >= this->motorStatusDirection_ && function <= this->motorStatusHomed_) + { + ScriptMotorAxis* axis = (ScriptMotorAxis*) this->getAxis(list); + epicsUInt32 status = axis->setStatusParam(function, value); + asynMotorController::setIntegerParam(list, this->motorStatus_, status); + } + + return asynMotorController::setIntegerParam(list, function, value); +} + +asynStatus ScriptMotorController::setDoubleParam(int list, int function, double value) +{ + if (function == this->motorPosition_ || function == this->motorEncoderPosition_) + { + ScriptMotorAxis* axis = (ScriptMotorAxis*) this->getAxis(list); + axis->setPositionParam(function, value); + } + + return asynMotorController::setDoubleParam(list, function, value); +} + +void ScriptMotorController::configAxis(int axisNo, const char* params) +{ + ScriptMotorAxis* axis = this->getAxis(axisNo); + + if (params) { axis->params = std::string(params); } + else { axis->params = std::string(""); } + + axis->config(params); +} + +/** Returns a pointer to an ScriptMotorAxis object. + * Returns NULL if the axis number encoded in pasynUser is invalid. + * \param[in] pasynUser asynUser structure that encodes the axis index number. */ +ScriptMotorAxis* ScriptMotorController::getAxis(asynUser *pasynUser) +{ + return static_cast(asynMotorController::getAxis(pasynUser)); +} + + +/** Returns a pointer to an ScriptMotorAxis object. + * Returns NULL if the axis number encoded in pasynUser is invalid. + * \param[in] axisNo Axis index number. */ +ScriptMotorAxis* ScriptMotorController::getAxis(int axisNo) +{ + return static_cast(asynMotorController::getAxis(axisNo)); +} + + +/****************************************** + * These are the ScriptMotorAxis methods * + ******************************************/ + + +/** Creates a new ScriptMotorAxis object. + * \param[in] pC Pointer to the ScriptMotorController to which this axis belongs. + * \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1. + * + * Initializes register numbers, etc. + */ +ScriptMotorAxis::ScriptMotorAxis(ScriptMotorController *pC, int axisNo, const char* script_file, const char* params) + : asynMotorAxis(pC, axisNo), + pC_(pC) +{ + this->initState(script_file); + this->config(params); + + int isnum; + + lua_getglobal(this->state, "MovingPollPeriod"); + double MovingPollPeriod = lua_tonumberx(this->state, -1, &isnum); + if (isnum) { pC->movingPollPeriod_ = MovingPollPeriod; } + lua_remove(this->state, -1); + + lua_getglobal(this->state, "IdlePollPeriod"); + double IdlePollPeriod = lua_tonumberx(this->state, -1, &isnum); + if (isnum) { pC->idlePollPeriod_ = IdlePollPeriod; } + lua_remove(this->state, -1); + + lua_getglobal(this->state, "ForcedFastPolls"); + double ForcedFastPolls = lua_tonumberx(this->state, -1, &isnum); + if (isnum) { pC->forcedFastPolls_ = ForcedFastPolls; } + lua_remove(this->state, -1); + + // Zero the encoder position (this only appears to be a problem on windows) + setDoubleParam(pC_->motorEncoderPosition_, 0.0); + + // Make the changed parameters take effect + callParamCallbacks(); +} + +void ScriptMotorAxis::initState(const char* script_file) +{ + this->state = luaL_newstate(); + int status = luaLoadScript(this->state, script_file); + + if (status) { printf("Error compiling script file: %s\n", script_file); } + + lua_pushstring(this->state, (const char*) this->pC_->portName); + lua_setglobal(this->state, "DRIVER"); + + lua_pushnumber(this->state, axisNo_); + lua_setglobal(this->state, "AXIS"); +} + +void ScriptMotorAxis::reload(const char* script_file, const char* controller_params) +{ + this->initState(script_file); + this->config(controller_params); + this->config(this->params.c_str()); +} + +epicsUInt32 ScriptMotorAxis::setStatusParam(int index, int value) +{ + if (index >= pC_->motorStatusDirection_ && index <= pC_->motorStatusHomed_) + { + epicsUInt32 status = status_.status; + int mask = 1 << (index - pC_->motorStatusDirection_); + + if (value) { status |= mask; } + else { status &= ~mask; } + + if (status != status_.status) + { + status_.status = status; + statusChanged_ = 1; + } + + return status; + } + + return 0; +} + +void ScriptMotorAxis::setPositionParam(int index, double value) +{ + if (index == pC_->motorPosition_) + { + if (value != status_.position) + { + statusChanged_ = 1; + status_.position = value; + } + } + else if (index == pC_->motorEncoderPosition_) + { + if (value != status_.encoderPosition) + { + statusChanged_ = 1; + status_.encoderPosition = value; + } + } +} + + +/* + * + */ +extern "C" int ScriptAxisConfig(const char* ScriptMotorName, int axisNo, const char* params) +{ + static const char *functionName = "VirtualMotorCreateAxis"; + + ScriptMotorController *pC = (ScriptMotorController*) findAsynPortDriver(ScriptMotorName); + if (!pC) + { + printf("Error port %s not found\n", ScriptMotorName); + return asynError; + } + + pC->lock(); + pC->configAxis(axisNo, params); + pC->unlock(); + + return asynSuccess; +} + + +/** Reports on status of the axis + * \param[in] fp The file pointer on which report information will be written + * \param[in] level The level of report detail desired + * + * After printing device-specific information calls asynMotorAxis::report() + */ +void ScriptMotorAxis::report(FILE *fp, int level) +{ + if (level > 0) { + fprintf(fp, " Axis #%d\n", axisNo_); + fprintf(fp, " axisIndex_=%d\n", axisIndex_); + } + + // Call the base class method + asynMotorAxis::report(fp, level); +} + + +/* + * move() is called by asynMotor device support when an absolute or a relative move is requested. + * It can be called multiple times if BDST > 0 or RTRY > 0. + * + * Arguments in terms of motor record fields: + * position (steps) = RVAL = DVAL / MRES + * baseVelocity (steps/s) = VBAS / abs(MRES) + * velocity (step/s) = VELO / abs(MRES) + * acceleration (step/s/s) = (velocity - baseVelocity) / ACCL + */ +asynStatus ScriptMotorAxis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration) +{ + asynStatus status; + // static const char *functionName = "ScriptMotorAxis::move"; + + int result = lua_getglobal(this->state, "move"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + lua_pushnumber(this->state, position); + lua_pushboolean(this->state, relative); + lua_pushnumber(this->state, minVelocity); + lua_pushnumber(this->state, maxVelocity); + lua_pushnumber(this->state, acceleration); + + if (lua_pcall(this->state, 5, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + // Do something with returned value + + lua_pop(this->state, 1); + } + + return asynSuccess; +} + + +/* + * home() is called by asynMotor device support when a home is requested. + * Note: forwards is set by device support, NOT by the motor record. + * + * Arguments in terms of motor record fields: + * minVelocity (steps/s) = VBAS / abs(MRES) + * maxVelocity (step/s) = HVEL / abs(MRES) + * acceleration (step/s/s) = (maxVelocity - minVelocity) / ACCL + * forwards = 1 if HOMF was pressed, 0 if HOMR was pressed + */ + +asynStatus ScriptMotorAxis::home(double minVelocity, double maxVelocity, double acceleration, int forwards) +{ + int result = lua_getglobal(this->state, "home"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + lua_pushnumber(this->state, minVelocity); + lua_pushnumber(this->state, maxVelocity); + lua_pushnumber(this->state, acceleration); + lua_pushboolean(this->state, forwards); + + if (lua_pcall(this->state, 4, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + // Do something with returned value + + lua_pop(this->state, 1); + } + + return asynSuccess; +} + + + +/* + * moveVelocity() is called by asynMotor device support when a jog is requested. + * If a controller doesn't have a jog command (or jog commands), this a jog can be simulated here. + * + * Arguments in terms of motor record fields: + * minVelocity (steps/s) = VBAS / abs(MRES) + * maxVelocity (step/s) = (jog_direction == forward) ? JVEL * DIR / MRES : -1 * JVEL * DIR / MRES + * acceleration (step/s/s) = JAR / abs(EGU) + */ +asynStatus ScriptMotorAxis::moveVelocity(double minVelocity, double maxVelocity, double acceleration) +{ + int result = lua_getglobal(this->state, "moveVelocity"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + lua_pushnumber(this->state, minVelocity); + lua_pushnumber(this->state, maxVelocity); + lua_pushnumber(this->state, acceleration); + + if (lua_pcall(this->state, 3, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + // Do something with returned value + + lua_pop(this->state, 1); + } + + return asynSuccess; +} + + +/* + * stop() is called by asynMotor device support whenever a user presses the stop button. + * It is also called when the jog button is released. + * + * Arguments in terms of motor record fields: + * acceleration = ??? + */ +asynStatus ScriptMotorAxis::stop(double acceleration) +{ + int result = lua_getglobal(this->state, "stop"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + lua_pushnumber(this->state, acceleration); + + if (lua_pcall(this->state, 1, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + // Do something with returned value + + lua_pop(this->state, 1); + } + + return asynSuccess; +} + + +/* + * setPosition() is called by asynMotor device support when a position is redefined. + * It is also required for autosave to restore a position to the controller at iocInit. + * + * Arguments in terms of motor record fields: + * position (steps) = DVAL / MRES = RVAL + */ +asynStatus ScriptMotorAxis::setPosition(double position) +{ + int result = lua_getglobal(this->state, "setPosition"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + lua_pushnumber(this->state, position); + + if (lua_pcall(this->state, 1, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + // Do something with returned value + + lua_pop(this->state, 1); + } + + return asynSuccess; +} + +asynStatus ScriptMotorAxis::setEncoderPosition(double position) +{ + int result = lua_getglobal(this->state, "setEncoderPosition"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + lua_pushnumber(this->state, position); + + if (lua_pcall(this->state, 1, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + // Do something with returned value + + lua_pop(this->state, 1); + } + + return asynSuccess; +} + +asynStatus ScriptMotorAxis::setHighLimit(double highLimit) +{ + int result = lua_getglobal(this->state, "setHighLimit"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + lua_pushnumber(this->state, highLimit); + + if (lua_pcall(this->state, 1, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + // Do something with returned value + + lua_pop(this->state, 1); + } + + return asynSuccess; +} + +asynStatus ScriptMotorAxis::setLowLimit(double lowLimit) +{ + int result = lua_getglobal(this->state, "setLowLimit"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + lua_pushnumber(this->state, lowLimit); + + if (lua_pcall(this->state, 1, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + // Do something with returned value + + lua_pop(this->state, 1); + } + + return asynSuccess; +} + + +asynStatus ScriptMotorAxis::setPGain(double PGain) +{ + int result = lua_getglobal(this->state, "setPGain"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + lua_pushnumber(this->state, PGain); + + if (lua_pcall(this->state, 1, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + // Do something with returned value + + lua_pop(this->state, 1); + } + + return asynSuccess; +} + +asynStatus ScriptMotorAxis::setIGain(double IGain) +{ + int result = lua_getglobal(this->state, "setIGain"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + lua_pushnumber(this->state, IGain); + + if (lua_pcall(this->state, 1, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + // Do something with returned value + + lua_pop(this->state, 1); + } + + return asynSuccess; +} + +asynStatus ScriptMotorAxis::setDGain(double DGain) +{ + int result = lua_getglobal(this->state, "setDGain"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + lua_pushnumber(this->state, DGain); + + if (lua_pcall(this->state, 1, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + // Do something with returned value + + lua_pop(this->state, 1); + } + + return asynSuccess; +} + +/* + * setClosedLoop() is called by asynMotor device support when a user enables or disables torque, + * usually from the motorx_all.adl, but only for drivers that set the following params to 1: + * pC->motorStatusGainSupport_ + * pC->motorStatusHasEncoder_ + * What is actually implemented here varies greatly based on the specfics of the controller. + * + * Arguments in terms of motor record fields: + * closedLoop = CNEN + */ + +asynStatus ScriptMotorAxis::setClosedLoop(bool closedLoop) +{ + int result = lua_getglobal(this->state, "setClosedLoop"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + lua_pushboolean(this->state, (int) closedLoop); + + if (lua_pcall(this->state, 1, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + // Do something with returned value + + lua_pop(this->state, 1); + } + + return asynSuccess; +} + +asynStatus ScriptMotorAxis::setEncoderRatio(double EncoderRatio) +{ + int result = lua_getglobal(this->state, "setEncoderRatio"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + lua_pushnumber(this->state, EncoderRatio); + + if (lua_pcall(this->state, 1, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + // Do something with returned value + + lua_pop(this->state, 1); + } + + return asynSuccess; +} + + + +/** Polls the axis. + * This function reads the motor position, the limit status, the home status, the moving status, + * and the drive power-on status. + * It calls setIntegerParam() and setDoubleParam() for each item that it polls, + * and then calls callParamCallbacks() at the end. + * \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false). */ +asynStatus ScriptMotorAxis::poll(bool *moving) +{ + int result = lua_getglobal(this->state, "poll"); + if (result != LUA_TFUNCTION) + { + // No function in script + } + else + { + if (lua_pcall(this->state, 0, 1, 0)) + { + this->logError(); + return asynError; + } + + int rettype = lua_type(this->state, -1); + + if (rettype == LUA_TBOOLEAN) + { + if (lua_toboolean(this->state, -1)) { *moving = true; } + else { *moving = false; } + } + + lua_pop(this->state, 1); + } + + this->callParamCallbacks(); + return asynSuccess; +} + +void ScriptMotorAxis::config(const char* params) +{ + luaLoadMacros(this->state, params); +} + +void ScriptMotorAxis::logError() +{ + std::string err(lua_tostring(this->state, -1)); + lua_pop(this->state, 1); + + printf("%s\n", err.c_str()); +} + +void ScriptMotorReload(const char* port) +{ + ScriptMotorController* controller = (ScriptMotorController*) findAsynPortDriver(port); + + if (controller != NULL) { controller->reload(); } +} + + +/** Code for iocsh registration */ +static const iocshArg ScriptMotorReloadArg0 = {"Motor Port name", iocshArgString}; + +static const iocshArg* const ScriptMotorReloadArgs[] = {&ScriptMotorReloadArg0}; + +static const iocshFuncDef ScriptMotorReloadDef = {"ScriptMotorReload", 1, ScriptMotorReloadArgs}; + +static void ScriptMotorReloadCallFunc(const iocshArgBuf *args) +{ + ScriptMotorReload(args[0].sval); +} + + +static const iocshArg ScriptMotorCreateControllerArg0 = {"Motor Port name", iocshArgString}; +static const iocshArg ScriptMotorCreateControllerArg1 = {"Number of axes", iocshArgInt}; +static const iocshArg ScriptMotorCreateControllerArg2 = {"Control Script", iocshArgString}; +static const iocshArg ScriptMotorCreateControllerArg3 = {"Parameters", iocshArgString}; +static const iocshArg * const ScriptMotorCreateControllerArgs[] = {&ScriptMotorCreateControllerArg0, + &ScriptMotorCreateControllerArg1, + &ScriptMotorCreateControllerArg2, + &ScriptMotorCreateControllerArg3}; +static const iocshFuncDef ScriptMotorCreateControllerDef = {"ScriptControllerConfig", 4, ScriptMotorCreateControllerArgs}; +static void ScriptMotorCreateContollerCallFunc(const iocshArgBuf *args) +{ + ScriptControllerConfig(args[0].sval, args[1].ival, args[2].sval, args[3].sval); +} + + +static const iocshArg ScriptMotorCreateAxisArg0 = {"Controller port name", iocshArgString}; +static const iocshArg ScriptMotorCreateAxisArg1 = {"Axis number", iocshArgInt}; +static const iocshArg ScriptMotorCreateAxisArg2 = {"Parameters", iocshArgString}; + +static const iocshArg * const ScriptMotorCreateAxisArgs[] = {&ScriptMotorCreateAxisArg0, + &ScriptMotorCreateAxisArg1, + &ScriptMotorCreateAxisArg2}; + +static const iocshFuncDef ScriptMotorCreateAxisDef = {"ScriptAxisConfig", 3, ScriptMotorCreateAxisArgs}; +static void ScriptMotorCreateAxisCallFunc(const iocshArgBuf *args) +{ + ScriptAxisConfig(args[0].sval, args[1].ival, args[2].sval); +} + + + +static void ScriptMotorRegister(void) +{ + iocshRegister(&ScriptMotorReloadDef, ScriptMotorReloadCallFunc); + iocshRegister(&ScriptMotorCreateControllerDef, ScriptMotorCreateContollerCallFunc); + iocshRegister(&ScriptMotorCreateAxisDef, ScriptMotorCreateAxisCallFunc); +} + + +extern "C" { +epicsExportRegistrar(ScriptMotorRegister); +} diff --git a/motorApp/ScriptMotorSrc/ScriptMotorDriver.dbd b/motorApp/ScriptMotorSrc/ScriptMotorDriver.dbd new file mode 100644 index 0000000..8f5bbc2 --- /dev/null +++ b/motorApp/ScriptMotorSrc/ScriptMotorDriver.dbd @@ -0,0 +1 @@ +registrar(ScriptMotorRegister) diff --git a/motorApp/ScriptMotorSrc/ScriptMotorDriver.h b/motorApp/ScriptMotorSrc/ScriptMotorDriver.h new file mode 100644 index 0000000..f3b8461 --- /dev/null +++ b/motorApp/ScriptMotorSrc/ScriptMotorDriver.h @@ -0,0 +1,76 @@ +#include "asynMotorController.h" +#include "asynMotorAxis.h" + +#include +#include "luaEpics.h" + +class epicsShareClass ScriptMotorAxis : public asynMotorAxis +{ +public: + /* These are the methods we override from the base class */ + ScriptMotorAxis(class ScriptMotorController *pC, int axisNo, const char* script_file, const char* params); + + void reload(const char* script, const char* params); + + void report(FILE *fp, int level); + + asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration); + asynStatus moveVelocity(double min_velocity, double max_velocity, double acceleration); + asynStatus home(double min_velocity, double max_velocity, double acceleration, int forwards); + asynStatus stop(double acceleration); + asynStatus poll(bool *moving); + asynStatus setPosition(double position); + asynStatus setEncoderPosition(double position); + asynStatus setHighLimit(double highLimit); + asynStatus setLowLimit(double lowLimit); + asynStatus setPGain(double pGain); + asynStatus setIGain(double iGain); + asynStatus setDGain(double dGain); + asynStatus setClosedLoop(bool closedLoop); + asynStatus setEncoderRatio(double ratio); + + virtual epicsUInt32 setStatusParam(int index, int value); + virtual void setPositionParam(int index, double value); + +private: + ScriptMotorController *pC_; /**< Pointer to the asynMotorController to which this axis belongs. + * Abbreviated because it is used very frequently */ + int axisIndex_; + + std::string params; + + lua_State* state; + + void initState(const char* script_file); + void config(const char* params); + void logError(); + +friend class ScriptMotorController; +}; + +class epicsShareClass ScriptMotorController : public asynMotorController { +public: + ScriptMotorController(const char *asyn_port, int max_axes, const char* script_file, const char* params); + + virtual asynStatus setIntegerParam(int list, int function, int value); + virtual asynStatus setDoubleParam(int list, int function, double value); + + virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); + + void report(FILE *fp, int level); + ScriptMotorAxis* getAxis(asynUser *pasynUser); + ScriptMotorAxis* getAxis(int axisNo); + + void configAxis(int axisNo, const char* params); + + void reload(); + +protected: + int ScriptMotorReload; + +private: + std::string script; + std::string init_params; + +friend class ScriptMotorAxis; +}; diff --git a/motorApp/SmarActMCSSrc/smarActMCSMotorDriver.cpp b/motorApp/SmarActMCSSrc/smarActMCSMotorDriver.cpp index 4ef9676..bf35d6b 100644 --- a/motorApp/SmarActMCSSrc/smarActMCSMotorDriver.cpp +++ b/motorApp/SmarActMCSSrc/smarActMCSMotorDriver.cpp @@ -35,8 +35,9 @@ #define FAR_AWAY 1000000000 /*nm*/ #define UDEG_PER_REV 360000000 -// Windows does not have rint() -#ifdef _WIN32 +// Windows and vxWorks do not have rint(), but minGW does +#if defined __MINGW32__ || defined __MINGW64__ +#elif defined _WIN32 || defined vxWorks double rint(double x) { //middle value point test diff --git a/motorApp/SmartMotorSrc/devSmartMotor.cc b/motorApp/SmartMotorSrc/devSmartMotor.cc index 919340d..7a0ce98 100644 --- a/motorApp/SmartMotorSrc/devSmartMotor.cc +++ b/motorApp/SmartMotorSrc/devSmartMotor.cc @@ -2,9 +2,6 @@ FILENAME... devSmartMotor.cc USAGE... Motor record driver level support for Animatics Corporation SmartMotors. -Version: $Revision: 1.2 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-03-14 20:21:56 $ */ /* @@ -44,6 +41,7 @@ Last Modified: $Date: 2008-03-14 20:21:56 $ */ #include +#include #include "motorRecord.h" #include "motor.h" @@ -72,7 +70,7 @@ extern struct driver_table SmartMotor_access; /* ----------------Create the dsets for devSmartMotor----------------- */ static struct driver_table *drvtabptr; -static long SmartMotor_init(void *); +static long SmartMotor_init(int); static long SmartMotor_init_record(void *); static long SmartMotor_start_trans(struct motorRecord *); static RTN_STATUS SmartMotor_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -129,12 +127,11 @@ static struct board_stat **SmartMotor_cards; /* initialize device support for SmartMotor stepper motor */ -static long SmartMotor_init(void *arg) +static long SmartMotor_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &SmartMotor_access; (drvtabptr->init) (); diff --git a/motorApp/SmartMotorSrc/drvSmartMotor.cc b/motorApp/SmartMotorSrc/drvSmartMotor.cc index acfbebf..bffe4b0 100644 --- a/motorApp/SmartMotorSrc/drvSmartMotor.cc +++ b/motorApp/SmartMotorSrc/drvSmartMotor.cc @@ -2,9 +2,6 @@ FILENAME... drvSmartMotor.cc USAGE... Motor record driver level support for Animatics Corporation SmartMotors. -Version: $Revision: 1.3 $ -Modified By: $Author: rivers $ -Last Modified: $Date: 2007-09-13 16:36:38 $ */ /* @@ -47,6 +44,8 @@ Last Modified: $Date: 2007-09-13 16:36:38 $ #include #include #include +#include +#include #include "motor.h" #include "motorRecord.h" #include "drvSmartMotor.h" diff --git a/motorApp/SoftMotorSrc/devSoft.cc b/motorApp/SoftMotorSrc/devSoft.cc index 77b0bdd..55d2913 100644 --- a/motorApp/SoftMotorSrc/devSoft.cc +++ b/motorApp/SoftMotorSrc/devSoft.cc @@ -1,11 +1,7 @@ /* -FILENAME... devSoft.cc -USAGE... Motor record device level support for Soft channel. +FILENAME... devSoft.cc +USAGE... Motor record device level support for Soft channel. -Version: $Revision: 14155 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2011-11-29 14:50:00 -0600 (Tue, 29 Nov 2011) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/SoftMotorSrc/devSoft.cc $ */ /* @@ -28,55 +24,60 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- * ----------------- * * .00 02-06-02 rls - Don't process from events unless interruptAccept is TRUE. - * - When done transitions from false to true it is not - * communicated to the motor record until after the last - * readback update. - * - In soft_process(), call dbProcess() instead of directly - * calling motor record's process(). - * - In soft_rdbl_func(), reset motor record's target to actual - * position after last readback if motion was not initiated - * by this record. + * - When done transitions from false to true it is not + * communicated to the motor record until after the last + * readback update. + * - In soft_process(), call dbProcess() instead of directly + * calling motor record's process(). + * - In soft_rdbl_func(), reset motor record's target to actual + * position after last readback if motion was not initiated + * by this record. * .01 10-29-02 rls - LOCK field added to prevent synchronization due to - * changing readback. + * changing readback. * .02 06-16-03 rls Convert to R3.14.x. * .03 08-03-05 rls - Added debug messages. - * - Fix compiler error with "gcc version 3.4.2 20041017 (Red - * Hat 3.4.2-6.fc3)". + * - Fix compiler error with "gcc version 3.4.2 20041017 (Red + * Hat 3.4.2-6.fc3)". */ /* NOTES... -- Can't call CA functions until after dbLockInitRecords() has - been called and initialized lock sets. +- Can't call CA functions until after dbLockInitRecords() has been called and initialized lock sets. */ +/* The following is needed to compile against Base R3.16.1 without a warning */ +#define USE_TYPED_RSET -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -#include "motorRecord.h" -#include "motor.h" -#include "devSoft.h" +#include "motorRecord.h" +#include "motor.h" +#include "devSoft.h" -#include "epicsExport.h" -#include "errlog.h" +#include "epicsExport.h" +#include "errlog.h" /*----------------debugging-----------------*/ volatile int devSoftdebug = 0; -extern "C" {epicsExportAddress(int, devSoftdebug);} -static inline void Debug(int level, const char *format, ...) { - #ifdef DEBUG - if (level < devSoftdebug) { - va_list pVar; - va_start(pVar, format); - vprintf(format, pVar); - va_end(pVar); +extern "C" +{epicsExportAddress(int, devSoftdebug);} +static inline void Debug(int level, const char *format, ...) +{ +#ifdef DEBUG + if (level < devSoftdebug) + { + va_list pVar; + va_start(pVar, format); + vprintf(format, pVar); + va_end(pVar); } - #endif +#endif } static CALLBACK_VALUE update(struct motorRecord *); @@ -95,7 +96,7 @@ struct motor_dset devMotorSoft = end }; -extern "C" {epicsExportAddress(dset,devMotorSoft);} +extern "C" {epicsExportAddress(dset, devMotorSoft);} static CALLBACK_VALUE update(struct motorRecord *mr) { @@ -105,9 +106,9 @@ static CALLBACK_VALUE update(struct motorRecord *mr) #ifdef DMR_SOFTMOTOR_MODS if (ptr->load_position) { - mr->rmp = ptr->new_position; - mr->rep = ptr->new_position; - ptr->load_position = FALSE; + mr->rmp = ptr->new_position; + mr->rep = ptr->new_position; + ptr->load_position = FALSE; } #endif @@ -117,13 +118,13 @@ static CALLBACK_VALUE update(struct motorRecord *mr) if (ptr->dinp_value == SOFTMOVE || ptr->dinp_value == HARDMOVE) { - Debug(5, "update(): DMOV=0 for %s.\n", mr->name); - status.Bits.RA_DONE = 0; + Debug(5, "update(): DMOV=0 for %s.\n", mr->name); + status.Bits.RA_DONE = 0; } else { - Debug(5, "update(): DMOV=1 for %s.\n", mr->name); - status.Bits.RA_DONE = 1; + Debug(5, "update(): DMOV=1 for %s.\n", mr->name); + status.Bits.RA_DONE = 1; } mr->msta = status.All; return(ptr->callback_flag); @@ -142,11 +143,11 @@ static RTN_STATUS end(struct motorRecord *mr) if (ptr->default_done_behavior == YES) { - msta_field status; + msta_field status; - status.All = 0; - status.Bits.RA_DONE = 1; - mr->msta = status.All; + status.All = 0; + status.Bits.RA_DONE = 1; + mr->msta = status.All; } return(OK); } @@ -159,38 +160,38 @@ static RTN_STATUS build(motor_cmnd command, double *parms, struct motorRecord *m switch (command) { - case MOVE_ABS: - case MOVE_REL: - status = dbPutLink(&mr->out, DBR_DOUBLE, &mr->dval, 1); - break; - - case STOP_AXIS: - status = dbPutLink(&mr->stoo, DBR_SHORT, &stop, 1); - break; - - case SET_HIGH_LIMIT: - case SET_LOW_LIMIT: - status = OK; - break; - - case LOAD_POS: - { - struct soft_private *ptr = (struct soft_private *) mr->dpvt; - msta_field msta; - + case MOVE_ABS: + case MOVE_REL: + status = dbPutLink(&mr->out, DBR_DOUBLE, &mr->dval, 1); + break; + + case STOP_AXIS: + status = dbPutLink(&mr->stoo, DBR_SHORT, &stop, 1); + break; + + case SET_HIGH_LIMIT: + case SET_LOW_LIMIT: + status = OK; + break; + + case LOAD_POS: + { + struct soft_private *ptr = (struct soft_private *) mr->dpvt; + msta_field msta; + #ifdef DMR_SOFTMOTOR_MODS - ptr->load_position = TRUE; - ptr->new_position = *parms; + ptr->load_position = TRUE; + ptr->new_position = *parms; #endif - msta.All = 0; - msta.Bits.RA_DONE = 1; - mr->msta = msta.All; - callbackRequest(&ptr->callback); - } - break; - - default: - status = ERROR; + msta.All = 0; + msta.Bits.RA_DONE = 1; + mr->msta = msta.All; + callbackRequest(&ptr->callback); + } + break; + + default: + status = ERROR; } return(status == 0 ? OK : ERROR); } @@ -198,24 +199,24 @@ static RTN_STATUS build(motor_cmnd command, double *parms, struct motorRecord *m /* FUNCTION... void soft_dinp_func(struct motorRecord *, short) -USAGE... Update soft channel device input links and +USAGE... Update soft channel device input links and process soft channel motor record when done moving. LOGIC... IF DINP link value is FALSE. - IF this soft motor's DMOV is FALSE. - This is a soft motor initiated move. - Set SOFTMOVE indicator. - ELSE IF LOCK field set to NO. - This is NOT a soft motor initiated move. - Set HARDMOVE indicator. - Set soft motor's DMOV FALSE. - Set PostProcess (PP) TRUE. - ENDIF + IF this soft motor's DMOV is FALSE. + This is a soft motor initiated move. + Set SOFTMOVE indicator. + ELSE IF LOCK field set to NO. + This is NOT a soft motor initiated move. + Set HARDMOVE indicator. + Set soft motor's DMOV FALSE. + Set PostProcess (PP) TRUE. + ENDIF ELSE - IF DINP state is HARDMOVE. - Set PostProcess (PP) True. - Set DINP state to DONE. - Process soft channel record. + IF DINP state is HARDMOVE. + Set PostProcess (PP) True. + Set DINP state to DONE. + Process soft channel record. ENDIF */ void soft_dinp_func(struct motorRecord *mr, short newdinp) @@ -223,33 +224,33 @@ void soft_dinp_func(struct motorRecord *mr, short newdinp) struct soft_private *ptr = (struct soft_private *) mr->dpvt; if (interruptAccept != TRUE) - return; - + return; + /* Test for hard motor started moving or initialization. */ if (newdinp == 0) { - if (mr->dmov == FALSE) - { - Debug(5, "soft_dinp_func(): SOFTMOVE set for %s.\n", mr->name); - ptr->dinp_value = SOFTMOVE; - } - else if (mr->lock == menuYesNoNO) - { /* Hard motor is moving independent of soft motor. */ - Debug(5, "soft_dinp_func(): HARDMOVE set for %s.\n", mr->name); - ptr->dinp_value = HARDMOVE; - mr->dmov = FALSE; - db_post_events(mr, &mr->dmov, DBE_VAL_LOG); - mr->pp = TRUE; - db_post_events(mr, &mr->pp, DBE_VAL_LOG); - } + if (mr->dmov == FALSE) + { + Debug(5, "soft_dinp_func(): SOFTMOVE set for %s.\n", mr->name); + ptr->dinp_value = SOFTMOVE; + } + else if (mr->lock == menuYesNoNO) + { /* Hard motor is moving independent of soft motor. */ + Debug(5, "soft_dinp_func(): HARDMOVE set for %s.\n", mr->name); + ptr->dinp_value = HARDMOVE; + mr->dmov = FALSE; + db_post_events(mr, &mr->dmov, DBE_VAL_LOG); + mr->pp = TRUE; + db_post_events(mr, &mr->pp, DBE_VAL_LOG); + } } - else /* Hard motor is done moving. */ + else /* Hard motor is done moving. */ { - if (ptr->dinp_value == HARDMOVE) - mr->pp = TRUE; - ptr->dinp_value = DONE; - Debug(5, "soft_dinp_func(): Done moving set for %s.\n", mr->name); - soft_process(mr); /* Process in case there is no readback callback. */ + if (ptr->dinp_value == HARDMOVE) + mr->pp = TRUE; + ptr->dinp_value = DONE; + Debug(5, "soft_dinp_func(): Done moving set for %s.\n", mr->name); + soft_process(mr); /* Process in case there is no readback callback. */ } } @@ -257,50 +258,50 @@ void soft_dinp_func(struct motorRecord *mr, short newdinp) void soft_rinp_func(struct motorRecord *mr, long newrinp) { if (interruptAccept != TRUE) - return; - + return; + mr->rmp = newrinp; soft_process(mr); } void soft_rdbl_func(struct motorRecord *mr, double newrdbl) -{ +{ struct soft_private *ptr = (struct soft_private *) mr->dpvt; if (interruptAccept != TRUE) - return; + return; newrdbl = newrdbl / mr->mres; mr->rmp = NINT(newrdbl); Debug(5, "soft_rdbl_func(): updated RMP = %d for %s.\n", mr->rmp, mr->name); - + if (ptr->initialized == false) { - /* Reset Target to Actual position. */ - unsigned short mask = (DBE_VALUE | DBE_LOG); + /* Reset Target to Actual position. */ + unsigned short mask = (DBE_VALUE | DBE_LOG); - mr->dmov = FALSE; - db_post_events(mr, &mr->dmov, mask); - mr->pp = TRUE; - db_post_events(mr, &mr->pp, mask); + mr->dmov = FALSE; + db_post_events(mr, &mr->dmov, mask); + mr->pp = TRUE; + db_post_events(mr, &mr->pp, mask); - ptr->dinp_value = DONE; - ptr->initialized = true; - } + ptr->dinp_value = DONE; + ptr->initialized = true; + } soft_process(mr); } /* FUNCTION... static void soft_process(struct motorRecord *) -USAGE... Process the soft channel motor record. +USAGE... Process the soft channel motor record. LOGIC... - Lock soft channel record - call dbScanLock(). - Set call back flag to CALLBACK_DATA so readback will get updated. - Process soft channel record - call process(). - Unlock soft channel record - call dbScanUnlock(). + Lock soft channel record - call dbScanLock(). + Set call back flag to CALLBACK_DATA so readback will get updated. + Process soft channel record - call process(). + Unlock soft channel record - call dbScanUnlock(). */ static void soft_process(struct motorRecord *mr) @@ -309,7 +310,7 @@ static void soft_process(struct motorRecord *mr) dbScanLock((struct dbCommon *) mr); ptr->callback_flag = CALLBACK_DATA; - dbProcess((struct dbCommon *) mr); /* Process the soft channel record. */ + dbProcess((struct dbCommon *) mr); /* Process the soft channel record. */ ptr->callback_flag = NOTHING_DONE; dbScanUnlock((struct dbCommon *) mr); } @@ -317,8 +318,8 @@ static void soft_process(struct motorRecord *mr) /* FUNCTION... void soft_motor_callback(CALLBACK *) -USAGE... Process motor record after the following events: - - LOAD_POS motor command. +USAGE... Process motor record after the following events: + - LOAD_POS motor command. LOGIC... */ diff --git a/motorApp/SoftMotorSrc/devSoft.h b/motorApp/SoftMotorSrc/devSoft.h index e59d465..470091c 100644 --- a/motorApp/SoftMotorSrc/devSoft.h +++ b/motorApp/SoftMotorSrc/devSoft.h @@ -4,10 +4,6 @@ FILENAME.. devSoft.h USAGE... This file contains information that is common to all Soft channel device support modules. -Version: $Revision: 10365 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2010-03-25 12:12:41 -0500 (Thu, 25 Mar 2010) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/SoftMotorSrc/devSoft.h $ */ /* @@ -58,7 +54,7 @@ struct motor_node { struct motorRecord *pmr; }; -extern long soft_init(void *); +extern long soft_init(int); extern long soft_init_record(void *); extern void soft_dinp_func(struct motorRecord *, short); extern void soft_rdbl_func(struct motorRecord *, double); diff --git a/motorApp/SoftMotorSrc/devSoftAux.cc b/motorApp/SoftMotorSrc/devSoftAux.cc index e61b9b6..05a0496 100644 --- a/motorApp/SoftMotorSrc/devSoftAux.cc +++ b/motorApp/SoftMotorSrc/devSoftAux.cc @@ -1,11 +1,7 @@ /* -FILENAME... devSoftAux.cc -USAGE... Motor record device level support for Soft channel. +FILENAME... devSoftAux.cc +USAGE... Motor record device level support for Soft channel. -Version: $Revision: 10365 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2010-03-25 12:12:41 -0500 (Thu, 25 Mar 2010) $ -HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorApp/SoftMotorSrc/devSoftAux.cc $ */ /* @@ -28,7 +24,7 @@ HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6- * ----------------- * .01 06-16-03 rls Convert to R3.14.x. * .02 12-14-04 rls With EPICS R3.14.7 changes to epicsThread.h, need explicit - * #include + * #include * .03 2006-04-10 pnd Convert to linked lists to remove arbitrary maximum */ @@ -45,6 +41,7 @@ in the same file; each defines (redefines) the DBR's. #include #include #include +#include #include #include @@ -52,7 +49,21 @@ in the same file; each defines (redefines) the DBR's. #include "motor.h" #include "devSoft.h" -#define STATIC static +#define STATIC static + +extern volatile int devSoftdebug; +static inline void Debug(int level, const char *format, ...) +{ +#ifdef DEBUG + if (level < devSoftdebug) + { + va_list pVar; + va_start(pVar, format); + vprintf(format, pVar); + va_end(pVar); + } +#endif +} STATIC void soft_dinp(struct event_handler_args); STATIC void soft_rdbl(struct event_handler_args); @@ -78,44 +89,42 @@ STATIC void soft_rinp(struct event_handler_args args) soft_rinp_func((struct motorRecord *) args.usr, *((long *) args.dbr)); } -long soft_init(void *after) +long soft_init(int after) { - int before_after = (after == 0) ? 0 : 1; - - if (before_after == 0) + if (!after) { - epicsThreadId dbCaTask_tid; - unsigned int soft_motor_priority; - int retry = 0; + epicsThreadId dbCaTask_tid; + unsigned int soft_motor_priority; + int retry = 0; soft_motor_sem = epicsEventCreate(epicsEventEmpty); - ellInit(&soft_motor_list); - - /* - * Fix for DMOV processing before the last DRBV update; i.e., lower - * the priority of the "soft_motor" task below the priority of the - * "dbCaLink" task. - */ - while((dbCaTask_tid = epicsThreadGetId("dbCaLink")) == 0 && retry < 10) - { - epicsThreadSleep(0.1); - retry++; - } - - if (dbCaTask_tid == 0) - { - errMessage(0, "cannot find dbCaLink task."); - return(ERROR); - } - soft_motor_priority = epicsThreadGetPriority(dbCaTask_tid); - soft_motor_priority -= 1; - - soft_motor_id = epicsThreadCreate((char *) "soft_motor", soft_motor_priority, + ellInit(&soft_motor_list); + + /* + * Fix for DMOV processing before the last DRBV update; i.e., lower + * the priority of the "soft_motor" task below the priority of the + * "dbCaLink" task. + */ + while((dbCaTask_tid = epicsThreadGetId("dbCaLink")) == 0 && retry < 10) + { + epicsThreadSleep(0.1); + retry++; + } + + if (dbCaTask_tid == 0) + { + errMessage(0, "cannot find dbCaLink task."); + return(ERROR); + } + soft_motor_priority = epicsThreadGetPriority(dbCaTask_tid); + soft_motor_priority -= 1; + + soft_motor_id = epicsThreadCreate((char *) "soft_motor", soft_motor_priority, epicsThreadGetStackSize(epicsThreadStackBig), - (EPICSTHREADFUNC) soft_motor_task, NULL); + (EPICSTHREADFUNC) soft_motor_task, NULL); } else - epicsEventSignal(soft_motor_sem); /* Start soft_motor_task(). */ + epicsEventSignal(soft_motor_sem); /* Start soft_motor_task(). */ return(OK); } @@ -129,12 +138,11 @@ long soft_init_record(void *arg) int status = 0; list_entry = (struct motor_node *) malloc(sizeof(struct motor_node)); - if (!list_entry) { - return(ERROR); - } + if (!list_entry) + return(ERROR); list_entry->pmr = mr; - ellAdd(&soft_motor_list, (ELLNODE*)list_entry); + ellAdd(&soft_motor_list, (ELLNODE*) list_entry); /* Allocate space for private field. */ mr->dpvt = (struct soft_private *) malloc(sizeof(struct soft_private)); @@ -143,8 +151,7 @@ long soft_init_record(void *arg) ptr->initialized = false; cbptr = &ptr->callback; - callbackSetCallback((void (*)(struct callbackPvt *)) soft_motor_callback, - cbptr); + callbackSetCallback((void (*)(struct callbackPvt *)) soft_motor_callback, cbptr); callbackSetPriority(priorityMedium, cbptr); callbackSetUser(mr, cbptr); return ((long) status); @@ -158,44 +165,60 @@ STATIC EPICSTHREADFUNC soft_motor_task(void *parm) chid dinp, rdbl, rinp; epicsEventId wait_forever; - epicsEventWait(soft_motor_sem); /* Wait for dbLockInitRecords() to execute. */ - SEVCHK(ca_context_create(ca_enable_preemptive_callback), - "soft_motor_task: ca_context_create() error"); + epicsEventWait(soft_motor_sem); /* Wait for dbLockInitRecords() to execute. */ + SEVCHK(ca_context_create(ca_enable_preemptive_callback), "soft_motor_task: ca_context_create() error"); - while ((node = (struct motor_node *)ellGet(&soft_motor_list))) + while ((node = (struct motor_node *) ellGet(&soft_motor_list))) { - struct soft_private *ptr; - - mr = node->pmr; - free(node); - - ptr = (struct soft_private *) mr->dpvt; - if (mr->dinp.value.constantStr == NULL) - { - ptr->default_done_behavior = true; - } - else - { - ptr->default_done_behavior = false; - SEVCHK(ca_search(mr->dinp.value.pv_link.pvname, &dinp), - "ca_search() failure"); - SEVCHK(ca_add_event(DBR_SHORT, dinp, soft_dinp, mr, NULL),"ca_add_event() failure"); - SEVCHK(ca_pend_io((float) 5.0), "DINP link failure"); - } + struct soft_private *ptr; + + mr = node->pmr; + free(node); + dbScanLock((dbCommon *)mr); + + ptr = (struct soft_private *) mr->dpvt; + Debug(5, "devSoftAux::soft_motor_task: motor %s link type=%d\n", mr->name, mr->dinp.type); + Debug(5, "devSoftAux::soft_motor_task: motor %s constantStr=%s dinp link=%s\n", mr->name, mr->dinp.value.constantStr, mr->dinp.value.pv_link.pvname); + if (((mr->dinp.type == PV_LINK) || + (mr->dinp.type == CA_LINK) || + (mr->dinp.type == DB_LINK)) && + (mr->dinp.value.pv_link.pvname != NULL)) + { + ptr->default_done_behavior = false; + Debug(5, "devSoftAux::soft_motor_task: adding dinp link for motor %s link=%s\n", mr->name, mr->dinp.value.pv_link.pvname); + SEVCHK(ca_search(mr->dinp.value.pv_link.pvname, &dinp), + "ca_search() failure"); + SEVCHK(ca_add_event(DBR_SHORT, dinp, soft_dinp, mr, NULL),"ca_add_event() failure"); + SEVCHK(ca_pend_io((float) 5.0), "DINP link failure"); + } + else + { + ptr->default_done_behavior = true; + } - if (mr->urip != 0) - { - SEVCHK(ca_search(mr->rdbl.value.pv_link.pvname, &rdbl),"ca_search() failure"); - SEVCHK(ca_add_event(DBR_DOUBLE, rdbl, soft_rdbl, mr, NULL),"ca_add_event() failure"); - SEVCHK(ca_pend_io((float) 5.0), "RDBL link failure"); - } - - if (mr->rinp.value.constantStr != NULL) - { - SEVCHK(ca_search(mr->rinp.value.pv_link.pvname, &rinp),"ca_search() failure"); - SEVCHK(ca_add_event(DBR_LONG, rinp, soft_rinp, mr, NULL),"ca_add_event() failure"); - SEVCHK(ca_pend_io((float) 5.0), "RINP link failure"); - } + if ((mr->urip != 0) && + ((mr->rdbl.type == PV_LINK) || + (mr->rdbl.type == CA_LINK) || + (mr->rdbl.type == DB_LINK)) && + (mr->rdbl.value.pv_link.pvname != NULL)) + { + Debug(5, "devSoftAux::soft_motor_task: adding rdbl link for motor %s link=%s\n", mr->name, mr->rdbl.value.pv_link.pvname); + SEVCHK(ca_search(mr->rdbl.value.pv_link.pvname, &rdbl),"ca_search() failure"); + SEVCHK(ca_add_event(DBR_DOUBLE, rdbl, soft_rdbl, mr, NULL),"ca_add_event() failure"); + SEVCHK(ca_pend_io((float) 5.0), "RDBL link failure"); + } + + if (((mr->rinp.type == PV_LINK) || + (mr->rinp.type == CA_LINK) || + (mr->rinp.type == DB_LINK)) && + (mr->rinp.value.pv_link.pvname != NULL)) + { + Debug(5, "devSoftAux::soft_motor_task: adding rinp link for motor %s link=%s\n", mr->name, mr->rinp.value.pv_link.pvname); + SEVCHK(ca_search(mr->rinp.value.pv_link.pvname, &rinp),"ca_search() failure"); + SEVCHK(ca_add_event(DBR_LONG, rinp, soft_rinp, mr, NULL),"ca_add_event() failure"); + SEVCHK(ca_pend_io((float) 5.0), "RINP link failure"); + } + dbScanUnlock((dbCommon *)mr); } ellFree(&soft_motor_list); @@ -203,9 +226,9 @@ STATIC EPICSTHREADFUNC soft_motor_task(void *parm) thread, so as not to show up in the thread list as "SUSPENDED", which is usually a sign of a fault. */ wait_forever = epicsEventCreate(epicsEventEmpty); - if (wait_forever) { - epicsEventMustWait(wait_forever); - } + if (wait_forever) + epicsEventMustWait(wait_forever); + return(NULL); } diff --git a/motorApp/ThorLabsSrc/ThorLabsRegister.cc b/motorApp/ThorLabsSrc/ThorLabsRegister.cc index a9939a1..457af50 100644 --- a/motorApp/ThorLabsSrc/ThorLabsRegister.cc +++ b/motorApp/ThorLabsSrc/ThorLabsRegister.cc @@ -2,9 +2,6 @@ FILENAME... ThorLabslRegister.cc USAGE... Register ThorLabs motor device driver shell commands. -Version: $Revision: 1.1 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2006-09-27 20:32:37 $ */ /***************************************************************** diff --git a/motorApp/ThorLabsSrc/devMDT695.cc b/motorApp/ThorLabsSrc/devMDT695.cc index c46b339..86d1f7d 100644 --- a/motorApp/ThorLabsSrc/devMDT695.cc +++ b/motorApp/ThorLabsSrc/devMDT695.cc @@ -3,9 +3,6 @@ FILENAME... devMDT695.cc USAGE... Motor record device level support for ThorLabs Piezo Control Module (MDT695) -Version: $Revision: 1.2 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2008-03-14 20:23:45 $ */ /* @@ -41,6 +38,7 @@ Last Modified: $Date: 2008-03-14 20:23:45 $ #include #include +#include #include "motorRecord.h" #include "motor.h" #include "motordevCom.h" @@ -53,7 +51,7 @@ extern struct driver_table MDT695_access; /* ----------------Create the dsets for devMDT695----------------- */ STATIC struct driver_table *drvtabptr; -STATIC long MDT695_init(void *); +STATIC long MDT695_init(int); STATIC long MDT695_init_record(void *); STATIC long MDT695_start_trans(struct motorRecord *); STATIC RTN_STATUS MDT695_build_trans(motor_cmnd, double *, struct motorRecord *); @@ -107,12 +105,11 @@ static struct board_stat **MDT695_cards; /* initialize device support for MDT695 stepper motor */ -STATIC long MDT695_init(void *arg) +STATIC long MDT695_init(int after) { long rtnval; - int after = (arg == 0) ? 0 : 1; - if (after == 0) + if (!after) { drvtabptr = &MDT695_access; (drvtabptr->init)(); diff --git a/motorApp/ThorLabsSrc/drvMDT695.cc b/motorApp/ThorLabsSrc/drvMDT695.cc index ad9c7ab..ab2c801 100644 --- a/motorApp/ThorLabsSrc/drvMDT695.cc +++ b/motorApp/ThorLabsSrc/drvMDT695.cc @@ -4,9 +4,6 @@ USAGE... Motor record driver level support for ThorLabs Piezo Control Module (Model: MDT695) Compatable with MDT694, MDT693 -Version: $Revision: 1.4 $ -Modified By: $Author: sluiter $ -Last Modified: $Date: 2009-09-08 18:36:20 $ */ @@ -47,6 +44,8 @@ Last Modified: $Date: 2009-09-08 18:36:20 $ #include #include #include +#include +#include #include "motor.h" #include "ThorLabsRegister.h" #include "drvMDT695.h" @@ -335,7 +334,7 @@ static int set_status(int card, int signal) nodeptr->postmsgptr != 0) { strncpy(send_buff, nodeptr->postmsgptr, 80); - send_mess(card, send_buff, (char) NULL); + send_mess(card, send_buff, (char*) NULL); nodeptr->postmsgptr = NULL; } diff --git a/motorApp/ThorLabsSrc/drvMDT695.h b/motorApp/ThorLabsSrc/drvMDT695.h index 8ebf6ee..fc52029 100644 --- a/motorApp/ThorLabsSrc/drvMDT695.h +++ b/motorApp/ThorLabsSrc/drvMDT695.h @@ -3,9 +3,6 @@ FILENAME... drvMDT695.h USAGE... This file contains ThorLabs Piezo Control Module (MDT695) motorRecord driver information . -Version: $Revision: 1.1 $ -Modified By: $Author: sullivan $ -Last Modified: $Date: 2006-09-27 20:32:37 $ */ /* diff --git a/motorApp/op/adl/4motor_form.adl b/motorApp/op/adl/4motor_form.adl index 195997f..834de3b 100644 --- a/motorApp/op/adl/4motor_form.adl +++ b/motorApp/op/adl/4motor_form.adl @@ -240,58 +240,6 @@ text { textix="(SECONDS)" align="horiz. centered" } -"text entry" { - object { - x=1000 - y=113 - width=50 - height=16 - } - control { - chan="$(P)$(M5).BACC" - clr=14 - bclr=2 - } -} -"text entry" { - object { - x=1000 - y=128 - width=50 - height=16 - } - control { - chan="$(P)$(M6).BACC" - clr=14 - bclr=2 - } -} -"text entry" { - object { - x=1000 - y=143 - width=50 - height=16 - } - control { - chan="$(P)$(M7).BACC" - clr=14 - bclr=2 - } -} -"text entry" { - object { - x=1000 - y=158 - width=50 - height=16 - } - control { - chan="$(P)$(M8).BACC" - clr=14 - bclr=2 - } -} "text entry" { object { x=1000 diff --git a/motorApp/op/adl/ScriptMotorReload.adl b/motorApp/op/adl/ScriptMotorReload.adl new file mode 100644 index 0000000..6f76c4a --- /dev/null +++ b/motorApp/op/adl/ScriptMotorReload.adl @@ -0,0 +1,140 @@ + +file { + name="/home/oxygen40/KLANG/Documents/Projects/Repository/git/motor/motorApp/op/adl/ScriptMotorReload.adl" + version=030107 +} +display { + object { + x=663 + y=227 + width=220 + height=75 + } + clr=14 + bclr=4 + cmap="" + gridSpacing=5 + gridOn=0 + snapToGrid=0 +} +"color map" { + ncolors=65 + colors { + ffffff, + ececec, + dadada, + c8c8c8, + bbbbbb, + aeaeae, + 9e9e9e, + 919191, + 858585, + 787878, + 696969, + 5a5a5a, + 464646, + 2d2d2d, + 000000, + 00d800, + 1ebb00, + 339900, + 2d7f00, + 216c00, + fd0000, + de1309, + be190b, + a01207, + 820400, + 5893ff, + 597ee1, + 4b6ec7, + 3a5eab, + 27548d, + fbf34a, + f9da3c, + eeb62b, + e19015, + cd6100, + ffb0ff, + d67fe2, + ae4ebc, + 8b1a96, + 610a75, + a4aaff, + 8793e2, + 6a73c1, + 4d52a4, + 343386, + c7bb6d, + b79d5c, + a47e3c, + 7d5627, + 58340f, + 99ffff, + 73dfff, + 4ea5f9, + 2a63e4, + 0a00b8, + ebf1b5, + d4db9d, + bbc187, + a6a462, + 8b8239, + 73ff6b, + 52da3b, + 3cb420, + 289315, + 1a7309, + } +} +rectangle { + object { + x=0 + y=0 + width=250 + height=25 + } + "basic attribute" { + clr=29 + } +} +"message button" { + object { + x=10 + y=35 + width=200 + height=30 + } + control { + chan="$(P)$(PORT):ScriptReload" + clr=14 + bclr=62 + } + label="Reload $(PORT)" + press_msg="1" +} +rectangle { + object { + x=-7 + y=-7 + width=257 + height=32 + } + "basic attribute" { + clr=14 + fill="outline" + width=3 + } +} +text { + object { + x=5 + y=3 + width=200 + height=20 + } + "basic attribute" { + clr=0 + } + textix="Script Motor Reload" +} diff --git a/motorApp/op/adl/XPSPositionCompare.adl b/motorApp/op/adl/XPSPositionCompare.adl new file mode 100644 index 0000000..4823ea3 --- /dev/null +++ b/motorApp/op/adl/XPSPositionCompare.adl @@ -0,0 +1,522 @@ + +file { + name="/home/epics/devel/motor/motorApp/op/adl/XPSPositionCompare.adl" + version=030107 +} +display { + object { + x=428 + y=115 + width=880 + height=140 + } + clr=14 + bclr=4 + cmap="" + gridSpacing=5 + gridOn=0 + snapToGrid=0 +} +"color map" { + ncolors=65 + colors { + ffffff, + ececec, + dadada, + c8c8c8, + bbbbbb, + aeaeae, + 9e9e9e, + 919191, + 858585, + 787878, + 696969, + 5a5a5a, + 464646, + 2d2d2d, + 000000, + 00d800, + 1ebb00, + 339900, + 2d7f00, + 216c00, + fd0000, + de1309, + be190b, + a01207, + 820400, + 5893ff, + 597ee1, + 4b6ec7, + 3a5eab, + 27548d, + fbf34a, + f9da3c, + eeb62b, + e19015, + cd6100, + ffb0ff, + d67fe2, + ae4ebc, + 8b1a96, + 610a75, + a4aaff, + 8793e2, + 6a73c1, + 4d52a4, + 343386, + c7bb6d, + b79d5c, + a47e3c, + 7d5627, + 58340f, + 99ffff, + 73dfff, + 4ea5f9, + 2a63e4, + 0a00b8, + ebf1b5, + d4db9d, + bbc187, + a6a462, + 8b8239, + 73ff6b, + 52da3b, + 3cb420, + 289315, + 1a7309, + } +} +text { + object { + x=33 + y=56 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Description" + align="horiz. centered" +} +text { + object { + x=38 + y=40 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Motor" + align="horiz. centered" +} +text { + object { + x=282 + y=5 + width=286 + height=26 + } + "basic attribute" { + clr=14 + fill="outline" + } + textix="XPS Position Compare" + align="horiz. centered" +} +polyline { + object { + x=2 + y=34 + width=880 + height=0 + } + "basic attribute" { + clr=14 + fill="outline" + } + points { + (2,34) + (882,34) + } +} +text { + object { + x=215 + y=56 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Enable" + align="horiz. centered" +} +rectangle { + object { + x=5 + y=80 + width=870 + height=55 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=10 + y=110 + width=200 + height=20 + } + monitor { + chan="$(P)$(M1).DESC" + clr=14 + bclr=45 + } + limits { + } +} +menu { + object { + x=215 + y=110 + width=130 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareMode" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=215 + y=88 + width=130 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareMode_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text entry" { + object { + x=560 + y=110 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareStepSize" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +menu { + object { + x=665 + y=110 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionComparePulseWidth" + clr=14 + bclr=51 + } +} +menu { + object { + x=770 + y=110 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareSettlingTime" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=560 + y=88 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareStepSize_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=665 + y=88 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionComparePulseWidth_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=770 + y=88 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareSettlingTime_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text entry" { + object { + x=350 + y=110 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareMinPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text update" { + object { + x=350 + y=88 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareMinPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text entry" { + object { + x=455 + y=110 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareMaxPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text update" { + object { + x=455 + y=88 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareMaxPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +composite { + object { + x=350 + y=40 + width=520 + height=36 + } + "composite name"="" + children { + text { + object { + x=350 + y=56 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Mode" + align="horiz. centered" + } + text { + object { + x=455 + y=56 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Position" + align="horiz. centered" + } + text { + object { + x=560 + y=56 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Size" + align="horiz. centered" + } + text { + object { + x=350 + y=40 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Minimum" + align="horiz. centered" + } + text { + object { + x=455 + y=40 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Maximum" + align="horiz. centered" + } + text { + object { + x=560 + y=40 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Step" + align="horiz. centered" + } + text { + object { + x=665 + y=56 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Width (us)" + align="horiz. centered" + } + text { + object { + x=665 + y=40 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Pulse" + align="horiz. centered" + } + text { + object { + x=770 + y=56 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Time (us)" + align="horiz. centered" + } + text { + object { + x=770 + y=40 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Settling" + align="horiz. centered" + } + } +} diff --git a/motorApp/op/adl/XPSPositionCompare8.adl b/motorApp/op/adl/XPSPositionCompare8.adl new file mode 100644 index 0000000..c21af6b --- /dev/null +++ b/motorApp/op/adl/XPSPositionCompare8.adl @@ -0,0 +1,2191 @@ + +file { + name="/home/epics/devel/motor/motorApp/op/adl/XPSPositionCompare8.adl" + version=030107 +} +display { + object { + x=428 + y=115 + width=880 + height=560 + } + clr=14 + bclr=4 + cmap="" + gridSpacing=5 + gridOn=0 + snapToGrid=0 +} +"color map" { + ncolors=65 + colors { + ffffff, + ececec, + dadada, + c8c8c8, + bbbbbb, + aeaeae, + 9e9e9e, + 919191, + 858585, + 787878, + 696969, + 5a5a5a, + 464646, + 2d2d2d, + 000000, + 00d800, + 1ebb00, + 339900, + 2d7f00, + 216c00, + fd0000, + de1309, + be190b, + a01207, + 820400, + 5893ff, + 597ee1, + 4b6ec7, + 3a5eab, + 27548d, + fbf34a, + f9da3c, + eeb62b, + e19015, + cd6100, + ffb0ff, + d67fe2, + ae4ebc, + 8b1a96, + 610a75, + a4aaff, + 8793e2, + 6a73c1, + 4d52a4, + 343386, + c7bb6d, + b79d5c, + a47e3c, + 7d5627, + 58340f, + 99ffff, + 73dfff, + 4ea5f9, + 2a63e4, + 0a00b8, + ebf1b5, + d4db9d, + bbc187, + a6a462, + 8b8239, + 73ff6b, + 52da3b, + 3cb420, + 289315, + 1a7309, + } +} +text { + object { + x=33 + y=56 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Description" + align="horiz. centered" +} +text { + object { + x=38 + y=40 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Motor" + align="horiz. centered" +} +text { + object { + x=282 + y=5 + width=286 + height=26 + } + "basic attribute" { + clr=14 + fill="outline" + } + textix="XPS Position Compare" + align="horiz. centered" +} +polyline { + object { + x=2 + y=34 + width=880 + height=0 + } + "basic attribute" { + clr=14 + fill="outline" + } + points { + (2,34) + (882,34) + } +} +"text update" { + object { + x=10 + y=110 + width=200 + height=20 + } + monitor { + chan="$(P)$(M1).DESC" + clr=14 + bclr=45 + } + limits { + } +} +rectangle { + object { + x=4 + y=140 + width=840 + height=55 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=9 + y=170 + width=200 + height=20 + } + monitor { + chan="$(P)$(M1).DESC" + clr=14 + bclr=45 + } + limits { + } +} +"text update" { + object { + x=10 + y=170 + width=200 + height=20 + } + monitor { + chan="$(P)$(M2).DESC" + clr=14 + bclr=45 + } + limits { + } +} +"text update" { + object { + x=10 + y=230 + width=200 + height=20 + } + monitor { + chan="$(P)$(M3).DESC" + clr=14 + bclr=45 + } + limits { + } +} +"text update" { + object { + x=10 + y=290 + width=200 + height=20 + } + monitor { + chan="$(P)$(M4).DESC" + clr=14 + bclr=45 + } + limits { + } +} +"text update" { + object { + x=10 + y=350 + width=200 + height=20 + } + monitor { + chan="$(P)$(M5).DESC" + clr=14 + bclr=45 + } + limits { + } +} +"text update" { + object { + x=10 + y=410 + width=200 + height=20 + } + monitor { + chan="$(P)$(M6).DESC" + clr=14 + bclr=45 + } + limits { + } +} +"text update" { + object { + x=10 + y=470 + width=200 + height=20 + } + monitor { + chan="$(P)$(M7).DESC" + clr=14 + bclr=45 + } + limits { + } +} +"text update" { + object { + x=10 + y=530 + width=200 + height=20 + } + monitor { + chan="$(P)$(M8).DESC" + clr=14 + bclr=45 + } + limits { + } +} +text { + object { + x=215 + y=56 + width=129 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Mode" + align="horiz. centered" +} +menu { + object { + x=215 + y=110 + width=129 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareMode" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=215 + y=88 + width=129 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareMode_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +menu { + object { + x=214 + y=170 + width=129 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareMode" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=214 + y=148 + width=129 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareMode_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +menu { + object { + x=215 + y=170 + width=129 + height=20 + } + control { + chan="$(P)$(M2)PositionCompareMode" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=215 + y=148 + width=129 + height=18 + } + monitor { + chan="$(P)$(M2)PositionCompareMode_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +menu { + object { + x=215 + y=230 + width=129 + height=20 + } + control { + chan="$(P)$(M3)PositionCompareMode" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=215 + y=208 + width=129 + height=18 + } + monitor { + chan="$(P)$(M3)PositionCompareMode_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +menu { + object { + x=215 + y=290 + width=129 + height=20 + } + control { + chan="$(P)$(M4)PositionCompareMode" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=215 + y=268 + width=129 + height=18 + } + monitor { + chan="$(P)$(M4)PositionCompareMode_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +menu { + object { + x=215 + y=350 + width=129 + height=20 + } + control { + chan="$(P)$(M5)PositionCompareMode" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=215 + y=328 + width=129 + height=18 + } + monitor { + chan="$(P)$(M5)PositionCompareMode_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +menu { + object { + x=215 + y=410 + width=129 + height=20 + } + control { + chan="$(P)$(M6)PositionCompareMode" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=215 + y=388 + width=129 + height=18 + } + monitor { + chan="$(P)$(M6)PositionCompareMode_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +menu { + object { + x=215 + y=470 + width=129 + height=20 + } + control { + chan="$(P)$(M7)PositionCompareMode" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=215 + y=448 + width=129 + height=18 + } + monitor { + chan="$(P)$(M7)PositionCompareMode_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +menu { + object { + x=215 + y=530 + width=129 + height=20 + } + control { + chan="$(P)$(M8)PositionCompareMode" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=215 + y=508 + width=129 + height=18 + } + monitor { + chan="$(P)$(M8)PositionCompareMode_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +text { + object { + x=350 + y=56 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Position" + align="horiz. centered" +} +text { + object { + x=455 + y=56 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Position" + align="horiz. centered" +} +text { + object { + x=560 + y=56 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Size" + align="horiz. centered" +} +text { + object { + x=350 + y=40 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Minimum" + align="horiz. centered" +} +text { + object { + x=455 + y=40 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Maximum" + align="horiz. centered" +} +text { + object { + x=560 + y=40 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Step" + align="horiz. centered" +} +text { + object { + x=665 + y=56 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Width (us)" + align="horiz. centered" +} +text { + object { + x=665 + y=40 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Pulse" + align="horiz. centered" +} +text { + object { + x=770 + y=56 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Time (us)" + align="horiz. centered" +} +text { + object { + x=770 + y=40 + width=100 + height=20 + } + "basic attribute" { + clr=54 + fill="outline" + } + textix="Settling" + align="horiz. centered" +} +"text entry" { + object { + x=350 + y=110 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareMinPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=455 + y=110 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareMaxPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=560 + y=110 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareStepSize" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +menu { + object { + x=665 + y=110 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionComparePulseWidth" + clr=14 + bclr=51 + } +} +menu { + object { + x=770 + y=110 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareSettlingTime" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=350 + y=88 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareMinPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=455 + y=88 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareMaxPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=560 + y=88 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareStepSize_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=665 + y=88 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionComparePulseWidth_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=770 + y=88 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareSettlingTime_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text entry" { + object { + x=349 + y=170 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareMinPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=454 + y=170 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareMaxPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=559 + y=170 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareStepSize" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +menu { + object { + x=664 + y=170 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionComparePulseWidth" + clr=14 + bclr=51 + } +} +menu { + object { + x=769 + y=170 + width=100 + height=20 + } + control { + chan="$(P)$(M1)PositionCompareSettlingTime" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=349 + y=148 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareMinPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=454 + y=148 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareMaxPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=559 + y=148 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareStepSize_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=664 + y=148 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionComparePulseWidth_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=769 + y=148 + width=100 + height=18 + } + monitor { + chan="$(P)$(M1)PositionCompareSettlingTime_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text entry" { + object { + x=350 + y=170 + width=100 + height=20 + } + control { + chan="$(P)$(M2)PositionCompareMinPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=455 + y=170 + width=100 + height=20 + } + control { + chan="$(P)$(M2)PositionCompareMaxPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=560 + y=170 + width=100 + height=20 + } + control { + chan="$(P)$(M2)PositionCompareStepSize" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +menu { + object { + x=665 + y=170 + width=100 + height=20 + } + control { + chan="$(P)$(M2)PositionComparePulseWidth" + clr=14 + bclr=51 + } +} +menu { + object { + x=770 + y=170 + width=100 + height=20 + } + control { + chan="$(P)$(M2)PositionCompareSettlingTime" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=350 + y=148 + width=100 + height=18 + } + monitor { + chan="$(P)$(M2)PositionCompareMinPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=455 + y=148 + width=100 + height=18 + } + monitor { + chan="$(P)$(M2)PositionCompareMaxPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=560 + y=148 + width=100 + height=18 + } + monitor { + chan="$(P)$(M2)PositionCompareStepSize_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=665 + y=148 + width=100 + height=18 + } + monitor { + chan="$(P)$(M2)PositionComparePulseWidth_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=770 + y=148 + width=100 + height=18 + } + monitor { + chan="$(P)$(M2)PositionCompareSettlingTime_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text entry" { + object { + x=350 + y=230 + width=100 + height=20 + } + control { + chan="$(P)$(M3)PositionCompareMinPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=455 + y=230 + width=100 + height=20 + } + control { + chan="$(P)$(M3)PositionCompareMaxPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=560 + y=230 + width=100 + height=20 + } + control { + chan="$(P)$(M3)PositionCompareStepSize" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +menu { + object { + x=665 + y=230 + width=100 + height=20 + } + control { + chan="$(P)$(M3)PositionComparePulseWidth" + clr=14 + bclr=51 + } +} +menu { + object { + x=770 + y=230 + width=100 + height=20 + } + control { + chan="$(P)$(M3)PositionCompareSettlingTime" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=350 + y=208 + width=100 + height=18 + } + monitor { + chan="$(P)$(M3)PositionCompareMinPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=455 + y=208 + width=100 + height=18 + } + monitor { + chan="$(P)$(M3)PositionCompareMaxPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=560 + y=208 + width=100 + height=18 + } + monitor { + chan="$(P)$(M3)PositionCompareStepSize_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=665 + y=208 + width=100 + height=18 + } + monitor { + chan="$(P)$(M3)PositionComparePulseWidth_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=770 + y=208 + width=100 + height=18 + } + monitor { + chan="$(P)$(M3)PositionCompareSettlingTime_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text entry" { + object { + x=350 + y=290 + width=100 + height=20 + } + control { + chan="$(P)$(M4)PositionCompareMinPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=455 + y=290 + width=100 + height=20 + } + control { + chan="$(P)$(M4)PositionCompareMaxPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=560 + y=290 + width=100 + height=20 + } + control { + chan="$(P)$(M4)PositionCompareStepSize" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +menu { + object { + x=665 + y=290 + width=100 + height=20 + } + control { + chan="$(P)$(M4)PositionComparePulseWidth" + clr=14 + bclr=51 + } +} +menu { + object { + x=770 + y=290 + width=100 + height=20 + } + control { + chan="$(P)$(M4)PositionCompareSettlingTime" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=350 + y=268 + width=100 + height=18 + } + monitor { + chan="$(P)$(M4)PositionCompareMinPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=455 + y=268 + width=100 + height=18 + } + monitor { + chan="$(P)$(M4)PositionCompareMaxPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=560 + y=268 + width=100 + height=18 + } + monitor { + chan="$(P)$(M4)PositionCompareStepSize_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=665 + y=268 + width=100 + height=18 + } + monitor { + chan="$(P)$(M4)PositionComparePulseWidth_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=770 + y=268 + width=100 + height=18 + } + monitor { + chan="$(P)$(M4)PositionCompareSettlingTime_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text entry" { + object { + x=350 + y=350 + width=100 + height=20 + } + control { + chan="$(P)$(M5)PositionCompareMinPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=455 + y=350 + width=100 + height=20 + } + control { + chan="$(P)$(M5)PositionCompareMaxPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=560 + y=350 + width=100 + height=20 + } + control { + chan="$(P)$(M5)PositionCompareStepSize" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +menu { + object { + x=665 + y=350 + width=100 + height=20 + } + control { + chan="$(P)$(M5)PositionComparePulseWidth" + clr=14 + bclr=51 + } +} +menu { + object { + x=770 + y=350 + width=100 + height=20 + } + control { + chan="$(P)$(M5)PositionCompareSettlingTime" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=350 + y=328 + width=100 + height=18 + } + monitor { + chan="$(P)$(M5)PositionCompareMinPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=455 + y=328 + width=100 + height=18 + } + monitor { + chan="$(P)$(M5)PositionCompareMaxPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=560 + y=328 + width=100 + height=18 + } + monitor { + chan="$(P)$(M5)PositionCompareStepSize_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=665 + y=328 + width=100 + height=18 + } + monitor { + chan="$(P)$(M5)PositionComparePulseWidth_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=770 + y=328 + width=100 + height=18 + } + monitor { + chan="$(P)$(M5)PositionCompareSettlingTime_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text entry" { + object { + x=350 + y=410 + width=100 + height=20 + } + control { + chan="$(P)$(M6)PositionCompareMinPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=455 + y=410 + width=100 + height=20 + } + control { + chan="$(P)$(M6)PositionCompareMaxPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=560 + y=410 + width=100 + height=20 + } + control { + chan="$(P)$(M6)PositionCompareStepSize" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +menu { + object { + x=665 + y=410 + width=100 + height=20 + } + control { + chan="$(P)$(M6)PositionComparePulseWidth" + clr=14 + bclr=51 + } +} +menu { + object { + x=770 + y=410 + width=100 + height=20 + } + control { + chan="$(P)$(M6)PositionCompareSettlingTime" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=350 + y=388 + width=100 + height=18 + } + monitor { + chan="$(P)$(M6)PositionCompareMinPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=455 + y=388 + width=100 + height=18 + } + monitor { + chan="$(P)$(M6)PositionCompareMaxPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=560 + y=388 + width=100 + height=18 + } + monitor { + chan="$(P)$(M6)PositionCompareStepSize_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=665 + y=388 + width=100 + height=18 + } + monitor { + chan="$(P)$(M6)PositionComparePulseWidth_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=770 + y=388 + width=100 + height=18 + } + monitor { + chan="$(P)$(M6)PositionCompareSettlingTime_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text entry" { + object { + x=350 + y=470 + width=100 + height=20 + } + control { + chan="$(P)$(M7)PositionCompareMinPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=455 + y=470 + width=100 + height=20 + } + control { + chan="$(P)$(M7)PositionCompareMaxPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=560 + y=470 + width=100 + height=20 + } + control { + chan="$(P)$(M7)PositionCompareStepSize" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +menu { + object { + x=665 + y=470 + width=100 + height=20 + } + control { + chan="$(P)$(M7)PositionComparePulseWidth" + clr=14 + bclr=51 + } +} +menu { + object { + x=770 + y=470 + width=100 + height=20 + } + control { + chan="$(P)$(M7)PositionCompareSettlingTime" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=350 + y=448 + width=100 + height=18 + } + monitor { + chan="$(P)$(M7)PositionCompareMinPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=455 + y=448 + width=100 + height=18 + } + monitor { + chan="$(P)$(M7)PositionCompareMaxPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=560 + y=448 + width=100 + height=18 + } + monitor { + chan="$(P)$(M7)PositionCompareStepSize_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=665 + y=448 + width=100 + height=18 + } + monitor { + chan="$(P)$(M7)PositionComparePulseWidth_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=770 + y=448 + width=100 + height=18 + } + monitor { + chan="$(P)$(M7)PositionCompareSettlingTime_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text entry" { + object { + x=350 + y=530 + width=100 + height=20 + } + control { + chan="$(P)$(M8)PositionCompareMinPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=455 + y=530 + width=100 + height=20 + } + control { + chan="$(P)$(M8)PositionCompareMaxPosition" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +"text entry" { + object { + x=560 + y=530 + width=100 + height=20 + } + control { + chan="$(P)$(M8)PositionCompareStepSize" + clr=14 + bclr=51 + } + clrmod="discrete" + limits { + } +} +menu { + object { + x=665 + y=530 + width=100 + height=20 + } + control { + chan="$(P)$(M8)PositionComparePulseWidth" + clr=14 + bclr=51 + } +} +menu { + object { + x=770 + y=530 + width=100 + height=20 + } + control { + chan="$(P)$(M8)PositionCompareSettlingTime" + clr=14 + bclr=51 + } +} +"text update" { + object { + x=350 + y=508 + width=100 + height=18 + } + monitor { + chan="$(P)$(M8)PositionCompareMinPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=455 + y=508 + width=100 + height=18 + } + monitor { + chan="$(P)$(M8)PositionCompareMaxPosition_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=560 + y=508 + width=100 + height=18 + } + monitor { + chan="$(P)$(M8)PositionCompareStepSize_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=665 + y=508 + width=100 + height=18 + } + monitor { + chan="$(P)$(M8)PositionComparePulseWidth_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +"text update" { + object { + x=770 + y=508 + width=100 + height=18 + } + monitor { + chan="$(P)$(M8)PositionCompareSettlingTime_RBV" + clr=54 + bclr=4 + } + align="horiz. centered" + limits { + } +} +rectangle { + object { + x=5 + y=80 + width=870 + height=55 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +rectangle { + object { + x=5 + y=140 + width=870 + height=55 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +rectangle { + object { + x=5 + y=200 + width=870 + height=55 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +rectangle { + object { + x=5 + y=260 + width=870 + height=55 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +rectangle { + object { + x=5 + y=320 + width=870 + height=55 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +rectangle { + object { + x=5 + y=380 + width=870 + height=55 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +rectangle { + object { + x=5 + y=440 + width=870 + height=55 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +rectangle { + object { + x=5 + y=500 + width=870 + height=55 + } + "basic attribute" { + clr=14 + fill="outline" + } +} diff --git a/motorApp/op/adl/XPSTest.adl b/motorApp/op/adl/XPSTest.adl deleted file mode 100644 index d1087f4..0000000 --- a/motorApp/op/adl/XPSTest.adl +++ /dev/null @@ -1,170 +0,0 @@ - -file { - name="/home/epics/devel/motor/5-9beta/motorApp/op/adl/XPSTest.adl" - version=030000 -} -display { - object { - x=537 - y=30 - width=200 - height=175 - } - clr=14 - bclr=4 - cmap="" - gridSpacing=5 - gridOn=0 - snapToGrid=0 -} -"color map" { - ncolors=65 - colors { - ffffff, - ececec, - dadada, - c8c8c8, - bbbbbb, - aeaeae, - 9e9e9e, - 919191, - 858585, - 787878, - 696969, - 5a5a5a, - 464646, - 2d2d2d, - 000000, - 00d800, - 1ebb00, - 339900, - 2d7f00, - 216c00, - fd0000, - de1309, - be190b, - a01207, - 820400, - 5893ff, - 597ee1, - 4b6ec7, - 3a5eab, - 27548d, - fbf34a, - f9da3c, - eeb62b, - e19015, - cd6100, - ffb0ff, - d67fe2, - ae4ebc, - 8b1a96, - 610a75, - a4aaff, - 8793e2, - 6a73c1, - 4d52a4, - 343386, - c7bb6d, - b79d5c, - a47e3c, - 7d5627, - 58340f, - 99ffff, - 73dfff, - 4ea5f9, - 2a63e4, - 0a00b8, - ebf1b5, - d4db9d, - bbc187, - a6a462, - 8b8239, - 73ff6b, - 52da3b, - 3cb420, - 289315, - 1a7309, - } -} -"related display" { - object { - x=25 - y=104 - width=150 - height=25 - } - display[0] { - label="Motor 1" - name="XPSExtra.adl" - args="P=IOC:, M1=m1" - } - display[1] { - label="Motor 2" - name="XPSExtra.adl" - args="P=IOC:, M1=m2" - } - clr=14 - bclr=4 - label="Extra motor PVs" -} -"related display" { - object { - x=25 - y=134 - width=150 - height=25 - } - display[0] { - label="XPS Trajectory Scan" - name="trajectoryScan.adl" - args="P=IOC:, R=traj1, TITLE=XPS_trajectory,M1=m1,M2=m2" - } - clr=14 - bclr=4 - label="Trajectory scan" -} -"related display" { - object { - x=25 - y=74 - width=150 - height=25 - } - display[0] { - label="XPS Auxilliary" - name="XPSAux.adl" - args="P=IOC:, R=XPSAux" - } - clr=14 - bclr=4 - label="Auxilliary I/O" -} -text { - object { - x=6 - y=11 - width=150 - height=25 - } - "basic attribute" { - clr=14 - } - textix="Newport XPS Test" -} -"related display" { - object { - x=25 - y=44 - width=150 - height=25 - } - display[0] { - label="Motors" - name="motor3x.adl" - args="P=IOC:, M1=m1, M2=m2, M3=m3" - } - clr=14 - bclr=4 - label="Motors" -} diff --git a/motorApp/op/adl/XPSTop.adl b/motorApp/op/adl/XPSTop.adl index 0f6e8d0..094c1e5 100644 --- a/motorApp/op/adl/XPSTop.adl +++ b/motorApp/op/adl/XPSTop.adl @@ -1,14 +1,14 @@ file { name="/home/epics/devel/motor/motorApp/op/adl/XPSTop.adl" - version=030102 + version=030107 } display { object { x=833 y=53 width=200 - height=175 + height=205 } clr=14 bclr=4 @@ -168,3 +168,19 @@ text { bclr=4 label="Motors" } +"related display" { + object { + x=25 + y=164 + width=150 + height=25 + } + display[0] { + label="XPS Position Compare" + name="XPSPositionCompare8.adl" + args="P=IOC:, R=PC1:, TITLE=XPSProfileMove, M1=m1,M2=m2,M3=m3,M4=m4,M5=m5,M6=m6,M7=m7,M8=m8" + } + clr=14 + bclr=4 + label="Position compare" +} diff --git a/motorApp/op/adl/motorStatus120.adl b/motorApp/op/adl/motorStatus120.adl new file mode 100644 index 0000000..e6ce52e --- /dev/null +++ b/motorApp/op/adl/motorStatus120.adl @@ -0,0 +1,20891 @@ + +file { + name="/home/oxygen/GOETZE/epics/synAppsSVN/support/motor/motorApp/op/adl/motorStatus120.adl" + version=030107 +} +display { + object { + x=697 + y=519 + width=680 + height=310 + } + clr=7 + bclr=2 + cmap="" + gridSpacing=5 + gridOn=0 + snapToGrid=1 +} +"color map" { + ncolors=65 + colors { + ffffff, + ececec, + dadada, + c8c8c8, + bbbbbb, + aeaeae, + 9e9e9e, + 919191, + 858585, + 787878, + 696969, + 5a5a5a, + 464646, + 2d2d2d, + 000000, + 00d800, + 1ebb00, + 339900, + 2d7f00, + 216c00, + fd0000, + de1309, + be190b, + a01207, + 820400, + 5893ff, + 597ee1, + 4b6ec7, + 3a5eab, + 27548d, + fbf34a, + f9da3c, + eeb62b, + e19015, + cd6100, + ffb0ff, + d67fe2, + ae4ebc, + 8b1a96, + 610a75, + a4aaff, + 8793e2, + 6a73c1, + 4d52a4, + 343386, + c7bb6d, + b79d5c, + a47e3c, + 7d5627, + 58340f, + 99ffff, + 73dfff, + 4ea5f9, + 2a63e4, + 0a00b8, + ebf1b5, + d4db9d, + bbc187, + a6a462, + 8b8239, + 73ff6b, + 52da3b, + 3cb420, + 289315, + 1a7309, + } +} +text { + object { + x=38 + y=0 + width=590 + height=20 + } + "basic attribute" { + clr=14 + } + textix=" $(P) motor status" + align="horiz. centered" +} +composite { + object { + x=364 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=364 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=365 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m68.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=399 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m68_able.VAL" + } + } + rectangle { + object { + x=389 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m68.LLS" + } + } + rectangle { + object { + x=389 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m68.LVIO" + } + } + rectangle { + object { + x=389 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m68.HLS" + } + } + composite { + object { + x=365 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=365 + y=139 + width=24 + height=12 + } + display[0] { + label="m68" + name="motorx_more.adl" + args="P=$(P),M=m68" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=365 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m68.DMOV" + } + } + rectangle { + object { + x=365 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=365 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="68" + align="horiz. centered" + } + } + } + "text update" { + object { + x=365 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m68.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=319 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=319 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=320 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m60.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=354 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m60_able.VAL" + } + } + rectangle { + object { + x=344 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m60.LLS" + } + } + rectangle { + object { + x=344 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m60.LVIO" + } + } + rectangle { + object { + x=344 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m60.HLS" + } + } + composite { + object { + x=320 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=320 + y=139 + width=24 + height=12 + } + display[0] { + label="m60" + name="motorx_more.adl" + args="P=$(P),M=m60" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=320 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m60.DMOV" + } + } + rectangle { + object { + x=320 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=320 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="60" + align="horiz. centered" + } + } + } + "text update" { + object { + x=320 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m60.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=364 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=364 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=365 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m65.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=399 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m65_able.VAL" + } + } + rectangle { + object { + x=389 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m65.LLS" + } + } + rectangle { + object { + x=389 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m65.LVIO" + } + } + rectangle { + object { + x=389 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m65.HLS" + } + } + composite { + object { + x=365 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=365 + y=31 + width=24 + height=12 + } + display[0] { + label="m65" + name="motorx_more.adl" + args="P=$(P),M=m65" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=365 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m65.DMOV" + } + } + rectangle { + object { + x=365 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=365 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="65" + align="horiz. centered" + } + } + } + "text update" { + object { + x=365 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m65.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=364 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=364 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=365 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m66.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=399 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m66_able.VAL" + } + } + rectangle { + object { + x=389 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m66.LLS" + } + } + rectangle { + object { + x=389 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m66.LVIO" + } + } + rectangle { + object { + x=389 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m66.HLS" + } + } + composite { + object { + x=365 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=365 + y=67 + width=24 + height=12 + } + display[0] { + label="m66" + name="motorx_more.adl" + args="P=$(P),M=m66" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=365 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m66.DMOV" + } + } + rectangle { + object { + x=365 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=365 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="66" + align="horiz. centered" + } + } + } + "text update" { + object { + x=365 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m66.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=364 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=364 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=365 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m67.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=399 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m67_able.VAL" + } + } + rectangle { + object { + x=389 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m67.LLS" + } + } + rectangle { + object { + x=389 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m67.LVIO" + } + } + rectangle { + object { + x=389 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m67.HLS" + } + } + composite { + object { + x=365 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=365 + y=103 + width=24 + height=12 + } + display[0] { + label="m67" + name="motorx_more.adl" + args="P=$(P),M=m67" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=365 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m67.DMOV" + } + } + rectangle { + object { + x=365 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=365 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="67" + align="horiz. centered" + } + } + } + "text update" { + object { + x=365 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m67.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=319 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=319 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=320 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m57.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=354 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m57_able.VAL" + } + } + rectangle { + object { + x=344 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m57.LLS" + } + } + rectangle { + object { + x=344 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m57.LVIO" + } + } + rectangle { + object { + x=344 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m57.HLS" + } + } + composite { + object { + x=320 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=320 + y=31 + width=24 + height=12 + } + display[0] { + label="m57" + name="motorx_more.adl" + args="P=$(P),M=m57" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=320 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m57.DMOV" + } + } + rectangle { + object { + x=320 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=320 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="57" + align="horiz. centered" + } + } + } + "text update" { + object { + x=320 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m57.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=319 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=319 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=320 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m58.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=354 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m58_able.VAL" + } + } + rectangle { + object { + x=344 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m58.LLS" + } + } + rectangle { + object { + x=344 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m58.LVIO" + } + } + rectangle { + object { + x=344 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m58.HLS" + } + } + composite { + object { + x=320 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=320 + y=67 + width=24 + height=12 + } + display[0] { + label="m58" + name="motorx_more.adl" + args="P=$(P),M=m58" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=320 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m58.DMOV" + } + } + rectangle { + object { + x=320 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=320 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="58" + align="horiz. centered" + } + } + } + "text update" { + object { + x=320 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m58.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=319 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=319 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=320 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m59.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=354 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m59_able.VAL" + } + } + rectangle { + object { + x=344 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m59.LLS" + } + } + rectangle { + object { + x=344 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m59.LVIO" + } + } + rectangle { + object { + x=344 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m59.HLS" + } + } + composite { + object { + x=320 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=320 + y=103 + width=24 + height=12 + } + display[0] { + label="m59" + name="motorx_more.adl" + args="P=$(P),M=m59" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=320 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m59.DMOV" + } + } + rectangle { + object { + x=320 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=320 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="59" + align="horiz. centered" + } + } + } + "text update" { + object { + x=320 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m59.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=319 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=319 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=320 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m61.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=354 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m61_able.VAL" + } + } + rectangle { + object { + x=344 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m61.LLS" + } + } + rectangle { + object { + x=344 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m61.LVIO" + } + } + rectangle { + object { + x=344 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m61.HLS" + } + } + composite { + object { + x=320 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=320 + y=175 + width=24 + height=12 + } + display[0] { + label="m61" + name="motorx_more.adl" + args="P=$(P),M=m61" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=320 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m61.DMOV" + } + } + rectangle { + object { + x=320 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=320 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="61" + align="horiz. centered" + } + } + } + "text update" { + object { + x=320 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m61.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=364 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=364 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=365 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m69.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=399 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m69_able.VAL" + } + } + rectangle { + object { + x=389 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m69.LLS" + } + } + rectangle { + object { + x=389 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m69.LVIO" + } + } + rectangle { + object { + x=389 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m69.HLS" + } + } + composite { + object { + x=365 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=365 + y=175 + width=24 + height=12 + } + display[0] { + label="m69" + name="motorx_more.adl" + args="P=$(P),M=m69" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=365 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m69.DMOV" + } + } + rectangle { + object { + x=365 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=365 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="69" + align="horiz. centered" + } + } + } + "text update" { + object { + x=365 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m69.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=364 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=364 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=365 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m70.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=399 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m70_able.VAL" + } + } + rectangle { + object { + x=389 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m70.LLS" + } + } + rectangle { + object { + x=389 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m70.LVIO" + } + } + rectangle { + object { + x=389 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m70.HLS" + } + } + composite { + object { + x=365 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=365 + y=211 + width=24 + height=12 + } + display[0] { + label="m70" + name="motorx_more.adl" + args="P=$(P),M=m70" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=365 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m70.DMOV" + } + } + rectangle { + object { + x=365 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=365 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="70" + align="horiz. centered" + } + } + } + "text update" { + object { + x=365 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m70.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=319 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=319 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=320 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m62.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=354 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m62_able.VAL" + } + } + rectangle { + object { + x=344 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m62.LLS" + } + } + rectangle { + object { + x=344 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m62.LVIO" + } + } + rectangle { + object { + x=344 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m62.HLS" + } + } + composite { + object { + x=320 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=320 + y=211 + width=24 + height=12 + } + display[0] { + label="m62" + name="motorx_more.adl" + args="P=$(P),M=m62" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=320 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m62.DMOV" + } + } + rectangle { + object { + x=320 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=320 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="62" + align="horiz. centered" + } + } + } + "text update" { + object { + x=320 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m62.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=319 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=319 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=320 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m63.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=354 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m63_able.VAL" + } + } + rectangle { + object { + x=344 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m63.LLS" + } + } + rectangle { + object { + x=344 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m63.LVIO" + } + } + rectangle { + object { + x=344 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m63.HLS" + } + } + composite { + object { + x=320 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=320 + y=247 + width=24 + height=12 + } + display[0] { + label="m63" + name="motorx_more.adl" + args="P=$(P),M=m63" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=320 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m63.DMOV" + } + } + rectangle { + object { + x=320 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=320 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="63" + align="horiz. centered" + } + } + } + "text update" { + object { + x=320 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m63.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=364 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=364 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=365 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m71.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=399 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m71_able.VAL" + } + } + rectangle { + object { + x=389 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m71.LLS" + } + } + rectangle { + object { + x=389 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m71.LVIO" + } + } + rectangle { + object { + x=389 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m71.HLS" + } + } + composite { + object { + x=365 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=365 + y=247 + width=24 + height=12 + } + display[0] { + label="m71" + name="motorx_more.adl" + args="P=$(P),M=m71" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=365 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m71.DMOV" + } + } + rectangle { + object { + x=365 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=365 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="71" + align="horiz. centered" + } + } + } + "text update" { + object { + x=365 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m71.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=364 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=365 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m72.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=399 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m72_able.VAL" + } +} +rectangle { + object { + x=389 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m72.LLS" + } +} +rectangle { + object { + x=389 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m72.LVIO" + } +} +rectangle { + object { + x=389 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m72.HLS" + } +} +composite { + object { + x=365 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=365 + y=283 + width=24 + height=12 + } + display[0] { + label="m72" + name="motorx_more.adl" + args="P=$(P),M=m72" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=365 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m72.DMOV" + } + } + rectangle { + object { + x=365 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=365 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="72" + align="horiz. centered" + } + } +} +"text update" { + object { + x=365 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m72.RBV" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=319 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=320 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m64.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=354 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m64_able.VAL" + } +} +rectangle { + object { + x=344 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m64.LLS" + } +} +rectangle { + object { + x=344 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m64.LVIO" + } +} +rectangle { + object { + x=344 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m64.HLS" + } +} +composite { + object { + x=320 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=320 + y=283 + width=24 + height=12 + } + display[0] { + label="m64" + name="motorx_more.adl" + args="P=$(P),M=m64" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=320 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m64.DMOV" + } + } + rectangle { + object { + x=320 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=320 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="64" + align="horiz. centered" + } + } +} +"text update" { + object { + x=320 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m64.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=274 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=274 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=275 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m49.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=309 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m49_able.VAL" + } + } + rectangle { + object { + x=299 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m49.LLS" + } + } + rectangle { + object { + x=299 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m49.LVIO" + } + } + rectangle { + object { + x=299 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m49.HLS" + } + } + composite { + object { + x=275 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=275 + y=31 + width=24 + height=12 + } + display[0] { + label="m49" + name="motorx_more.adl" + args="P=$(P),M=m49" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=275 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m49.DMOV" + } + } + rectangle { + object { + x=275 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=275 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="49" + align="horiz. centered" + } + } + } + "text update" { + object { + x=275 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m49.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=274 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=274 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=275 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m50.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=309 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m50_able.VAL" + } + } + rectangle { + object { + x=299 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m50.LLS" + } + } + rectangle { + object { + x=299 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m50.LVIO" + } + } + rectangle { + object { + x=299 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m50.HLS" + } + } + composite { + object { + x=275 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=275 + y=67 + width=24 + height=12 + } + display[0] { + label="m50" + name="motorx_more.adl" + args="P=$(P),M=m50" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=275 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m50.DMOV" + } + } + rectangle { + object { + x=275 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=275 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="50" + align="horiz. centered" + } + } + } + "text update" { + object { + x=275 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m50.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=274 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=274 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=275 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m51.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=309 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m51_able.VAL" + } + } + rectangle { + object { + x=299 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m51.LLS" + } + } + rectangle { + object { + x=299 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m51.LVIO" + } + } + rectangle { + object { + x=299 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m51.HLS" + } + } + composite { + object { + x=275 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=275 + y=103 + width=24 + height=12 + } + display[0] { + label="m51" + name="motorx_more.adl" + args="P=$(P),M=m51" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=275 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m51.DMOV" + } + } + rectangle { + object { + x=275 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=275 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="51" + align="horiz. centered" + } + } + } + "text update" { + object { + x=275 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m51.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=274 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=274 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=275 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m52.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=309 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m52_able.VAL" + } + } + rectangle { + object { + x=299 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m52.LLS" + } + } + rectangle { + object { + x=299 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m52.LVIO" + } + } + rectangle { + object { + x=299 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m52.HLS" + } + } + composite { + object { + x=275 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=275 + y=139 + width=24 + height=12 + } + display[0] { + label="m52" + name="motorx_more.adl" + args="P=$(P),M=m52" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=275 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m52.DMOV" + } + } + rectangle { + object { + x=275 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=275 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="52" + align="horiz. centered" + } + } + } + "text update" { + object { + x=275 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m52.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=274 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=274 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=275 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m53.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=309 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m53_able.VAL" + } + } + rectangle { + object { + x=299 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m53.LLS" + } + } + rectangle { + object { + x=299 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m53.LVIO" + } + } + rectangle { + object { + x=299 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m53.HLS" + } + } + composite { + object { + x=275 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=275 + y=175 + width=24 + height=12 + } + display[0] { + label="m53" + name="motorx_more.adl" + args="P=$(P),M=m53" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=275 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m53.DMOV" + } + } + rectangle { + object { + x=275 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=275 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="53" + align="horiz. centered" + } + } + } + "text update" { + object { + x=275 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m53.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=274 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=274 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=275 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m54.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=309 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m54_able.VAL" + } + } + rectangle { + object { + x=299 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m54.LLS" + } + } + rectangle { + object { + x=299 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m54.LVIO" + } + } + rectangle { + object { + x=299 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m54.HLS" + } + } + composite { + object { + x=275 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=275 + y=211 + width=24 + height=12 + } + display[0] { + label="m54" + name="motorx_more.adl" + args="P=$(P),M=m54" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=275 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m54.DMOV" + } + } + rectangle { + object { + x=275 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=275 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="54" + align="horiz. centered" + } + } + } + "text update" { + object { + x=275 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m54.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=274 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=274 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=275 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m55.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=309 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m55_able.VAL" + } + } + rectangle { + object { + x=299 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m55.LLS" + } + } + rectangle { + object { + x=299 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m55.LVIO" + } + } + rectangle { + object { + x=299 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m55.HLS" + } + } + composite { + object { + x=275 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=275 + y=247 + width=24 + height=12 + } + display[0] { + label="m55" + name="motorx_more.adl" + args="P=$(P),M=m55" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=275 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m55.DMOV" + } + } + rectangle { + object { + x=275 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=275 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="55" + align="horiz. centered" + } + } + } + "text update" { + object { + x=275 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m55.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=274 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=275 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m56.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=309 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m56_able.VAL" + } +} +rectangle { + object { + x=299 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m56.LLS" + } +} +rectangle { + object { + x=299 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m56.LVIO" + } +} +rectangle { + object { + x=299 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m56.HLS" + } +} +composite { + object { + x=275 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=275 + y=283 + width=24 + height=12 + } + display[0] { + label="m56" + name="motorx_more.adl" + args="P=$(P),M=m56" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=275 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m56.DMOV" + } + } + rectangle { + object { + x=275 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=275 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="56" + align="horiz. centered" + } + } +} +"text update" { + object { + x=275 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m56.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=229 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=229 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=230 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m41.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=264 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m41_able.VAL" + } + } + rectangle { + object { + x=254 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m41.LLS" + } + } + rectangle { + object { + x=254 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m41.LVIO" + } + } + rectangle { + object { + x=254 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m41.HLS" + } + } + composite { + object { + x=230 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=230 + y=31 + width=24 + height=12 + } + display[0] { + label="m41" + name="motorx_more.adl" + args="P=$(P),M=m41" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=230 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m41.DMOV" + } + } + rectangle { + object { + x=230 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=230 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="41" + align="horiz. centered" + } + } + } + "text update" { + object { + x=230 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m41.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=229 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=229 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=230 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m42.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=264 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m42_able.VAL" + } + } + rectangle { + object { + x=254 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m42.LLS" + } + } + rectangle { + object { + x=254 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m42.LVIO" + } + } + rectangle { + object { + x=254 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m42.HLS" + } + } + composite { + object { + x=230 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=230 + y=67 + width=24 + height=12 + } + display[0] { + label="m42" + name="motorx_more.adl" + args="P=$(P),M=m42" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=230 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m42.DMOV" + } + } + rectangle { + object { + x=230 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=230 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="42" + align="horiz. centered" + } + } + } + "text update" { + object { + x=230 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m42.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=229 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=229 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=230 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m43.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=264 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m43_able.VAL" + } + } + rectangle { + object { + x=254 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m43.LLS" + } + } + rectangle { + object { + x=254 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m43.LVIO" + } + } + rectangle { + object { + x=254 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m43.HLS" + } + } + composite { + object { + x=230 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=230 + y=103 + width=24 + height=12 + } + display[0] { + label="m43" + name="motorx_more.adl" + args="P=$(P),M=m43" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=230 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m43.DMOV" + } + } + rectangle { + object { + x=230 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=230 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="43" + align="horiz. centered" + } + } + } + "text update" { + object { + x=230 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m43.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=229 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=229 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=230 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m44.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=264 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m44_able.VAL" + } + } + rectangle { + object { + x=254 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m44.LLS" + } + } + rectangle { + object { + x=254 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m44.LVIO" + } + } + rectangle { + object { + x=254 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m44.HLS" + } + } + composite { + object { + x=230 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=230 + y=139 + width=24 + height=12 + } + display[0] { + label="m44" + name="motorx_more.adl" + args="P=$(P),M=m44" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=230 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m44.DMOV" + } + } + rectangle { + object { + x=230 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=230 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="44" + align="horiz. centered" + } + } + } + "text update" { + object { + x=230 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m44.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=229 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=229 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=230 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m45.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=264 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m45_able.VAL" + } + } + rectangle { + object { + x=254 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m45.LLS" + } + } + rectangle { + object { + x=254 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m45.LVIO" + } + } + rectangle { + object { + x=254 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m45.HLS" + } + } + composite { + object { + x=230 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=230 + y=175 + width=24 + height=12 + } + display[0] { + label="m45" + name="motorx_more.adl" + args="P=$(P),M=m45" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=230 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m45.DMOV" + } + } + rectangle { + object { + x=230 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=230 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="45" + align="horiz. centered" + } + } + } + "text update" { + object { + x=230 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m45.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=229 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=229 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=230 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m46.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=264 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m46_able.VAL" + } + } + rectangle { + object { + x=254 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m46.LLS" + } + } + rectangle { + object { + x=254 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m46.LVIO" + } + } + rectangle { + object { + x=254 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m46.HLS" + } + } + composite { + object { + x=230 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=230 + y=211 + width=24 + height=12 + } + display[0] { + label="m46" + name="motorx_more.adl" + args="P=$(P),M=m46" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=230 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m46.DMOV" + } + } + rectangle { + object { + x=230 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=230 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="46" + align="horiz. centered" + } + } + } + "text update" { + object { + x=230 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m46.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=229 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=229 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=230 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m47.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=264 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m47_able.VAL" + } + } + rectangle { + object { + x=254 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m47.LLS" + } + } + rectangle { + object { + x=254 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m47.LVIO" + } + } + rectangle { + object { + x=254 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m47.HLS" + } + } + composite { + object { + x=230 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=230 + y=247 + width=24 + height=12 + } + display[0] { + label="m47" + name="motorx_more.adl" + args="P=$(P),M=m47" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=230 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m47.DMOV" + } + } + rectangle { + object { + x=230 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=230 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="47" + align="horiz. centered" + } + } + } + "text update" { + object { + x=230 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m47.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=229 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=230 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m48.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=264 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m48_able.VAL" + } +} +rectangle { + object { + x=254 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m48.LLS" + } +} +rectangle { + object { + x=254 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m48.LVIO" + } +} +rectangle { + object { + x=254 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m48.HLS" + } +} +composite { + object { + x=230 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=230 + y=283 + width=24 + height=12 + } + display[0] { + label="m48" + name="motorx_more.adl" + args="P=$(P),M=m48" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=230 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m48.DMOV" + } + } + rectangle { + object { + x=230 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=230 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="48" + align="horiz. centered" + } + } +} +"text update" { + object { + x=230 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m48.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=184 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=184 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=185 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m33.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=219 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m33_able.VAL" + } + } + rectangle { + object { + x=209 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m33.LLS" + } + } + rectangle { + object { + x=209 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m33.LVIO" + } + } + rectangle { + object { + x=209 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m33.HLS" + } + } + composite { + object { + x=185 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=185 + y=31 + width=24 + height=12 + } + display[0] { + label="m33" + name="motorx_more.adl" + args="P=$(P),M=m33" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=185 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m33.DMOV" + } + } + rectangle { + object { + x=185 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=185 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="33" + align="horiz. centered" + } + } + } + "text update" { + object { + x=185 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m33.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=184 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=184 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=185 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m34.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=219 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m34_able.VAL" + } + } + rectangle { + object { + x=209 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m34.LLS" + } + } + rectangle { + object { + x=209 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m34.LVIO" + } + } + rectangle { + object { + x=209 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m34.HLS" + } + } + composite { + object { + x=185 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=185 + y=67 + width=24 + height=12 + } + display[0] { + label="m34" + name="motorx_more.adl" + args="P=$(P),M=m34" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=185 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m34.DMOV" + } + } + rectangle { + object { + x=185 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=185 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="34" + align="horiz. centered" + } + } + } + "text update" { + object { + x=185 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m34.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=184 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=184 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=185 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m35.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=219 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m35_able.VAL" + } + } + rectangle { + object { + x=209 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m35.LLS" + } + } + rectangle { + object { + x=209 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m35.LVIO" + } + } + rectangle { + object { + x=209 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m35.HLS" + } + } + composite { + object { + x=185 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=185 + y=103 + width=24 + height=12 + } + display[0] { + label="m35" + name="motorx_more.adl" + args="P=$(P),M=m35" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=185 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m35.DMOV" + } + } + rectangle { + object { + x=185 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=185 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="35" + align="horiz. centered" + } + } + } + "text update" { + object { + x=185 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m35.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=184 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=184 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=185 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m36.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=219 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m36_able.VAL" + } + } + rectangle { + object { + x=209 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m36.LLS" + } + } + rectangle { + object { + x=209 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m36.LVIO" + } + } + rectangle { + object { + x=209 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m36.HLS" + } + } + composite { + object { + x=185 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=185 + y=139 + width=24 + height=12 + } + display[0] { + label="m36" + name="motorx_more.adl" + args="P=$(P),M=m36" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=185 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m36.DMOV" + } + } + rectangle { + object { + x=185 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=185 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="36" + align="horiz. centered" + } + } + } + "text update" { + object { + x=185 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m36.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=184 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=184 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=185 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m37.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=219 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m37_able.VAL" + } + } + rectangle { + object { + x=209 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m37.LLS" + } + } + rectangle { + object { + x=209 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m37.LVIO" + } + } + rectangle { + object { + x=209 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m37.HLS" + } + } + composite { + object { + x=185 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=185 + y=175 + width=24 + height=12 + } + display[0] { + label="m37" + name="motorx_more.adl" + args="P=$(P),M=m37" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=185 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m37.DMOV" + } + } + rectangle { + object { + x=185 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=185 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="37" + align="horiz. centered" + } + } + } + "text update" { + object { + x=185 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m37.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=184 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=184 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=185 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m38.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=219 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m38_able.VAL" + } + } + rectangle { + object { + x=209 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m38.LLS" + } + } + rectangle { + object { + x=209 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m38.LVIO" + } + } + rectangle { + object { + x=209 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m38.HLS" + } + } + composite { + object { + x=185 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=185 + y=211 + width=24 + height=12 + } + display[0] { + label="m38" + name="motorx_more.adl" + args="P=$(P),M=m38" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=185 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m38.DMOV" + } + } + rectangle { + object { + x=185 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=185 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="38" + align="horiz. centered" + } + } + } + "text update" { + object { + x=185 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m38.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=184 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=184 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=185 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m39.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=219 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m39_able.VAL" + } + } + rectangle { + object { + x=209 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m39.LLS" + } + } + rectangle { + object { + x=209 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m39.LVIO" + } + } + rectangle { + object { + x=209 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m39.HLS" + } + } + composite { + object { + x=185 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=185 + y=247 + width=24 + height=12 + } + display[0] { + label="m39" + name="motorx_more.adl" + args="P=$(P),M=m39" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=185 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m39.DMOV" + } + } + rectangle { + object { + x=185 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=185 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="39" + align="horiz. centered" + } + } + } + "text update" { + object { + x=185 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m39.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=184 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=185 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m40.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=219 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m40_able.VAL" + } +} +rectangle { + object { + x=209 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m40.LLS" + } +} +rectangle { + object { + x=209 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m40.LVIO" + } +} +rectangle { + object { + x=209 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m40.HLS" + } +} +composite { + object { + x=185 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=185 + y=283 + width=24 + height=12 + } + display[0] { + label="m40" + name="motorx_more.adl" + args="P=$(P),M=m40" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=185 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m40.DMOV" + } + } + rectangle { + object { + x=185 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=185 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="40" + align="horiz. centered" + } + } +} +"text update" { + object { + x=185 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m40.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=139 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=139 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=140 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m25.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=174 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m25_able.VAL" + } + } + rectangle { + object { + x=164 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m25.LLS" + } + } + rectangle { + object { + x=164 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m25.LVIO" + } + } + rectangle { + object { + x=164 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m25.HLS" + } + } + composite { + object { + x=140 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=140 + y=31 + width=24 + height=12 + } + display[0] { + label="m25" + name="motorx_more.adl" + args="P=$(P),M=m25" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=140 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m25.DMOV" + } + } + rectangle { + object { + x=140 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=140 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="25" + align="horiz. centered" + } + } + } + "text update" { + object { + x=140 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m25.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=139 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=139 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=140 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m26.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=174 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m26_able.VAL" + } + } + rectangle { + object { + x=164 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m26.LLS" + } + } + rectangle { + object { + x=164 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m26.LVIO" + } + } + rectangle { + object { + x=164 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m26.HLS" + } + } + composite { + object { + x=140 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=140 + y=67 + width=24 + height=12 + } + display[0] { + label="m26" + name="motorx_more.adl" + args="P=$(P),M=m26" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=140 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m26.DMOV" + } + } + rectangle { + object { + x=140 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=140 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="26" + align="horiz. centered" + } + } + } + "text update" { + object { + x=140 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m26.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=139 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=139 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=140 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m27.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=174 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m27_able.VAL" + } + } + rectangle { + object { + x=164 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m27.LLS" + } + } + rectangle { + object { + x=164 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m27.LVIO" + } + } + rectangle { + object { + x=164 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m27.HLS" + } + } + composite { + object { + x=140 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=140 + y=103 + width=24 + height=12 + } + display[0] { + label="m27" + name="motorx_more.adl" + args="P=$(P),M=m27" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=140 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m27.DMOV" + } + } + rectangle { + object { + x=140 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=140 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="27" + align="horiz. centered" + } + } + } + "text update" { + object { + x=140 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m27.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=139 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=139 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=140 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m28.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=174 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m28_able.VAL" + } + } + rectangle { + object { + x=164 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m28.LLS" + } + } + rectangle { + object { + x=164 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m28.LVIO" + } + } + rectangle { + object { + x=164 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m28.HLS" + } + } + composite { + object { + x=140 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=140 + y=139 + width=24 + height=12 + } + display[0] { + label="m28" + name="motorx_more.adl" + args="P=$(P),M=m28" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=140 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m28.DMOV" + } + } + rectangle { + object { + x=140 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=140 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="28" + align="horiz. centered" + } + } + } + "text update" { + object { + x=140 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m28.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=139 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=139 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=140 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m29.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=174 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m29_able.VAL" + } + } + rectangle { + object { + x=164 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m29.LLS" + } + } + rectangle { + object { + x=164 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m29.LVIO" + } + } + rectangle { + object { + x=164 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m29.HLS" + } + } + composite { + object { + x=140 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=140 + y=175 + width=24 + height=12 + } + display[0] { + label="m29" + name="motorx_more.adl" + args="P=$(P),M=m29" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=140 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m29.DMOV" + } + } + rectangle { + object { + x=140 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=140 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="29" + align="horiz. centered" + } + } + } + "text update" { + object { + x=140 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m29.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=139 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=139 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=140 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m30.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=174 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m30_able.VAL" + } + } + rectangle { + object { + x=164 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m30.LLS" + } + } + rectangle { + object { + x=164 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m30.LVIO" + } + } + rectangle { + object { + x=164 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m30.HLS" + } + } + composite { + object { + x=140 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=140 + y=211 + width=24 + height=12 + } + display[0] { + label="m30" + name="motorx_more.adl" + args="P=$(P),M=m30" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=140 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m30.DMOV" + } + } + rectangle { + object { + x=140 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=140 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="30" + align="horiz. centered" + } + } + } + "text update" { + object { + x=140 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m30.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=139 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=139 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=140 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m31.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=174 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m31_able.VAL" + } + } + rectangle { + object { + x=164 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m31.LLS" + } + } + rectangle { + object { + x=164 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m31.LVIO" + } + } + rectangle { + object { + x=164 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m31.HLS" + } + } + composite { + object { + x=140 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=140 + y=247 + width=24 + height=12 + } + display[0] { + label="m31" + name="motorx_more.adl" + args="P=$(P),M=m31" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=140 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m31.DMOV" + } + } + rectangle { + object { + x=140 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=140 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="31" + align="horiz. centered" + } + } + } + "text update" { + object { + x=140 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m31.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=139 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=140 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m32.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=174 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m32_able.VAL" + } +} +rectangle { + object { + x=164 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m32.LLS" + } +} +rectangle { + object { + x=164 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m32.LVIO" + } +} +rectangle { + object { + x=164 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m32.HLS" + } +} +composite { + object { + x=140 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=140 + y=283 + width=24 + height=12 + } + display[0] { + label="m32" + name="motorx_more.adl" + args="P=$(P),M=m32" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=140 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m32.DMOV" + } + } + rectangle { + object { + x=140 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=140 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="32" + align="horiz. centered" + } + } +} +"text update" { + object { + x=140 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m32.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=94 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=94 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=95 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m17.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=129 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m17_able.VAL" + } + } + rectangle { + object { + x=119 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m17.LLS" + } + } + rectangle { + object { + x=119 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m17.LVIO" + } + } + rectangle { + object { + x=119 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m17.HLS" + } + } + composite { + object { + x=95 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=95 + y=31 + width=24 + height=12 + } + display[0] { + label="m17" + name="motorx_more.adl" + args="P=$(P),M=m17" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=95 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m17.DMOV" + } + } + rectangle { + object { + x=95 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=95 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="17" + align="horiz. centered" + } + } + } + "text update" { + object { + x=95 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m17.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=94 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=94 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=95 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m18.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=129 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m18_able.VAL" + } + } + rectangle { + object { + x=119 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m18.LLS" + } + } + rectangle { + object { + x=119 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m18.LVIO" + } + } + rectangle { + object { + x=119 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m18.HLS" + } + } + composite { + object { + x=95 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=95 + y=67 + width=24 + height=12 + } + display[0] { + label="m18" + name="motorx_more.adl" + args="P=$(P),M=m18" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=95 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m18.DMOV" + } + } + rectangle { + object { + x=95 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=95 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="18" + align="horiz. centered" + } + } + } + "text update" { + object { + x=95 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m18.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=94 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=94 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=95 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m19.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=129 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m19_able.VAL" + } + } + rectangle { + object { + x=119 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m19.LLS" + } + } + rectangle { + object { + x=119 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m19.LVIO" + } + } + rectangle { + object { + x=119 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m19.HLS" + } + } + composite { + object { + x=95 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=95 + y=103 + width=24 + height=12 + } + display[0] { + label="m19" + name="motorx_more.adl" + args="P=$(P),M=m19" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=95 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m19.DMOV" + } + } + rectangle { + object { + x=95 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=95 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="19" + align="horiz. centered" + } + } + } + "text update" { + object { + x=95 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m19.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=94 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=94 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=95 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m20.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=129 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m20_able.VAL" + } + } + rectangle { + object { + x=119 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m20.LLS" + } + } + rectangle { + object { + x=119 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m20.LVIO" + } + } + rectangle { + object { + x=119 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m20.HLS" + } + } + composite { + object { + x=95 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=95 + y=139 + width=24 + height=12 + } + display[0] { + label="m20" + name="motorx_more.adl" + args="P=$(P),M=m20" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=95 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m20.DMOV" + } + } + rectangle { + object { + x=95 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=95 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="20" + align="horiz. centered" + } + } + } + "text update" { + object { + x=95 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m20.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=94 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=94 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=95 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m21.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=129 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m21_able.VAL" + } + } + rectangle { + object { + x=119 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m21.LLS" + } + } + rectangle { + object { + x=119 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m21.LVIO" + } + } + rectangle { + object { + x=119 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m21.HLS" + } + } + composite { + object { + x=95 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=95 + y=175 + width=24 + height=12 + } + display[0] { + label="m21" + name="motorx_more.adl" + args="P=$(P),M=m21" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=95 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m21.DMOV" + } + } + rectangle { + object { + x=95 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=95 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="21" + align="horiz. centered" + } + } + } + "text update" { + object { + x=95 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m21.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=94 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=94 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=95 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m22.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=129 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m22_able.VAL" + } + } + rectangle { + object { + x=119 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m22.LLS" + } + } + rectangle { + object { + x=119 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m22.LVIO" + } + } + rectangle { + object { + x=119 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m22.HLS" + } + } + composite { + object { + x=95 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=95 + y=211 + width=24 + height=12 + } + display[0] { + label="m22" + name="motorx_more.adl" + args="P=$(P),M=m22" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=95 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m22.DMOV" + } + } + rectangle { + object { + x=95 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=95 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="22" + align="horiz. centered" + } + } + } + "text update" { + object { + x=95 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m22.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=94 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=94 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=95 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m23.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=129 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m23_able.VAL" + } + } + rectangle { + object { + x=119 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m23.LLS" + } + } + rectangle { + object { + x=119 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m23.LVIO" + } + } + rectangle { + object { + x=119 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m23.HLS" + } + } + composite { + object { + x=95 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=95 + y=247 + width=24 + height=12 + } + display[0] { + label="m23" + name="motorx_more.adl" + args="P=$(P),M=m23" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=95 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m23.DMOV" + } + } + rectangle { + object { + x=95 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=95 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="23" + align="horiz. centered" + } + } + } + "text update" { + object { + x=95 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m23.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=94 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=95 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m24.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=129 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m24_able.VAL" + } +} +rectangle { + object { + x=119 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m24.LLS" + } +} +rectangle { + object { + x=119 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m24.LVIO" + } +} +rectangle { + object { + x=119 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m24.HLS" + } +} +composite { + object { + x=95 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=95 + y=283 + width=24 + height=12 + } + display[0] { + label="m24" + name="motorx_more.adl" + args="P=$(P),M=m24" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=95 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m24.DMOV" + } + } + rectangle { + object { + x=95 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=95 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="24" + align="horiz. centered" + } + } +} +"text update" { + object { + x=95 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m24.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=49 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=49 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=50 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m9.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=84 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m9_able.VAL" + } + } + rectangle { + object { + x=74 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m9.LLS" + } + } + rectangle { + object { + x=74 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m9.LVIO" + } + } + rectangle { + object { + x=74 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m9.HLS" + } + } + composite { + object { + x=50 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=50 + y=31 + width=24 + height=12 + } + display[0] { + label="m9" + name="motorx_more.adl" + args="P=$(P),M=m9" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=50 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m9.DMOV" + } + } + rectangle { + object { + x=50 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=50 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="9" + align="horiz. centered" + } + } + } + "text update" { + object { + x=50 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m9.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=49 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=49 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=50 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m10.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=84 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m10_able.VAL" + } + } + rectangle { + object { + x=74 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m10.LLS" + } + } + rectangle { + object { + x=74 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m10.LVIO" + } + } + rectangle { + object { + x=74 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m10.HLS" + } + } + composite { + object { + x=50 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=50 + y=67 + width=24 + height=12 + } + display[0] { + label="m10" + name="motorx_more.adl" + args="P=$(P),M=m10" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=50 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m10.DMOV" + } + } + rectangle { + object { + x=50 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=50 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="10" + align="horiz. centered" + } + } + } + "text update" { + object { + x=50 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m10.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=49 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=49 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=50 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m11.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=84 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m11_able.VAL" + } + } + rectangle { + object { + x=74 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m11.LLS" + } + } + rectangle { + object { + x=74 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m11.LVIO" + } + } + rectangle { + object { + x=74 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m11.HLS" + } + } + composite { + object { + x=50 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=50 + y=103 + width=24 + height=12 + } + display[0] { + label="m11" + name="motorx_more.adl" + args="P=$(P),M=m11" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=50 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m11.DMOV" + } + } + rectangle { + object { + x=50 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=50 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="11" + align="horiz. centered" + } + } + } + "text update" { + object { + x=50 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m11.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=49 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=49 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=50 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m12.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=84 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m12_able.VAL" + } + } + rectangle { + object { + x=74 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m12.LLS" + } + } + rectangle { + object { + x=74 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m12.LVIO" + } + } + rectangle { + object { + x=74 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m12.HLS" + } + } + composite { + object { + x=50 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=50 + y=139 + width=24 + height=12 + } + display[0] { + label="m12" + name="motorx_more.adl" + args="P=$(P),M=m12" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=50 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m12.DMOV" + } + } + rectangle { + object { + x=50 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=50 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="12" + align="horiz. centered" + } + } + } + "text update" { + object { + x=50 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m12.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=49 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=49 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=50 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m13.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=84 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m13_able.VAL" + } + } + rectangle { + object { + x=74 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m13.LLS" + } + } + rectangle { + object { + x=74 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m13.LVIO" + } + } + rectangle { + object { + x=74 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m13.HLS" + } + } + composite { + object { + x=50 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=50 + y=175 + width=24 + height=12 + } + display[0] { + label="m13" + name="motorx_more.adl" + args="P=$(P),M=m13" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=50 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m13.DMOV" + } + } + rectangle { + object { + x=50 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=50 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="13" + align="horiz. centered" + } + } + } + "text update" { + object { + x=50 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m13.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=49 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=49 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=50 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m14.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=84 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m14_able.VAL" + } + } + rectangle { + object { + x=74 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m14.LLS" + } + } + rectangle { + object { + x=74 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m14.LVIO" + } + } + rectangle { + object { + x=74 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m14.HLS" + } + } + composite { + object { + x=50 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=50 + y=211 + width=24 + height=12 + } + display[0] { + label="m14" + name="motorx_more.adl" + args="P=$(P),M=m14" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=50 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m14.DMOV" + } + } + rectangle { + object { + x=50 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=50 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="14" + align="horiz. centered" + } + } + } + "text update" { + object { + x=50 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m14.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=49 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=49 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=50 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m15.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=84 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m15_able.VAL" + } + } + rectangle { + object { + x=74 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m15.LLS" + } + } + rectangle { + object { + x=74 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m15.LVIO" + } + } + rectangle { + object { + x=74 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m15.HLS" + } + } + composite { + object { + x=50 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=50 + y=247 + width=24 + height=12 + } + display[0] { + label="m15" + name="motorx_more.adl" + args="P=$(P),M=m15" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=50 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m15.DMOV" + } + } + rectangle { + object { + x=50 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=50 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="15" + align="horiz. centered" + } + } + } + "text update" { + object { + x=50 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m15.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=49 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=50 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m16.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=84 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m16_able.VAL" + } +} +rectangle { + object { + x=74 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m16.LLS" + } +} +rectangle { + object { + x=74 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m16.LVIO" + } +} +rectangle { + object { + x=74 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m16.HLS" + } +} +composite { + object { + x=50 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=50 + y=283 + width=24 + height=12 + } + display[0] { + label="m16" + name="motorx_more.adl" + args="P=$(P),M=m16" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=50 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m16.DMOV" + } + } + rectangle { + object { + x=50 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=50 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="16" + align="horiz. centered" + } + } +} +"text update" { + object { + x=50 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m16.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=4 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=4 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=5 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m1.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=39 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m1_able.VAL" + } + } + rectangle { + object { + x=29 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m1.LLS" + } + } + rectangle { + object { + x=29 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m1.LVIO" + } + } + rectangle { + object { + x=29 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m1.HLS" + } + } + composite { + object { + x=5 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=5 + y=31 + width=24 + height=12 + } + display[0] { + label="m1" + name="motorx_more.adl" + args="P=$(P),M=m1" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=5 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m1.DMOV" + } + } + rectangle { + object { + x=5 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=5 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="1" + align="horiz. centered" + } + } + } + "text update" { + object { + x=5 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m1.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=4 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=4 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=5 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m2.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=39 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m2_able.VAL" + } + } + rectangle { + object { + x=29 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m2.LLS" + } + } + rectangle { + object { + x=29 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m2.LVIO" + } + } + rectangle { + object { + x=29 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m2.HLS" + } + } + composite { + object { + x=5 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=5 + y=67 + width=24 + height=12 + } + display[0] { + label="m2" + name="motorx_more.adl" + args="P=$(P),M=m2" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=5 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m2.DMOV" + } + } + rectangle { + object { + x=5 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=5 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="2" + align="horiz. centered" + } + } + } + "text update" { + object { + x=5 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m2.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=4 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=4 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=5 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m3.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=39 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m3_able.VAL" + } + } + rectangle { + object { + x=29 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m3.LLS" + } + } + rectangle { + object { + x=29 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m3.LVIO" + } + } + rectangle { + object { + x=29 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m3.HLS" + } + } + composite { + object { + x=5 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=5 + y=103 + width=24 + height=12 + } + display[0] { + label="m3" + name="motorx_more.adl" + args="P=$(P),M=m3" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=5 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m3.DMOV" + } + } + rectangle { + object { + x=5 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=5 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="3" + align="horiz. centered" + } + } + } + "text update" { + object { + x=5 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m3.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=4 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=4 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=5 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m4.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=39 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m4_able.VAL" + } + } + rectangle { + object { + x=29 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m4.LLS" + } + } + rectangle { + object { + x=29 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m4.LVIO" + } + } + rectangle { + object { + x=29 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m4.HLS" + } + } + composite { + object { + x=5 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=5 + y=139 + width=24 + height=12 + } + display[0] { + label="m4" + name="motorx_more.adl" + args="P=$(P),M=m4" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=5 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m4.DMOV" + } + } + rectangle { + object { + x=5 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=5 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="4" + align="horiz. centered" + } + } + } + "text update" { + object { + x=5 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m4.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=4 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=4 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=5 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m5.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=39 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m5_able.VAL" + } + } + rectangle { + object { + x=29 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m5.LLS" + } + } + rectangle { + object { + x=29 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m5.LVIO" + } + } + rectangle { + object { + x=29 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m5.HLS" + } + } + composite { + object { + x=5 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=5 + y=175 + width=24 + height=12 + } + display[0] { + label="m5" + name="motorx_more.adl" + args="P=$(P),M=m5" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=5 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m5.DMOV" + } + } + rectangle { + object { + x=5 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=5 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="5" + align="horiz. centered" + } + } + } + "text update" { + object { + x=5 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m5.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=4 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=4 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=5 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m6.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=39 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m6_able.VAL" + } + } + rectangle { + object { + x=29 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m6.LLS" + } + } + rectangle { + object { + x=29 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m6.LVIO" + } + } + rectangle { + object { + x=29 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m6.HLS" + } + } + composite { + object { + x=5 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=5 + y=211 + width=24 + height=12 + } + display[0] { + label="m6" + name="motorx_more.adl" + args="P=$(P),M=m6" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=5 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m6.DMOV" + } + } + rectangle { + object { + x=5 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=5 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="6" + align="horiz. centered" + } + } + } + "text update" { + object { + x=5 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m6.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=4 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=4 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=5 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m7.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=39 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m7_able.VAL" + } + } + rectangle { + object { + x=29 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m7.LLS" + } + } + rectangle { + object { + x=29 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m7.LVIO" + } + } + rectangle { + object { + x=29 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m7.HLS" + } + } + composite { + object { + x=5 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=5 + y=247 + width=24 + height=12 + } + display[0] { + label="m7" + name="motorx_more.adl" + args="P=$(P),M=m7" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=5 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m7.DMOV" + } + } + rectangle { + object { + x=5 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=5 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="7" + align="horiz. centered" + } + } + } + "text update" { + object { + x=5 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m7.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=4 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=5 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m8.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=39 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m8_able.VAL" + } +} +rectangle { + object { + x=29 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m8.LLS" + } +} +rectangle { + object { + x=29 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m8.LVIO" + } +} +rectangle { + object { + x=29 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m8.HLS" + } +} +composite { + object { + x=5 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=5 + y=283 + width=24 + height=12 + } + display[0] { + label="m8" + name="motorx_more.adl" + args="P=$(P),M=m8" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=5 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m8.DMOV" + } + } + rectangle { + object { + x=5 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=5 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="8" + align="horiz. centered" + } + } +} +"text update" { + object { + x=5 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m8.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=409 + y=20 + width=40 + height=285 + } + "composite name"="" + children { + rectangle { + object { + x=409 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=410 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m75.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=444 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m75_able.VAL" + } + } + rectangle { + object { + x=434 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m75.LLS" + } + } + rectangle { + object { + x=434 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m75.LVIO" + } + } + rectangle { + object { + x=434 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m75.HLS" + } + } + composite { + object { + x=410 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=410 + y=103 + width=24 + height=12 + } + display[0] { + label="m3" + name="motorx_more.adl" + args="P=$(P),M=m75" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=410 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m75.DMOV" + } + } + rectangle { + object { + x=410 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=410 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="75" + align="horiz. centered" + } + } + } + rectangle { + object { + x=409 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=410 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m76.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=444 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m76_able.VAL" + } + } + rectangle { + object { + x=434 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m76.LLS" + } + } + rectangle { + object { + x=434 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m76.LVIO" + } + } + rectangle { + object { + x=434 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m76.HLS" + } + } + composite { + object { + x=410 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=410 + y=139 + width=24 + height=12 + } + display[0] { + label="m4" + name="motorx_more.adl" + args="P=$(P),M=m76" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=410 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m76.DMOV" + } + } + rectangle { + object { + x=410 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=410 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="76" + align="horiz. centered" + } + } + } + rectangle { + object { + x=409 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=410 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m77.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=444 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m77_able.VAL" + } + } + rectangle { + object { + x=434 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m77.LLS" + } + } + rectangle { + object { + x=434 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m77.LVIO" + } + } + rectangle { + object { + x=434 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m77.HLS" + } + } + composite { + object { + x=410 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=410 + y=175 + width=24 + height=12 + } + display[0] { + label="m5" + name="motorx_more.adl" + args="P=$(P),M=m77" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=410 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m77.DMOV" + } + } + rectangle { + object { + x=410 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=410 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="77" + align="horiz. centered" + } + } + } + rectangle { + object { + x=409 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=410 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m78.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=444 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m78_able.VAL" + } + } + rectangle { + object { + x=434 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m78.LLS" + } + } + rectangle { + object { + x=434 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m78.LVIO" + } + } + rectangle { + object { + x=434 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m78.HLS" + } + } + composite { + object { + x=410 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=410 + y=211 + width=24 + height=12 + } + display[0] { + label="m6" + name="motorx_more.adl" + args="P=$(P),M=m78" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=410 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m78.DMOV" + } + } + rectangle { + object { + x=410 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=410 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="78" + align="horiz. centered" + } + } + } + rectangle { + object { + x=409 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=410 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m79.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=444 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m79_able.VAL" + } + } + rectangle { + object { + x=434 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m79.LLS" + } + } + rectangle { + object { + x=434 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m79.LVIO" + } + } + rectangle { + object { + x=434 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m79.HLS" + } + } + composite { + object { + x=410 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=410 + y=247 + width=24 + height=12 + } + display[0] { + label="m7" + name="motorx_more.adl" + args="P=$(P),M=m79" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=410 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m79.DMOV" + } + } + rectangle { + object { + x=410 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=410 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="79" + align="horiz. centered" + } + } + } + rectangle { + object { + x=409 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=410 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m80.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=444 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m80_able.VAL" + } + } + rectangle { + object { + x=434 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m80.LLS" + } + } + rectangle { + object { + x=434 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m80.LVIO" + } + } + rectangle { + object { + x=434 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m80.HLS" + } + } + composite { + object { + x=410 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=410 + y=283 + width=24 + height=12 + } + display[0] { + label="m8" + name="motorx_more.adl" + args="P=$(P),M=m80" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=410 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m80.DMOV" + } + } + rectangle { + object { + x=410 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=410 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="80" + align="horiz. centered" + } + } + } + rectangle { + object { + x=409 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=410 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m73.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=444 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m73_able.VAL" + } + } + rectangle { + object { + x=434 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m73.LLS" + } + } + rectangle { + object { + x=434 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m73.LVIO" + } + } + rectangle { + object { + x=434 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m73.HLS" + } + } + composite { + object { + x=410 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=410 + y=31 + width=24 + height=12 + } + display[0] { + label="m1" + name="motorx_more.adl" + args="P=$(P),M=m73" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=410 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m73.DMOV" + } + } + rectangle { + object { + x=410 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=410 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="73" + align="horiz. centered" + } + } + } + rectangle { + object { + x=409 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=410 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m74.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=444 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m74_able.VAL" + } + } + rectangle { + object { + x=434 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m74.LLS" + } + } + rectangle { + object { + x=434 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m74.LVIO" + } + } + rectangle { + object { + x=434 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m74.HLS" + } + } + composite { + object { + x=410 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=410 + y=67 + width=24 + height=12 + } + display[0] { + label="m2" + name="motorx_more.adl" + args="P=$(P),M=m74" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=410 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m74.DMOV" + } + } + rectangle { + object { + x=410 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=410 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="74" + align="horiz. centered" + } + } + } + "text update" { + object { + x=410 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m73.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=410 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m74.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=410 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m75.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=410 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m76.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=410 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m77.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=410 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m78.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=410 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m79.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=410 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m80.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=454 + y=20 + width=40 + height=285 + } + "composite name"="" + children { + rectangle { + object { + x=454 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=455 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m83.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=489 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m83_able.VAL" + } + } + rectangle { + object { + x=479 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m83.LLS" + } + } + rectangle { + object { + x=479 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m83.LVIO" + } + } + rectangle { + object { + x=479 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m83.HLS" + } + } + composite { + object { + x=455 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=455 + y=103 + width=24 + height=12 + } + display[0] { + label="m3" + name="motorx_more.adl" + args="P=$(P),M=m83" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=455 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m83.DMOV" + } + } + rectangle { + object { + x=455 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=455 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="83" + align="horiz. centered" + } + } + } + rectangle { + object { + x=454 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=455 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m84.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=489 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m84_able.VAL" + } + } + rectangle { + object { + x=479 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m84.LLS" + } + } + rectangle { + object { + x=479 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m84.LVIO" + } + } + rectangle { + object { + x=479 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m84.HLS" + } + } + composite { + object { + x=455 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=455 + y=139 + width=24 + height=12 + } + display[0] { + label="m4" + name="motorx_more.adl" + args="P=$(P),M=m84" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=455 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m84.DMOV" + } + } + rectangle { + object { + x=455 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=455 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="84" + align="horiz. centered" + } + } + } + rectangle { + object { + x=454 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=455 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m85.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=489 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m85_able.VAL" + } + } + rectangle { + object { + x=479 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m85.LLS" + } + } + rectangle { + object { + x=479 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m85.LVIO" + } + } + rectangle { + object { + x=479 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m85.HLS" + } + } + composite { + object { + x=455 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=455 + y=175 + width=24 + height=12 + } + display[0] { + label="m5" + name="motorx_more.adl" + args="P=$(P),M=m85" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=455 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m85.DMOV" + } + } + rectangle { + object { + x=455 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=455 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="85" + align="horiz. centered" + } + } + } + rectangle { + object { + x=454 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=455 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m86.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=489 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m86_able.VAL" + } + } + rectangle { + object { + x=479 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m86.LLS" + } + } + rectangle { + object { + x=479 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m86.LVIO" + } + } + rectangle { + object { + x=479 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m86.HLS" + } + } + composite { + object { + x=455 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=455 + y=211 + width=24 + height=12 + } + display[0] { + label="m6" + name="motorx_more.adl" + args="P=$(P),M=m86" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=455 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m86.DMOV" + } + } + rectangle { + object { + x=455 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=455 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="86" + align="horiz. centered" + } + } + } + rectangle { + object { + x=454 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=455 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m87.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=489 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m87_able.VAL" + } + } + rectangle { + object { + x=479 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m87.LLS" + } + } + rectangle { + object { + x=479 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m87.LVIO" + } + } + rectangle { + object { + x=479 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m87.HLS" + } + } + composite { + object { + x=455 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=455 + y=247 + width=24 + height=12 + } + display[0] { + label="m7" + name="motorx_more.adl" + args="P=$(P),M=m87" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=455 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m87.DMOV" + } + } + rectangle { + object { + x=455 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=455 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="87" + align="horiz. centered" + } + } + } + rectangle { + object { + x=454 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=455 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m88.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=489 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m88_able.VAL" + } + } + rectangle { + object { + x=479 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m88.LLS" + } + } + rectangle { + object { + x=479 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m88.LVIO" + } + } + rectangle { + object { + x=479 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m88.HLS" + } + } + composite { + object { + x=455 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=455 + y=283 + width=24 + height=12 + } + display[0] { + label="m8" + name="motorx_more.adl" + args="P=$(P),M=m88" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=455 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m88.DMOV" + } + } + rectangle { + object { + x=455 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=455 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="88" + align="horiz. centered" + } + } + } + rectangle { + object { + x=454 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=455 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m81.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=489 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m81_able.VAL" + } + } + rectangle { + object { + x=479 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m81.LLS" + } + } + rectangle { + object { + x=479 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m81.LVIO" + } + } + rectangle { + object { + x=479 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m81.HLS" + } + } + composite { + object { + x=455 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=455 + y=31 + width=24 + height=12 + } + display[0] { + label="m1" + name="motorx_more.adl" + args="P=$(P),M=m81" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=455 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m81.DMOV" + } + } + rectangle { + object { + x=455 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=455 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="81" + align="horiz. centered" + } + } + } + rectangle { + object { + x=454 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=455 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m82.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=489 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m82_able.VAL" + } + } + rectangle { + object { + x=479 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m82.LLS" + } + } + rectangle { + object { + x=479 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m82.LVIO" + } + } + rectangle { + object { + x=479 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m82.HLS" + } + } + composite { + object { + x=455 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=455 + y=67 + width=24 + height=12 + } + display[0] { + label="m2" + name="motorx_more.adl" + args="P=$(P),M=m82" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=455 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m82.DMOV" + } + } + rectangle { + object { + x=455 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=455 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="82" + align="horiz. centered" + } + } + } + "text update" { + object { + x=455 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m81.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=455 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m82.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=455 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m83.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=455 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m84.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=455 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m85.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=455 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m86.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=455 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m87.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=455 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m88.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=499 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=500 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m91.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=534 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m91_able.VAL" + } +} +rectangle { + object { + x=524 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m91.LLS" + } +} +rectangle { + object { + x=524 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m91.LVIO" + } +} +rectangle { + object { + x=524 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m91.HLS" + } +} +"related display" { + object { + x=500 + y=103 + width=24 + height=12 + } + display[0] { + label="m3" + name="motorx_more.adl" + args="P=$(P),M=m91" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=500 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m91.DMOV" + } +} +rectangle { + object { + x=500 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=500 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="91" + align="horiz. centered" +} +rectangle { + object { + x=499 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=500 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m92.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=534 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m92_able.VAL" + } +} +rectangle { + object { + x=524 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m92.LLS" + } +} +rectangle { + object { + x=524 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m92.LVIO" + } +} +rectangle { + object { + x=524 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m92.HLS" + } +} +"related display" { + object { + x=500 + y=139 + width=24 + height=12 + } + display[0] { + label="m4" + name="motorx_more.adl" + args="P=$(P),M=m92" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=500 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m92.DMOV" + } +} +rectangle { + object { + x=500 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=500 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="92" + align="horiz. centered" +} +rectangle { + object { + x=499 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=500 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m93.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=534 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m93_able.VAL" + } +} +rectangle { + object { + x=524 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m93.LLS" + } +} +rectangle { + object { + x=524 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m93.LVIO" + } +} +rectangle { + object { + x=524 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m93.HLS" + } +} +"related display" { + object { + x=500 + y=175 + width=24 + height=12 + } + display[0] { + label="m5" + name="motorx_more.adl" + args="P=$(P),M=m93" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=500 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m93.DMOV" + } +} +rectangle { + object { + x=500 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=500 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="93" + align="horiz. centered" +} +rectangle { + object { + x=499 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=500 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m94.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=534 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m94_able.VAL" + } +} +rectangle { + object { + x=524 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m94.LLS" + } +} +rectangle { + object { + x=524 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m94.LVIO" + } +} +rectangle { + object { + x=524 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m94.HLS" + } +} +"related display" { + object { + x=500 + y=211 + width=24 + height=12 + } + display[0] { + label="m6" + name="motorx_more.adl" + args="P=$(P),M=m94" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=500 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m94.DMOV" + } +} +rectangle { + object { + x=500 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=500 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="94" + align="horiz. centered" +} +rectangle { + object { + x=499 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=500 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m95.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=534 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m95_able.VAL" + } +} +rectangle { + object { + x=524 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m95.LLS" + } +} +rectangle { + object { + x=524 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m95.LVIO" + } +} +rectangle { + object { + x=524 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m95.HLS" + } +} +"related display" { + object { + x=500 + y=247 + width=24 + height=12 + } + display[0] { + label="m7" + name="motorx_more.adl" + args="P=$(P),M=m95" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=500 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m95.DMOV" + } +} +rectangle { + object { + x=500 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=500 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="95" + align="horiz. centered" +} +rectangle { + object { + x=499 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=500 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m96.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=534 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m96_able.VAL" + } +} +rectangle { + object { + x=524 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m96.LLS" + } +} +rectangle { + object { + x=524 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m96.LVIO" + } +} +rectangle { + object { + x=524 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m96.HLS" + } +} +"related display" { + object { + x=500 + y=283 + width=24 + height=12 + } + display[0] { + label="m8" + name="motorx_more.adl" + args="P=$(P),M=m96" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=500 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m96.DMOV" + } +} +rectangle { + object { + x=500 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=500 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="96" + align="horiz. centered" +} +rectangle { + object { + x=499 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=500 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m89.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=534 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m89_able.VAL" + } +} +rectangle { + object { + x=524 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m89.LLS" + } +} +rectangle { + object { + x=524 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m89.LVIO" + } +} +rectangle { + object { + x=524 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m89.HLS" + } +} +"related display" { + object { + x=500 + y=31 + width=24 + height=12 + } + display[0] { + label="m1" + name="motorx_more.adl" + args="P=$(P),M=m89" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=500 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m89.DMOV" + } +} +rectangle { + object { + x=500 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=500 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="89" + align="horiz. centered" +} +rectangle { + object { + x=499 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=500 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m90.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=534 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m90_able.VAL" + } +} +rectangle { + object { + x=524 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m90.LLS" + } +} +rectangle { + object { + x=524 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m90.LVIO" + } +} +rectangle { + object { + x=524 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m90.HLS" + } +} +"related display" { + object { + x=500 + y=67 + width=24 + height=12 + } + display[0] { + label="m2" + name="motorx_more.adl" + args="P=$(P),M=m90" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=500 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m90.DMOV" + } +} +rectangle { + object { + x=500 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=500 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="90" + align="horiz. centered" +} +"text update" { + object { + x=500 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m89.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=500 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m90.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=500 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m91.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=500 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m92.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=500 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m93.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=500 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m94.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=500 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m95.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=500 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m96.RBV" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=544 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=545 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m99.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=579 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m99_able.VAL" + } +} +rectangle { + object { + x=569 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m99.LLS" + } +} +rectangle { + object { + x=569 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m99.LVIO" + } +} +rectangle { + object { + x=569 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m99.HLS" + } +} +"related display" { + object { + x=545 + y=103 + width=24 + height=12 + } + display[0] { + label="m3" + name="motorx_more.adl" + args="P=$(P),M=m99" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=545 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m99.DMOV" + } +} +rectangle { + object { + x=545 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=545 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="99" + align="horiz. centered" +} +rectangle { + object { + x=544 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=545 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m100.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=579 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m100_able.VAL" + } +} +rectangle { + object { + x=569 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m100.LLS" + } +} +rectangle { + object { + x=569 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m100.LVIO" + } +} +rectangle { + object { + x=569 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m100.HLS" + } +} +"related display" { + object { + x=545 + y=139 + width=24 + height=12 + } + display[0] { + label="m4" + name="motorx_more.adl" + args="P=$(P),M=m100" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=545 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m100.DMOV" + } +} +rectangle { + object { + x=545 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=545 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="100" + align="horiz. centered" +} +rectangle { + object { + x=544 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=545 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m101.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=579 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m101_able.VAL" + } +} +rectangle { + object { + x=569 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m101.LLS" + } +} +rectangle { + object { + x=569 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m101.LVIO" + } +} +rectangle { + object { + x=569 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m101.HLS" + } +} +"related display" { + object { + x=545 + y=175 + width=24 + height=12 + } + display[0] { + label="m5" + name="motorx_more.adl" + args="P=$(P),M=m101" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=545 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m101.DMOV" + } +} +rectangle { + object { + x=545 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=545 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="101" + align="horiz. centered" +} +rectangle { + object { + x=544 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=545 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m102.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=579 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m102_able.VAL" + } +} +rectangle { + object { + x=569 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m102.LLS" + } +} +rectangle { + object { + x=569 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m102.LVIO" + } +} +rectangle { + object { + x=569 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m102.HLS" + } +} +"related display" { + object { + x=545 + y=211 + width=24 + height=12 + } + display[0] { + label="m6" + name="motorx_more.adl" + args="P=$(P),M=m102" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=545 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m102.DMOV" + } +} +rectangle { + object { + x=545 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=545 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="102" + align="horiz. centered" +} +rectangle { + object { + x=544 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=545 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m103.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=579 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m103_able.VAL" + } +} +rectangle { + object { + x=569 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m103.LLS" + } +} +rectangle { + object { + x=569 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m103.LVIO" + } +} +rectangle { + object { + x=569 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m103.HLS" + } +} +"related display" { + object { + x=545 + y=247 + width=24 + height=12 + } + display[0] { + label="m7" + name="motorx_more.adl" + args="P=$(P),M=m103" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=545 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m103.DMOV" + } +} +rectangle { + object { + x=545 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=545 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="103" + align="horiz. centered" +} +rectangle { + object { + x=544 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=545 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m104.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=579 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m104_able.VAL" + } +} +rectangle { + object { + x=569 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m104.LLS" + } +} +rectangle { + object { + x=569 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m104.LVIO" + } +} +rectangle { + object { + x=569 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m104.HLS" + } +} +"related display" { + object { + x=545 + y=283 + width=24 + height=12 + } + display[0] { + label="m8" + name="motorx_more.adl" + args="P=$(P),M=m104" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=545 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m104.DMOV" + } +} +rectangle { + object { + x=545 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=545 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="104" + align="horiz. centered" +} +rectangle { + object { + x=544 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=545 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m97.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=579 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m97_able.VAL" + } +} +rectangle { + object { + x=569 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m97.LLS" + } +} +rectangle { + object { + x=569 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m97.LVIO" + } +} +rectangle { + object { + x=569 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m97.HLS" + } +} +"related display" { + object { + x=545 + y=31 + width=24 + height=12 + } + display[0] { + label="m1" + name="motorx_more.adl" + args="P=$(P),M=m97" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=545 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m97.DMOV" + } +} +rectangle { + object { + x=545 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=545 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="97" + align="horiz. centered" +} +rectangle { + object { + x=544 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=545 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m98.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=579 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m98_able.VAL" + } +} +rectangle { + object { + x=569 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m98.LLS" + } +} +rectangle { + object { + x=569 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m98.LVIO" + } +} +rectangle { + object { + x=569 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m98.HLS" + } +} +"related display" { + object { + x=545 + y=67 + width=24 + height=12 + } + display[0] { + label="m2" + name="motorx_more.adl" + args="P=$(P),M=m98" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=545 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m98.DMOV" + } +} +rectangle { + object { + x=545 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=545 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="98" + align="horiz. centered" +} +"text update" { + object { + x=545 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m97.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=545 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m98.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=545 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m99.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=545 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m100.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=545 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m101.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=545 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m102.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=545 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m103.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=545 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m104.RBV" + clr=14 + bclr=0 + } + limits { + } +} +text { + object { + x=0 + y=0 + width=85 + height=14 + } + "basic attribute" { + clr=14 + } + textix="$(P) motors" + align="horiz. centered" +} +rectangle { + object { + x=589 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=590 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m107.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=624 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m107_able.VAL" + } +} +rectangle { + object { + x=614 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m107.LLS" + } +} +rectangle { + object { + x=614 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m107.LVIO" + } +} +rectangle { + object { + x=614 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m107.HLS" + } +} +"related display" { + object { + x=590 + y=103 + width=24 + height=12 + } + display[0] { + label="m107" + name="motorx_more.adl" + args="P=$(P),M=m107" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=590 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m107.DMOV" + } +} +rectangle { + object { + x=590 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=590 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="107" + align="horiz. centered" +} +rectangle { + object { + x=589 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=590 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m108.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=624 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m108_able.VAL" + } +} +rectangle { + object { + x=614 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m108.LLS" + } +} +rectangle { + object { + x=614 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m108.LVIO" + } +} +rectangle { + object { + x=614 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m108.HLS" + } +} +"related display" { + object { + x=590 + y=139 + width=24 + height=12 + } + display[0] { + label="m108" + name="motorx_more.adl" + args="P=$(P),M=m108" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=590 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m108.DMOV" + } +} +rectangle { + object { + x=590 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=590 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="108" + align="horiz. centered" +} +rectangle { + object { + x=589 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=590 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m109.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=624 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m109_able.VAL" + } +} +rectangle { + object { + x=614 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m109.LLS" + } +} +rectangle { + object { + x=614 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m109.LVIO" + } +} +rectangle { + object { + x=614 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m109.HLS" + } +} +"related display" { + object { + x=590 + y=175 + width=24 + height=12 + } + display[0] { + label="m109" + name="motorx_more.adl" + args="P=$(P),M=m109" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=590 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m109.DMOV" + } +} +rectangle { + object { + x=590 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=590 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="109" + align="horiz. centered" +} +rectangle { + object { + x=589 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=590 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m110.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=624 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m110_able.VAL" + } +} +rectangle { + object { + x=614 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m110.LLS" + } +} +rectangle { + object { + x=614 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m110.LVIO" + } +} +rectangle { + object { + x=614 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m110.HLS" + } +} +"related display" { + object { + x=590 + y=211 + width=24 + height=12 + } + display[0] { + label="m110" + name="motorx_more.adl" + args="P=$(P),M=m110" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=590 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m110.DMOV" + } +} +rectangle { + object { + x=590 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=590 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="110" + align="horiz. centered" +} +rectangle { + object { + x=589 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=590 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m111.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=624 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m111_able.VAL" + } +} +rectangle { + object { + x=614 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m111.LLS" + } +} +rectangle { + object { + x=614 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m111.LVIO" + } +} +rectangle { + object { + x=614 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m111.HLS" + } +} +"related display" { + object { + x=590 + y=247 + width=24 + height=12 + } + display[0] { + label="m111" + name="motorx_more.adl" + args="P=$(P),M=m111" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=590 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m111.DMOV" + } +} +rectangle { + object { + x=590 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=590 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="111" + align="horiz. centered" +} +rectangle { + object { + x=589 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=590 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m112.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=624 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m112_able.VAL" + } +} +rectangle { + object { + x=614 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m112.LLS" + } +} +rectangle { + object { + x=614 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m112.LVIO" + } +} +rectangle { + object { + x=614 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m112.HLS" + } +} +"related display" { + object { + x=590 + y=283 + width=24 + height=12 + } + display[0] { + label="m112" + name="motorx_more.adl" + args="P=$(P),M=m112" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=590 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m112.DMOV" + } +} +rectangle { + object { + x=590 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=590 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="112" + align="horiz. centered" +} +rectangle { + object { + x=589 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=590 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m105.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=624 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m105_able.VAL" + } +} +rectangle { + object { + x=614 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m105.LLS" + } +} +rectangle { + object { + x=614 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m105.LVIO" + } +} +rectangle { + object { + x=614 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m105.HLS" + } +} +"related display" { + object { + x=590 + y=31 + width=24 + height=12 + } + display[0] { + label="m105" + name="motorx_more.adl" + args="P=$(P),M=m105" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=590 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m105.DMOV" + } +} +rectangle { + object { + x=590 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=590 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="105" + align="horiz. centered" +} +rectangle { + object { + x=589 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=590 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m106.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=624 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m106_able.VAL" + } +} +rectangle { + object { + x=614 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m106.LLS" + } +} +rectangle { + object { + x=614 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m106.LVIO" + } +} +rectangle { + object { + x=614 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m106.HLS" + } +} +"related display" { + object { + x=590 + y=67 + width=24 + height=12 + } + display[0] { + label="m2" + name="motorx_more.adl" + args="P=$(P),M=m106" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=590 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m106.DMOV" + } +} +rectangle { + object { + x=590 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=590 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="106" + align="horiz. centered" +} +"text update" { + object { + x=590 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m105.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=590 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m106.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=590 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m107.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=590 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m108.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=590 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m109.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=590 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m110.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=590 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m111.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=590 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m112.RBV" + clr=14 + bclr=0 + } + limits { + } +} +text { + object { + x=0 + y=0 + width=85 + height=14 + } + "basic attribute" { + clr=14 + } + textix="$(P) motors" + align="horiz. centered" +} +rectangle { + object { + x=634 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=635 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m115.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=669 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m115_able.VAL" + } +} +rectangle { + object { + x=659 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m115.LLS" + } +} +rectangle { + object { + x=659 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m115.LVIO" + } +} +rectangle { + object { + x=659 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m115.HLS" + } +} +"related display" { + object { + x=635 + y=103 + width=24 + height=12 + } + display[0] { + label="m115" + name="motorx_more.adl" + args="P=$(P),M=m115" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=635 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m115.DMOV" + } +} +rectangle { + object { + x=635 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=635 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="115" + align="horiz. centered" +} +rectangle { + object { + x=634 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=635 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m116.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=669 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m116_able.VAL" + } +} +rectangle { + object { + x=659 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m116.LLS" + } +} +rectangle { + object { + x=659 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m116.LVIO" + } +} +rectangle { + object { + x=659 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m116.HLS" + } +} +"related display" { + object { + x=635 + y=139 + width=24 + height=12 + } + display[0] { + label="m116" + name="motorx_more.adl" + args="P=$(P),M=m116" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=635 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m116.DMOV" + } +} +rectangle { + object { + x=635 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=635 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="116" + align="horiz. centered" +} +rectangle { + object { + x=634 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=635 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m117.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=669 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m117_able.VAL" + } +} +rectangle { + object { + x=659 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m117.LLS" + } +} +rectangle { + object { + x=659 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m117.LVIO" + } +} +rectangle { + object { + x=659 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m117.HLS" + } +} +"related display" { + object { + x=635 + y=175 + width=24 + height=12 + } + display[0] { + label="m117" + name="motorx_more.adl" + args="P=$(P),M=m117" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=635 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m117.DMOV" + } +} +rectangle { + object { + x=635 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=635 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="117" + align="horiz. centered" +} +rectangle { + object { + x=634 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=635 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m118.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=669 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m118_able.VAL" + } +} +rectangle { + object { + x=659 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m118.LLS" + } +} +rectangle { + object { + x=659 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m118.LVIO" + } +} +rectangle { + object { + x=659 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m118.HLS" + } +} +"related display" { + object { + x=635 + y=211 + width=24 + height=12 + } + display[0] { + label="m118" + name="motorx_more.adl" + args="P=$(P),M=m118" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=635 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m118.DMOV" + } +} +rectangle { + object { + x=635 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=635 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="118" + align="horiz. centered" +} +rectangle { + object { + x=634 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=635 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m119.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=669 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m119_able.VAL" + } +} +rectangle { + object { + x=659 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m119.LLS" + } +} +rectangle { + object { + x=659 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m119.LVIO" + } +} +rectangle { + object { + x=659 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m119.HLS" + } +} +"related display" { + object { + x=635 + y=247 + width=24 + height=12 + } + display[0] { + label="m119" + name="motorx_more.adl" + args="P=$(P),M=m119" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=635 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m119.DMOV" + } +} +rectangle { + object { + x=635 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=635 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="119" + align="horiz. centered" +} +rectangle { + object { + x=634 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=635 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m120.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=669 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m120_able.VAL" + } +} +rectangle { + object { + x=659 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m120.LLS" + } +} +rectangle { + object { + x=659 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m120.LVIO" + } +} +rectangle { + object { + x=659 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m120.HLS" + } +} +"related display" { + object { + x=635 + y=283 + width=24 + height=12 + } + display[0] { + label="m120" + name="motorx_more.adl" + args="P=$(P),M=m120" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=635 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m120.DMOV" + } +} +rectangle { + object { + x=635 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=635 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="120" + align="horiz. centered" +} +rectangle { + object { + x=634 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=635 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m113.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=669 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m113_able.VAL" + } +} +rectangle { + object { + x=659 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m113.LLS" + } +} +rectangle { + object { + x=659 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m113.LVIO" + } +} +rectangle { + object { + x=659 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m113.HLS" + } +} +"related display" { + object { + x=635 + y=31 + width=24 + height=12 + } + display[0] { + label="m113" + name="motorx_more.adl" + args="P=$(P),M=m113" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=635 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m113.DMOV" + } +} +rectangle { + object { + x=635 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=635 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="113" + align="horiz. centered" +} +rectangle { + object { + x=634 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=635 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m114.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=669 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m114_able.VAL" + } +} +rectangle { + object { + x=659 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m114.LLS" + } +} +rectangle { + object { + x=659 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m114.LVIO" + } +} +rectangle { + object { + x=659 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m114.HLS" + } +} +"related display" { + object { + x=635 + y=67 + width=24 + height=12 + } + display[0] { + label="m2" + name="motorx_more.adl" + args="P=$(P),M=m114" + } + clr=14 + bclr=51 + visual="invisible" +} +rectangle { + object { + x=635 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m114.DMOV" + } +} +rectangle { + object { + x=635 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } +} +text { + object { + x=635 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="114" + align="horiz. centered" +} +"text update" { + object { + x=635 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m113.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=635 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m114.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=635 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m115.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=635 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m116.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=635 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m117.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=635 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m118.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=635 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m119.RBV" + clr=14 + bclr=0 + } + limits { + } +} +"text update" { + object { + x=635 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m120.RBV" + clr=14 + bclr=0 + } + limits { + } +} diff --git a/motorApp/op/adl/motorStatus96.adl b/motorApp/op/adl/motorStatus96.adl new file mode 100644 index 0000000..0c0f9c7 --- /dev/null +++ b/motorApp/op/adl/motorStatus96.adl @@ -0,0 +1,17148 @@ + +file { + name="/net/s8dserv/xorApps/epics/synApps_5_7/ioc/8id/8idApp/op/adl/motorStatus96.adl" + version=030107 +} +display { + object { + x=2019 + y=339 + width=537 + height=308 + } + clr=7 + bclr=2 + cmap="" + gridSpacing=5 + gridOn=0 + snapToGrid=1 +} +"color map" { + ncolors=65 + colors { + ffffff, + ececec, + dadada, + c8c8c8, + bbbbbb, + aeaeae, + 9e9e9e, + 919191, + 858585, + 787878, + 696969, + 5a5a5a, + 464646, + 2d2d2d, + 000000, + 00d800, + 1ebb00, + 339900, + 2d7f00, + 216c00, + fd0000, + de1309, + be190b, + a01207, + 820400, + 5893ff, + 597ee1, + 4b6ec7, + 3a5eab, + 27548d, + fbf34a, + f9da3c, + eeb62b, + e19015, + cd6100, + ffb0ff, + d67fe2, + ae4ebc, + 8b1a96, + 610a75, + a4aaff, + 8793e2, + 6a73c1, + 4d52a4, + 343386, + c7bb6d, + b79d5c, + a47e3c, + 7d5627, + 58340f, + 99ffff, + 73dfff, + 4ea5f9, + 2a63e4, + 0a00b8, + ebf1b5, + d4db9d, + bbc187, + a6a462, + 8b8239, + 73ff6b, + 52da3b, + 3cb420, + 289315, + 1a7309, + } +} +text { + object { + x=0 + y=0 + width=500 + height=20 + } + "basic attribute" { + clr=14 + } + textix=" $(P) motor status" + align="horiz. centered" +} +composite { + object { + x=365 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=365 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=366 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m68.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=400 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m68_able.VAL" + } + } + rectangle { + object { + x=390 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m68.LLS" + } + } + rectangle { + object { + x=390 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m68.LVIO" + } + } + rectangle { + object { + x=390 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m68.HLS" + } + } + composite { + object { + x=366 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=366 + y=139 + width=24 + height=12 + } + display[0] { + label="m68" + name="motorx_more.adl" + args="P=$(P),M=m68" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=366 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m68.DMOV" + } + } + rectangle { + object { + x=366 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=366 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="68" + align="horiz. centered" + } + } + } + "text update" { + object { + x=366 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m68.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=320 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=320 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=321 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m60.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=355 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m60_able.VAL" + } + } + rectangle { + object { + x=345 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m60.LLS" + } + } + rectangle { + object { + x=345 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m60.LVIO" + } + } + rectangle { + object { + x=345 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m60.HLS" + } + } + composite { + object { + x=321 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=321 + y=139 + width=24 + height=12 + } + display[0] { + label="m60" + name="motorx_more.adl" + args="P=$(P),M=m60" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=321 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m60.DMOV" + } + } + rectangle { + object { + x=321 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=321 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="60" + align="horiz. centered" + } + } + } + "text update" { + object { + x=321 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m60.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=365 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=365 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=366 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m65.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=400 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m65_able.VAL" + } + } + rectangle { + object { + x=390 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m65.LLS" + } + } + rectangle { + object { + x=390 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m65.LVIO" + } + } + rectangle { + object { + x=390 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m65.HLS" + } + } + composite { + object { + x=366 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=366 + y=31 + width=24 + height=12 + } + display[0] { + label="m65" + name="motorx_more.adl" + args="P=$(P),M=m65" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=366 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m65.DMOV" + } + } + rectangle { + object { + x=366 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=366 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="65" + align="horiz. centered" + } + } + } + "text update" { + object { + x=366 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m65.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=365 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=365 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=366 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m66.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=400 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m66_able.VAL" + } + } + rectangle { + object { + x=390 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m66.LLS" + } + } + rectangle { + object { + x=390 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m66.LVIO" + } + } + rectangle { + object { + x=390 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m66.HLS" + } + } + composite { + object { + x=366 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=366 + y=67 + width=24 + height=12 + } + display[0] { + label="m66" + name="motorx_more.adl" + args="P=$(P),M=m66" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=366 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m66.DMOV" + } + } + rectangle { + object { + x=366 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=366 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="66" + align="horiz. centered" + } + } + } + "text update" { + object { + x=366 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m66.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=365 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=365 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=366 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m67.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=400 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m67_able.VAL" + } + } + rectangle { + object { + x=390 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m67.LLS" + } + } + rectangle { + object { + x=390 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m67.LVIO" + } + } + rectangle { + object { + x=390 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m67.HLS" + } + } + composite { + object { + x=366 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=366 + y=103 + width=24 + height=12 + } + display[0] { + label="m67" + name="motorx_more.adl" + args="P=$(P),M=m67" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=366 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m67.DMOV" + } + } + rectangle { + object { + x=366 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=366 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="67" + align="horiz. centered" + } + } + } + "text update" { + object { + x=366 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m67.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=320 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=320 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=321 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m57.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=355 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m57_able.VAL" + } + } + rectangle { + object { + x=345 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m57.LLS" + } + } + rectangle { + object { + x=345 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m57.LVIO" + } + } + rectangle { + object { + x=345 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m57.HLS" + } + } + composite { + object { + x=321 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=321 + y=31 + width=24 + height=12 + } + display[0] { + label="m57" + name="motorx_more.adl" + args="P=$(P),M=m57" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=321 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m57.DMOV" + } + } + rectangle { + object { + x=321 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=321 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="57" + align="horiz. centered" + } + } + } + "text update" { + object { + x=321 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m57.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=320 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=320 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=321 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m58.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=355 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m58_able.VAL" + } + } + rectangle { + object { + x=345 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m58.LLS" + } + } + rectangle { + object { + x=345 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m58.LVIO" + } + } + rectangle { + object { + x=345 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m58.HLS" + } + } + composite { + object { + x=321 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=321 + y=67 + width=24 + height=12 + } + display[0] { + label="m58" + name="motorx_more.adl" + args="P=$(P),M=m58" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=321 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m58.DMOV" + } + } + rectangle { + object { + x=321 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=321 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="58" + align="horiz. centered" + } + } + } + "text update" { + object { + x=321 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m58.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=320 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=320 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=321 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m59.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=355 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m59_able.VAL" + } + } + rectangle { + object { + x=345 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m59.LLS" + } + } + rectangle { + object { + x=345 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m59.LVIO" + } + } + rectangle { + object { + x=345 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m59.HLS" + } + } + composite { + object { + x=321 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=321 + y=103 + width=24 + height=12 + } + display[0] { + label="m59" + name="motorx_more.adl" + args="P=$(P),M=m59" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=321 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m59.DMOV" + } + } + rectangle { + object { + x=321 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=321 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="59" + align="horiz. centered" + } + } + } + "text update" { + object { + x=321 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m59.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=320 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=320 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=321 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m61.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=355 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m61_able.VAL" + } + } + rectangle { + object { + x=345 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m61.LLS" + } + } + rectangle { + object { + x=345 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m61.LVIO" + } + } + rectangle { + object { + x=345 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m61.HLS" + } + } + composite { + object { + x=321 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=321 + y=175 + width=24 + height=12 + } + display[0] { + label="m61" + name="motorx_more.adl" + args="P=$(P),M=m61" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=321 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m61.DMOV" + } + } + rectangle { + object { + x=321 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=321 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="61" + align="horiz. centered" + } + } + } + "text update" { + object { + x=321 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m61.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=365 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=365 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=366 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m69.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=400 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m69_able.VAL" + } + } + rectangle { + object { + x=390 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m69.LLS" + } + } + rectangle { + object { + x=390 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m69.LVIO" + } + } + rectangle { + object { + x=390 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m69.HLS" + } + } + composite { + object { + x=366 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=366 + y=175 + width=24 + height=12 + } + display[0] { + label="m69" + name="motorx_more.adl" + args="P=$(P),M=m69" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=366 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m69.DMOV" + } + } + rectangle { + object { + x=366 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=366 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="69" + align="horiz. centered" + } + } + } + "text update" { + object { + x=366 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m69.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=365 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=365 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=366 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m70.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=400 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m70_able.VAL" + } + } + rectangle { + object { + x=390 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m70.LLS" + } + } + rectangle { + object { + x=390 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m70.LVIO" + } + } + rectangle { + object { + x=390 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m70.HLS" + } + } + composite { + object { + x=366 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=366 + y=211 + width=24 + height=12 + } + display[0] { + label="m70" + name="motorx_more.adl" + args="P=$(P),M=m70" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=366 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m70.DMOV" + } + } + rectangle { + object { + x=366 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=366 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="70" + align="horiz. centered" + } + } + } + "text update" { + object { + x=366 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m70.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=320 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=320 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=321 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m62.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=355 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m62_able.VAL" + } + } + rectangle { + object { + x=345 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m62.LLS" + } + } + rectangle { + object { + x=345 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m62.LVIO" + } + } + rectangle { + object { + x=345 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m62.HLS" + } + } + composite { + object { + x=321 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=321 + y=211 + width=24 + height=12 + } + display[0] { + label="m62" + name="motorx_more.adl" + args="P=$(P),M=m62" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=321 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m62.DMOV" + } + } + rectangle { + object { + x=321 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=321 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="62" + align="horiz. centered" + } + } + } + "text update" { + object { + x=321 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m62.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=320 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=320 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=321 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m63.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=355 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m63_able.VAL" + } + } + rectangle { + object { + x=345 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m63.LLS" + } + } + rectangle { + object { + x=345 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m63.LVIO" + } + } + rectangle { + object { + x=345 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m63.HLS" + } + } + composite { + object { + x=321 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=321 + y=247 + width=24 + height=12 + } + display[0] { + label="m63" + name="motorx_more.adl" + args="P=$(P),M=m63" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=321 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m63.DMOV" + } + } + rectangle { + object { + x=321 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=321 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="63" + align="horiz. centered" + } + } + } + "text update" { + object { + x=321 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m63.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=365 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=365 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=366 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m71.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=400 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m71_able.VAL" + } + } + rectangle { + object { + x=390 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m71.LLS" + } + } + rectangle { + object { + x=390 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m71.LVIO" + } + } + rectangle { + object { + x=390 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m71.HLS" + } + } + composite { + object { + x=366 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=366 + y=247 + width=24 + height=12 + } + display[0] { + label="m71" + name="motorx_more.adl" + args="P=$(P),M=m71" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=366 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m71.DMOV" + } + } + rectangle { + object { + x=366 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=366 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="71" + align="horiz. centered" + } + } + } + "text update" { + object { + x=366 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m71.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=365 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=366 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m72.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=400 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m72_able.VAL" + } +} +rectangle { + object { + x=390 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m72.LLS" + } +} +rectangle { + object { + x=390 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m72.LVIO" + } +} +rectangle { + object { + x=390 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m72.HLS" + } +} +composite { + object { + x=366 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=366 + y=283 + width=24 + height=12 + } + display[0] { + label="m72" + name="motorx_more.adl" + args="P=$(P),M=m72" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=366 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m72.DMOV" + } + } + rectangle { + object { + x=366 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=366 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="72" + align="horiz. centered" + } + } +} +"text update" { + object { + x=366 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m72.RBV" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=320 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=321 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m64.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=355 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m64_able.VAL" + } +} +rectangle { + object { + x=345 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m64.LLS" + } +} +rectangle { + object { + x=345 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m64.LVIO" + } +} +rectangle { + object { + x=345 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m64.HLS" + } +} +composite { + object { + x=321 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=321 + y=283 + width=24 + height=12 + } + display[0] { + label="m64" + name="motorx_more.adl" + args="P=$(P),M=m64" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=321 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m64.DMOV" + } + } + rectangle { + object { + x=321 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=321 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="64" + align="horiz. centered" + } + } +} +"text update" { + object { + x=321 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m64.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=275 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=275 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=276 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m49.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=310 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m49_able.VAL" + } + } + rectangle { + object { + x=300 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m49.LLS" + } + } + rectangle { + object { + x=300 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m49.LVIO" + } + } + rectangle { + object { + x=300 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m49.HLS" + } + } + composite { + object { + x=276 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=276 + y=31 + width=24 + height=12 + } + display[0] { + label="m49" + name="motorx_more.adl" + args="P=$(P),M=m49" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=276 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m49.DMOV" + } + } + rectangle { + object { + x=276 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=276 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="49" + align="horiz. centered" + } + } + } + "text update" { + object { + x=276 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m49.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=275 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=275 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=276 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m50.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=310 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m50_able.VAL" + } + } + rectangle { + object { + x=300 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m50.LLS" + } + } + rectangle { + object { + x=300 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m50.LVIO" + } + } + rectangle { + object { + x=300 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m50.HLS" + } + } + composite { + object { + x=276 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=276 + y=67 + width=24 + height=12 + } + display[0] { + label="m50" + name="motorx_more.adl" + args="P=$(P),M=m50" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=276 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m50.DMOV" + } + } + rectangle { + object { + x=276 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=276 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="50" + align="horiz. centered" + } + } + } + "text update" { + object { + x=276 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m50.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=275 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=275 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=276 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m51.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=310 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m51_able.VAL" + } + } + rectangle { + object { + x=300 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m51.LLS" + } + } + rectangle { + object { + x=300 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m51.LVIO" + } + } + rectangle { + object { + x=300 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m51.HLS" + } + } + composite { + object { + x=276 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=276 + y=103 + width=24 + height=12 + } + display[0] { + label="m51" + name="motorx_more.adl" + args="P=$(P),M=m51" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=276 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m51.DMOV" + } + } + rectangle { + object { + x=276 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=276 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="51" + align="horiz. centered" + } + } + } + "text update" { + object { + x=276 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m51.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=275 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=275 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=276 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m52.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=310 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m52_able.VAL" + } + } + rectangle { + object { + x=300 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m52.LLS" + } + } + rectangle { + object { + x=300 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m52.LVIO" + } + } + rectangle { + object { + x=300 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m52.HLS" + } + } + composite { + object { + x=276 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=276 + y=139 + width=24 + height=12 + } + display[0] { + label="m52" + name="motorx_more.adl" + args="P=$(P),M=m52" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=276 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m52.DMOV" + } + } + rectangle { + object { + x=276 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=276 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="52" + align="horiz. centered" + } + } + } + "text update" { + object { + x=276 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m52.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=275 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=275 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=276 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m53.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=310 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m53_able.VAL" + } + } + rectangle { + object { + x=300 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m53.LLS" + } + } + rectangle { + object { + x=300 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m53.LVIO" + } + } + rectangle { + object { + x=300 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m53.HLS" + } + } + composite { + object { + x=276 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=276 + y=175 + width=24 + height=12 + } + display[0] { + label="m53" + name="motorx_more.adl" + args="P=$(P),M=m53" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=276 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m53.DMOV" + } + } + rectangle { + object { + x=276 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=276 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="53" + align="horiz. centered" + } + } + } + "text update" { + object { + x=276 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m53.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=275 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=275 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=276 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m54.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=310 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m54_able.VAL" + } + } + rectangle { + object { + x=300 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m54.LLS" + } + } + rectangle { + object { + x=300 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m54.LVIO" + } + } + rectangle { + object { + x=300 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m54.HLS" + } + } + composite { + object { + x=276 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=276 + y=211 + width=24 + height=12 + } + display[0] { + label="m54" + name="motorx_more.adl" + args="P=$(P),M=m54" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=276 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m54.DMOV" + } + } + rectangle { + object { + x=276 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=276 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="54" + align="horiz. centered" + } + } + } + "text update" { + object { + x=276 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m54.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=275 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=275 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=276 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m55.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=310 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m55_able.VAL" + } + } + rectangle { + object { + x=300 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m55.LLS" + } + } + rectangle { + object { + x=300 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m55.LVIO" + } + } + rectangle { + object { + x=300 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m55.HLS" + } + } + composite { + object { + x=276 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=276 + y=247 + width=24 + height=12 + } + display[0] { + label="m55" + name="motorx_more.adl" + args="P=$(P),M=m55" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=276 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m55.DMOV" + } + } + rectangle { + object { + x=276 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=276 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="55" + align="horiz. centered" + } + } + } + "text update" { + object { + x=276 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m55.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=275 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=276 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m56.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=310 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m56_able.VAL" + } +} +rectangle { + object { + x=300 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m56.LLS" + } +} +rectangle { + object { + x=300 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m56.LVIO" + } +} +rectangle { + object { + x=300 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m56.HLS" + } +} +composite { + object { + x=276 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=276 + y=283 + width=24 + height=12 + } + display[0] { + label="m56" + name="motorx_more.adl" + args="P=$(P),M=m56" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=276 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m56.DMOV" + } + } + rectangle { + object { + x=276 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=276 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="56" + align="horiz. centered" + } + } +} +"text update" { + object { + x=276 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m56.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=230 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=230 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=231 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m41.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=265 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m41_able.VAL" + } + } + rectangle { + object { + x=255 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m41.LLS" + } + } + rectangle { + object { + x=255 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m41.LVIO" + } + } + rectangle { + object { + x=255 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m41.HLS" + } + } + composite { + object { + x=231 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=231 + y=31 + width=24 + height=12 + } + display[0] { + label="m41" + name="motorx_more.adl" + args="P=$(P),M=m41" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=231 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m41.DMOV" + } + } + rectangle { + object { + x=231 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=231 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="41" + align="horiz. centered" + } + } + } + "text update" { + object { + x=231 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m41.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=230 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=230 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=231 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m42.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=265 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m42_able.VAL" + } + } + rectangle { + object { + x=255 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m42.LLS" + } + } + rectangle { + object { + x=255 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m42.LVIO" + } + } + rectangle { + object { + x=255 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m42.HLS" + } + } + composite { + object { + x=231 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=231 + y=67 + width=24 + height=12 + } + display[0] { + label="m42" + name="motorx_more.adl" + args="P=$(P),M=m42" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=231 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m42.DMOV" + } + } + rectangle { + object { + x=231 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=231 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="42" + align="horiz. centered" + } + } + } + "text update" { + object { + x=231 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m42.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=230 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=230 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=231 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m43.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=265 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m43_able.VAL" + } + } + rectangle { + object { + x=255 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m43.LLS" + } + } + rectangle { + object { + x=255 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m43.LVIO" + } + } + rectangle { + object { + x=255 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m43.HLS" + } + } + composite { + object { + x=231 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=231 + y=103 + width=24 + height=12 + } + display[0] { + label="m43" + name="motorx_more.adl" + args="P=$(P),M=m43" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=231 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m43.DMOV" + } + } + rectangle { + object { + x=231 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=231 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="43" + align="horiz. centered" + } + } + } + "text update" { + object { + x=231 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m43.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=230 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=230 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=231 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m44.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=265 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m44_able.VAL" + } + } + rectangle { + object { + x=255 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m44.LLS" + } + } + rectangle { + object { + x=255 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m44.LVIO" + } + } + rectangle { + object { + x=255 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m44.HLS" + } + } + composite { + object { + x=231 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=231 + y=139 + width=24 + height=12 + } + display[0] { + label="m44" + name="motorx_more.adl" + args="P=$(P),M=m44" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=231 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m44.DMOV" + } + } + rectangle { + object { + x=231 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=231 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="44" + align="horiz. centered" + } + } + } + "text update" { + object { + x=231 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m44.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=230 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=230 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=231 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m45.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=265 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m45_able.VAL" + } + } + rectangle { + object { + x=255 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m45.LLS" + } + } + rectangle { + object { + x=255 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m45.LVIO" + } + } + rectangle { + object { + x=255 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m45.HLS" + } + } + composite { + object { + x=231 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=231 + y=175 + width=24 + height=12 + } + display[0] { + label="m45" + name="motorx_more.adl" + args="P=$(P),M=m45" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=231 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m45.DMOV" + } + } + rectangle { + object { + x=231 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=231 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="45" + align="horiz. centered" + } + } + } + "text update" { + object { + x=231 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m45.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=230 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=230 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=231 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m46.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=265 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m46_able.VAL" + } + } + rectangle { + object { + x=255 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m46.LLS" + } + } + rectangle { + object { + x=255 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m46.LVIO" + } + } + rectangle { + object { + x=255 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m46.HLS" + } + } + composite { + object { + x=231 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=231 + y=211 + width=24 + height=12 + } + display[0] { + label="m46" + name="motorx_more.adl" + args="P=$(P),M=m46" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=231 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m46.DMOV" + } + } + rectangle { + object { + x=231 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=231 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="46" + align="horiz. centered" + } + } + } + "text update" { + object { + x=231 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m46.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=230 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=230 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=231 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m47.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=265 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m47_able.VAL" + } + } + rectangle { + object { + x=255 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m47.LLS" + } + } + rectangle { + object { + x=255 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m47.LVIO" + } + } + rectangle { + object { + x=255 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m47.HLS" + } + } + composite { + object { + x=231 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=231 + y=247 + width=24 + height=12 + } + display[0] { + label="m47" + name="motorx_more.adl" + args="P=$(P),M=m47" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=231 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m47.DMOV" + } + } + rectangle { + object { + x=231 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=231 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="47" + align="horiz. centered" + } + } + } + "text update" { + object { + x=231 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m47.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=230 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=231 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m48.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=265 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m48_able.VAL" + } +} +rectangle { + object { + x=255 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m48.LLS" + } +} +rectangle { + object { + x=255 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m48.LVIO" + } +} +rectangle { + object { + x=255 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m48.HLS" + } +} +composite { + object { + x=231 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=231 + y=283 + width=24 + height=12 + } + display[0] { + label="m48" + name="motorx_more.adl" + args="P=$(P),M=m48" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=231 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m48.DMOV" + } + } + rectangle { + object { + x=231 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=231 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="48" + align="horiz. centered" + } + } +} +"text update" { + object { + x=231 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m48.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=185 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=185 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=186 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m33.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=220 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m33_able.VAL" + } + } + rectangle { + object { + x=210 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m33.LLS" + } + } + rectangle { + object { + x=210 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m33.LVIO" + } + } + rectangle { + object { + x=210 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m33.HLS" + } + } + composite { + object { + x=186 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=186 + y=31 + width=24 + height=12 + } + display[0] { + label="m33" + name="motorx_more.adl" + args="P=$(P),M=m33" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=186 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m33.DMOV" + } + } + rectangle { + object { + x=186 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=186 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="33" + align="horiz. centered" + } + } + } + "text update" { + object { + x=186 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m33.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=185 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=185 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=186 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m34.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=220 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m34_able.VAL" + } + } + rectangle { + object { + x=210 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m34.LLS" + } + } + rectangle { + object { + x=210 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m34.LVIO" + } + } + rectangle { + object { + x=210 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m34.HLS" + } + } + composite { + object { + x=186 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=186 + y=67 + width=24 + height=12 + } + display[0] { + label="m34" + name="motorx_more.adl" + args="P=$(P),M=m34" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=186 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m34.DMOV" + } + } + rectangle { + object { + x=186 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=186 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="34" + align="horiz. centered" + } + } + } + "text update" { + object { + x=186 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m34.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=185 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=185 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=186 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m35.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=220 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m35_able.VAL" + } + } + rectangle { + object { + x=210 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m35.LLS" + } + } + rectangle { + object { + x=210 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m35.LVIO" + } + } + rectangle { + object { + x=210 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m35.HLS" + } + } + composite { + object { + x=186 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=186 + y=103 + width=24 + height=12 + } + display[0] { + label="m35" + name="motorx_more.adl" + args="P=$(P),M=m35" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=186 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m35.DMOV" + } + } + rectangle { + object { + x=186 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=186 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="35" + align="horiz. centered" + } + } + } + "text update" { + object { + x=186 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m35.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=185 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=185 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=186 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m36.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=220 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m36_able.VAL" + } + } + rectangle { + object { + x=210 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m36.LLS" + } + } + rectangle { + object { + x=210 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m36.LVIO" + } + } + rectangle { + object { + x=210 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m36.HLS" + } + } + composite { + object { + x=186 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=186 + y=139 + width=24 + height=12 + } + display[0] { + label="m36" + name="motorx_more.adl" + args="P=$(P),M=m36" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=186 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m36.DMOV" + } + } + rectangle { + object { + x=186 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=186 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="36" + align="horiz. centered" + } + } + } + "text update" { + object { + x=186 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m36.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=185 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=185 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=186 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m37.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=220 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m37_able.VAL" + } + } + rectangle { + object { + x=210 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m37.LLS" + } + } + rectangle { + object { + x=210 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m37.LVIO" + } + } + rectangle { + object { + x=210 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m37.HLS" + } + } + composite { + object { + x=186 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=186 + y=175 + width=24 + height=12 + } + display[0] { + label="m37" + name="motorx_more.adl" + args="P=$(P),M=m37" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=186 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m37.DMOV" + } + } + rectangle { + object { + x=186 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=186 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="37" + align="horiz. centered" + } + } + } + "text update" { + object { + x=186 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m37.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=185 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=185 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=186 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m38.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=220 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m38_able.VAL" + } + } + rectangle { + object { + x=210 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m38.LLS" + } + } + rectangle { + object { + x=210 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m38.LVIO" + } + } + rectangle { + object { + x=210 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m38.HLS" + } + } + composite { + object { + x=186 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=186 + y=211 + width=24 + height=12 + } + display[0] { + label="m38" + name="motorx_more.adl" + args="P=$(P),M=m38" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=186 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m38.DMOV" + } + } + rectangle { + object { + x=186 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=186 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="38" + align="horiz. centered" + } + } + } + "text update" { + object { + x=186 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m38.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=185 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=185 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=186 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m39.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=220 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m39_able.VAL" + } + } + rectangle { + object { + x=210 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m39.LLS" + } + } + rectangle { + object { + x=210 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m39.LVIO" + } + } + rectangle { + object { + x=210 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m39.HLS" + } + } + composite { + object { + x=186 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=186 + y=247 + width=24 + height=12 + } + display[0] { + label="m39" + name="motorx_more.adl" + args="P=$(P),M=m39" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=186 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m39.DMOV" + } + } + rectangle { + object { + x=186 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=186 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="39" + align="horiz. centered" + } + } + } + "text update" { + object { + x=186 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m39.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=185 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=186 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m40.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=220 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m40_able.VAL" + } +} +rectangle { + object { + x=210 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m40.LLS" + } +} +rectangle { + object { + x=210 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m40.LVIO" + } +} +rectangle { + object { + x=210 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m40.HLS" + } +} +composite { + object { + x=186 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=186 + y=283 + width=24 + height=12 + } + display[0] { + label="m40" + name="motorx_more.adl" + args="P=$(P),M=m40" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=186 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m40.DMOV" + } + } + rectangle { + object { + x=186 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=186 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="40" + align="horiz. centered" + } + } +} +"text update" { + object { + x=186 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m40.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=140 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=140 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=141 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m25.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=175 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m25_able.VAL" + } + } + rectangle { + object { + x=165 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m25.LLS" + } + } + rectangle { + object { + x=165 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m25.LVIO" + } + } + rectangle { + object { + x=165 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m25.HLS" + } + } + composite { + object { + x=141 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=141 + y=31 + width=24 + height=12 + } + display[0] { + label="m25" + name="motorx_more.adl" + args="P=$(P),M=m25" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=141 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m25.DMOV" + } + } + rectangle { + object { + x=141 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=141 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="25" + align="horiz. centered" + } + } + } + "text update" { + object { + x=141 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m25.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=140 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=140 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=141 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m26.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=175 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m26_able.VAL" + } + } + rectangle { + object { + x=165 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m26.LLS" + } + } + rectangle { + object { + x=165 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m26.LVIO" + } + } + rectangle { + object { + x=165 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m26.HLS" + } + } + composite { + object { + x=141 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=141 + y=67 + width=24 + height=12 + } + display[0] { + label="m26" + name="motorx_more.adl" + args="P=$(P),M=m26" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=141 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m26.DMOV" + } + } + rectangle { + object { + x=141 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=141 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="26" + align="horiz. centered" + } + } + } + "text update" { + object { + x=141 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m26.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=140 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=140 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=141 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m27.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=175 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m27_able.VAL" + } + } + rectangle { + object { + x=165 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m27.LLS" + } + } + rectangle { + object { + x=165 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m27.LVIO" + } + } + rectangle { + object { + x=165 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m27.HLS" + } + } + composite { + object { + x=141 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=141 + y=103 + width=24 + height=12 + } + display[0] { + label="m27" + name="motorx_more.adl" + args="P=$(P),M=m27" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=141 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m27.DMOV" + } + } + rectangle { + object { + x=141 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=141 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="27" + align="horiz. centered" + } + } + } + "text update" { + object { + x=141 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m27.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=140 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=140 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=141 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m28.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=175 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m28_able.VAL" + } + } + rectangle { + object { + x=165 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m28.LLS" + } + } + rectangle { + object { + x=165 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m28.LVIO" + } + } + rectangle { + object { + x=165 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m28.HLS" + } + } + composite { + object { + x=141 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=141 + y=139 + width=24 + height=12 + } + display[0] { + label="m28" + name="motorx_more.adl" + args="P=$(P),M=m28" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=141 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m28.DMOV" + } + } + rectangle { + object { + x=141 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=141 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="28" + align="horiz. centered" + } + } + } + "text update" { + object { + x=141 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m28.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=140 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=140 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=141 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m29.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=175 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m29_able.VAL" + } + } + rectangle { + object { + x=165 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m29.LLS" + } + } + rectangle { + object { + x=165 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m29.LVIO" + } + } + rectangle { + object { + x=165 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m29.HLS" + } + } + composite { + object { + x=141 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=141 + y=175 + width=24 + height=12 + } + display[0] { + label="m29" + name="motorx_more.adl" + args="P=$(P),M=m29" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=141 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m29.DMOV" + } + } + rectangle { + object { + x=141 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=141 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="29" + align="horiz. centered" + } + } + } + "text update" { + object { + x=141 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m29.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=140 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=140 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=141 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m30.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=175 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m30_able.VAL" + } + } + rectangle { + object { + x=165 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m30.LLS" + } + } + rectangle { + object { + x=165 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m30.LVIO" + } + } + rectangle { + object { + x=165 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m30.HLS" + } + } + composite { + object { + x=141 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=141 + y=211 + width=24 + height=12 + } + display[0] { + label="m30" + name="motorx_more.adl" + args="P=$(P),M=m30" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=141 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m30.DMOV" + } + } + rectangle { + object { + x=141 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=141 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="30" + align="horiz. centered" + } + } + } + "text update" { + object { + x=141 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m30.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=140 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=140 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=141 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m31.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=175 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m31_able.VAL" + } + } + rectangle { + object { + x=165 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m31.LLS" + } + } + rectangle { + object { + x=165 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m31.LVIO" + } + } + rectangle { + object { + x=165 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m31.HLS" + } + } + composite { + object { + x=141 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=141 + y=247 + width=24 + height=12 + } + display[0] { + label="m31" + name="motorx_more.adl" + args="P=$(P),M=m31" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=141 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m31.DMOV" + } + } + rectangle { + object { + x=141 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=141 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="31" + align="horiz. centered" + } + } + } + "text update" { + object { + x=141 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m31.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=140 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=141 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m32.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=175 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m32_able.VAL" + } +} +rectangle { + object { + x=165 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m32.LLS" + } +} +rectangle { + object { + x=165 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m32.LVIO" + } +} +rectangle { + object { + x=165 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m32.HLS" + } +} +composite { + object { + x=141 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=141 + y=283 + width=24 + height=12 + } + display[0] { + label="m32" + name="motorx_more.adl" + args="P=$(P),M=m32" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=141 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m32.DMOV" + } + } + rectangle { + object { + x=141 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=141 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="32" + align="horiz. centered" + } + } +} +"text update" { + object { + x=141 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m32.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=95 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=95 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=96 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m17.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=130 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m17_able.VAL" + } + } + rectangle { + object { + x=120 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m17.LLS" + } + } + rectangle { + object { + x=120 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m17.LVIO" + } + } + rectangle { + object { + x=120 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m17.HLS" + } + } + composite { + object { + x=96 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=96 + y=31 + width=24 + height=12 + } + display[0] { + label="m17" + name="motorx_more.adl" + args="P=$(P),M=m17" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=96 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m17.DMOV" + } + } + rectangle { + object { + x=96 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=96 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="17" + align="horiz. centered" + } + } + } + "text update" { + object { + x=96 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m17.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=95 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=95 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=96 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m18.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=130 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m18_able.VAL" + } + } + rectangle { + object { + x=120 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m18.LLS" + } + } + rectangle { + object { + x=120 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m18.LVIO" + } + } + rectangle { + object { + x=120 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m18.HLS" + } + } + composite { + object { + x=96 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=96 + y=67 + width=24 + height=12 + } + display[0] { + label="m18" + name="motorx_more.adl" + args="P=$(P),M=m18" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=96 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m18.DMOV" + } + } + rectangle { + object { + x=96 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=96 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="18" + align="horiz. centered" + } + } + } + "text update" { + object { + x=96 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m18.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=95 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=95 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=96 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m19.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=130 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m19_able.VAL" + } + } + rectangle { + object { + x=120 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m19.LLS" + } + } + rectangle { + object { + x=120 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m19.LVIO" + } + } + rectangle { + object { + x=120 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m19.HLS" + } + } + composite { + object { + x=96 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=96 + y=103 + width=24 + height=12 + } + display[0] { + label="m19" + name="motorx_more.adl" + args="P=$(P),M=m19" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=96 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m19.DMOV" + } + } + rectangle { + object { + x=96 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=96 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="19" + align="horiz. centered" + } + } + } + "text update" { + object { + x=96 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m19.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=95 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=95 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=96 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m20.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=130 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m20_able.VAL" + } + } + rectangle { + object { + x=120 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m20.LLS" + } + } + rectangle { + object { + x=120 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m20.LVIO" + } + } + rectangle { + object { + x=120 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m20.HLS" + } + } + composite { + object { + x=96 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=96 + y=139 + width=24 + height=12 + } + display[0] { + label="m20" + name="motorx_more.adl" + args="P=$(P),M=m20" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=96 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m20.DMOV" + } + } + rectangle { + object { + x=96 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=96 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="20" + align="horiz. centered" + } + } + } + "text update" { + object { + x=96 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m20.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=95 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=95 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=96 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m21.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=130 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m21_able.VAL" + } + } + rectangle { + object { + x=120 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m21.LLS" + } + } + rectangle { + object { + x=120 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m21.LVIO" + } + } + rectangle { + object { + x=120 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m21.HLS" + } + } + composite { + object { + x=96 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=96 + y=175 + width=24 + height=12 + } + display[0] { + label="m21" + name="motorx_more.adl" + args="P=$(P),M=m21" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=96 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m21.DMOV" + } + } + rectangle { + object { + x=96 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=96 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="21" + align="horiz. centered" + } + } + } + "text update" { + object { + x=96 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m21.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=95 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=95 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=96 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m22.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=130 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m22_able.VAL" + } + } + rectangle { + object { + x=120 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m22.LLS" + } + } + rectangle { + object { + x=120 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m22.LVIO" + } + } + rectangle { + object { + x=120 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m22.HLS" + } + } + composite { + object { + x=96 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=96 + y=211 + width=24 + height=12 + } + display[0] { + label="m22" + name="motorx_more.adl" + args="P=$(P),M=m22" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=96 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m22.DMOV" + } + } + rectangle { + object { + x=96 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=96 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="22" + align="horiz. centered" + } + } + } + "text update" { + object { + x=96 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m22.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=95 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=95 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=96 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m23.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=130 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m23_able.VAL" + } + } + rectangle { + object { + x=120 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m23.LLS" + } + } + rectangle { + object { + x=120 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m23.LVIO" + } + } + rectangle { + object { + x=120 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m23.HLS" + } + } + composite { + object { + x=96 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=96 + y=247 + width=24 + height=12 + } + display[0] { + label="m23" + name="motorx_more.adl" + args="P=$(P),M=m23" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=96 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m23.DMOV" + } + } + rectangle { + object { + x=96 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=96 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="23" + align="horiz. centered" + } + } + } + "text update" { + object { + x=96 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m23.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=95 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=96 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m24.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=130 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m24_able.VAL" + } +} +rectangle { + object { + x=120 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m24.LLS" + } +} +rectangle { + object { + x=120 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m24.LVIO" + } +} +rectangle { + object { + x=120 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m24.HLS" + } +} +composite { + object { + x=96 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=96 + y=283 + width=24 + height=12 + } + display[0] { + label="m24" + name="motorx_more.adl" + args="P=$(P),M=m24" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=96 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m24.DMOV" + } + } + rectangle { + object { + x=96 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=96 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="24" + align="horiz. centered" + } + } +} +"text update" { + object { + x=96 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m24.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=50 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=50 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=51 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m9.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=85 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m9_able.VAL" + } + } + rectangle { + object { + x=75 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m9.LLS" + } + } + rectangle { + object { + x=75 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m9.LVIO" + } + } + rectangle { + object { + x=75 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m9.HLS" + } + } + composite { + object { + x=51 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=51 + y=31 + width=24 + height=12 + } + display[0] { + label="m9" + name="motorx_more.adl" + args="P=$(P),M=m9" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=51 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m9.DMOV" + } + } + rectangle { + object { + x=51 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=51 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="9" + align="horiz. centered" + } + } + } + "text update" { + object { + x=51 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m9.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=50 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=50 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=51 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m10.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=85 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m10_able.VAL" + } + } + rectangle { + object { + x=75 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m10.LLS" + } + } + rectangle { + object { + x=75 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m10.LVIO" + } + } + rectangle { + object { + x=75 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m10.HLS" + } + } + composite { + object { + x=51 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=51 + y=67 + width=24 + height=12 + } + display[0] { + label="m10" + name="motorx_more.adl" + args="P=$(P),M=m10" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=51 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m10.DMOV" + } + } + rectangle { + object { + x=51 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=51 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="10" + align="horiz. centered" + } + } + } + "text update" { + object { + x=51 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m10.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=50 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=50 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=51 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m11.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=85 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m11_able.VAL" + } + } + rectangle { + object { + x=75 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m11.LLS" + } + } + rectangle { + object { + x=75 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m11.LVIO" + } + } + rectangle { + object { + x=75 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m11.HLS" + } + } + composite { + object { + x=51 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=51 + y=103 + width=24 + height=12 + } + display[0] { + label="m11" + name="motorx_more.adl" + args="P=$(P),M=m11" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=51 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m11.DMOV" + } + } + rectangle { + object { + x=51 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=51 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="11" + align="horiz. centered" + } + } + } + "text update" { + object { + x=51 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m11.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=50 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=50 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=51 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m12.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=85 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m12_able.VAL" + } + } + rectangle { + object { + x=75 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m12.LLS" + } + } + rectangle { + object { + x=75 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m12.LVIO" + } + } + rectangle { + object { + x=75 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m12.HLS" + } + } + composite { + object { + x=51 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=51 + y=139 + width=24 + height=12 + } + display[0] { + label="m12" + name="motorx_more.adl" + args="P=$(P),M=m12" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=51 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m12.DMOV" + } + } + rectangle { + object { + x=51 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=51 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="12" + align="horiz. centered" + } + } + } + "text update" { + object { + x=51 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m12.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=50 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=50 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=51 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m13.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=85 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m13_able.VAL" + } + } + rectangle { + object { + x=75 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m13.LLS" + } + } + rectangle { + object { + x=75 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m13.LVIO" + } + } + rectangle { + object { + x=75 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m13.HLS" + } + } + composite { + object { + x=51 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=51 + y=175 + width=24 + height=12 + } + display[0] { + label="m13" + name="motorx_more.adl" + args="P=$(P),M=m13" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=51 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m13.DMOV" + } + } + rectangle { + object { + x=51 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=51 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="13" + align="horiz. centered" + } + } + } + "text update" { + object { + x=51 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m13.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=50 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=50 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=51 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m14.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=85 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m14_able.VAL" + } + } + rectangle { + object { + x=75 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m14.LLS" + } + } + rectangle { + object { + x=75 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m14.LVIO" + } + } + rectangle { + object { + x=75 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m14.HLS" + } + } + composite { + object { + x=51 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=51 + y=211 + width=24 + height=12 + } + display[0] { + label="m14" + name="motorx_more.adl" + args="P=$(P),M=m14" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=51 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m14.DMOV" + } + } + rectangle { + object { + x=51 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=51 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="14" + align="horiz. centered" + } + } + } + "text update" { + object { + x=51 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m14.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=50 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=50 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=51 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m15.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=85 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m15_able.VAL" + } + } + rectangle { + object { + x=75 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m15.LLS" + } + } + rectangle { + object { + x=75 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m15.LVIO" + } + } + rectangle { + object { + x=75 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m15.HLS" + } + } + composite { + object { + x=51 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=51 + y=247 + width=24 + height=12 + } + display[0] { + label="m15" + name="motorx_more.adl" + args="P=$(P),M=m15" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=51 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m15.DMOV" + } + } + rectangle { + object { + x=51 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=51 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="15" + align="horiz. centered" + } + } + } + "text update" { + object { + x=51 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m15.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=50 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=51 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m16.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=85 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m16_able.VAL" + } +} +rectangle { + object { + x=75 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m16.LLS" + } +} +rectangle { + object { + x=75 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m16.LVIO" + } +} +rectangle { + object { + x=75 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m16.HLS" + } +} +composite { + object { + x=51 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=51 + y=283 + width=24 + height=12 + } + display[0] { + label="m16" + name="motorx_more.adl" + args="P=$(P),M=m16" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=51 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m16.DMOV" + } + } + rectangle { + object { + x=51 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=51 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="16" + align="horiz. centered" + } + } +} +"text update" { + object { + x=51 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m16.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=5 + y=20 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=5 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=6 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m1.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=40 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m1_able.VAL" + } + } + rectangle { + object { + x=30 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m1.LLS" + } + } + rectangle { + object { + x=30 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m1.LVIO" + } + } + rectangle { + object { + x=30 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m1.HLS" + } + } + composite { + object { + x=6 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=6 + y=31 + width=24 + height=12 + } + display[0] { + label="m1" + name="motorx_more.adl" + args="P=$(P),M=m1" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=6 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m1.DMOV" + } + } + rectangle { + object { + x=6 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=6 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="1" + align="horiz. centered" + } + } + } + "text update" { + object { + x=6 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m1.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=5 + y=56 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=5 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=6 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m2.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=40 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m2_able.VAL" + } + } + rectangle { + object { + x=30 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m2.LLS" + } + } + rectangle { + object { + x=30 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m2.LVIO" + } + } + rectangle { + object { + x=30 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m2.HLS" + } + } + composite { + object { + x=6 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=6 + y=67 + width=24 + height=12 + } + display[0] { + label="m2" + name="motorx_more.adl" + args="P=$(P),M=m2" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=6 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m2.DMOV" + } + } + rectangle { + object { + x=6 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=6 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="2" + align="horiz. centered" + } + } + } + "text update" { + object { + x=6 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m2.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=5 + y=92 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=5 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=6 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m3.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=40 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m3_able.VAL" + } + } + rectangle { + object { + x=30 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m3.LLS" + } + } + rectangle { + object { + x=30 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m3.LVIO" + } + } + rectangle { + object { + x=30 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m3.HLS" + } + } + composite { + object { + x=6 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=6 + y=103 + width=24 + height=12 + } + display[0] { + label="m3" + name="motorx_more.adl" + args="P=$(P),M=m3" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=6 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m3.DMOV" + } + } + rectangle { + object { + x=6 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=6 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="3" + align="horiz. centered" + } + } + } + "text update" { + object { + x=6 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m3.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=5 + y=128 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=5 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=6 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m4.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=40 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m4_able.VAL" + } + } + rectangle { + object { + x=30 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m4.LLS" + } + } + rectangle { + object { + x=30 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m4.LVIO" + } + } + rectangle { + object { + x=30 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m4.HLS" + } + } + composite { + object { + x=6 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=6 + y=139 + width=24 + height=12 + } + display[0] { + label="m4" + name="motorx_more.adl" + args="P=$(P),M=m4" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=6 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m4.DMOV" + } + } + rectangle { + object { + x=6 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=6 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="4" + align="horiz. centered" + } + } + } + "text update" { + object { + x=6 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m4.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=5 + y=164 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=5 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=6 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m5.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=40 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m5_able.VAL" + } + } + rectangle { + object { + x=30 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m5.LLS" + } + } + rectangle { + object { + x=30 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m5.LVIO" + } + } + rectangle { + object { + x=30 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m5.HLS" + } + } + composite { + object { + x=6 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=6 + y=175 + width=24 + height=12 + } + display[0] { + label="m5" + name="motorx_more.adl" + args="P=$(P),M=m5" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=6 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m5.DMOV" + } + } + rectangle { + object { + x=6 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=6 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="5" + align="horiz. centered" + } + } + } + "text update" { + object { + x=6 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m5.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=5 + y=200 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=5 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=6 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m6.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=40 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m6_able.VAL" + } + } + rectangle { + object { + x=30 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m6.LLS" + } + } + rectangle { + object { + x=30 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m6.LVIO" + } + } + rectangle { + object { + x=30 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m6.HLS" + } + } + composite { + object { + x=6 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=6 + y=211 + width=24 + height=12 + } + display[0] { + label="m6" + name="motorx_more.adl" + args="P=$(P),M=m6" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=6 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m6.DMOV" + } + } + rectangle { + object { + x=6 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=6 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="6" + align="horiz. centered" + } + } + } + "text update" { + object { + x=6 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m6.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=5 + y=236 + width=40 + height=33 + } + "composite name"="" + children { + rectangle { + object { + x=5 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=6 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m7.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=40 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m7_able.VAL" + } + } + rectangle { + object { + x=30 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m7.LLS" + } + } + rectangle { + object { + x=30 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m7.LVIO" + } + } + rectangle { + object { + x=30 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m7.HLS" + } + } + composite { + object { + x=6 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=6 + y=247 + width=24 + height=12 + } + display[0] { + label="m7" + name="motorx_more.adl" + args="P=$(P),M=m7" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=6 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m7.DMOV" + } + } + rectangle { + object { + x=6 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=6 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="7" + align="horiz. centered" + } + } + } + "text update" { + object { + x=6 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m7.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +rectangle { + object { + x=5 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } +} +"text update" { + object { + x=6 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m8.DESC" + clr=14 + bclr=0 + } + limits { + } +} +rectangle { + object { + x=40 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m8_able.VAL" + } +} +rectangle { + object { + x=30 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m8.LLS" + } +} +rectangle { + object { + x=30 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m8.LVIO" + } +} +rectangle { + object { + x=30 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m8.HLS" + } +} +composite { + object { + x=6 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=6 + y=283 + width=24 + height=12 + } + display[0] { + label="m8" + name="motorx_more.adl" + args="P=$(P),M=m8" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=6 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m8.DMOV" + } + } + rectangle { + object { + x=6 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=6 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="8" + align="horiz. centered" + } + } +} +"text update" { + object { + x=6 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m8.RBV" + clr=14 + bclr=0 + } + limits { + } +} +composite { + object { + x=410 + y=20 + width=40 + height=285 + } + "composite name"="" + children { + rectangle { + object { + x=410 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=411 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m75.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=445 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m75_able.VAL" + } + } + rectangle { + object { + x=435 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m75.LLS" + } + } + rectangle { + object { + x=435 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m75.LVIO" + } + } + rectangle { + object { + x=435 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m75.HLS" + } + } + composite { + object { + x=411 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=411 + y=103 + width=24 + height=12 + } + display[0] { + label="m3" + name="motorx_more.adl" + args="P=$(P),M=m75" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=411 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m75.DMOV" + } + } + rectangle { + object { + x=411 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=411 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="75" + align="horiz. centered" + } + } + } + rectangle { + object { + x=410 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=411 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m76.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=445 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m76_able.VAL" + } + } + rectangle { + object { + x=435 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m76.LLS" + } + } + rectangle { + object { + x=435 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m76.LVIO" + } + } + rectangle { + object { + x=435 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m76.HLS" + } + } + composite { + object { + x=411 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=411 + y=139 + width=24 + height=12 + } + display[0] { + label="m4" + name="motorx_more.adl" + args="P=$(P),M=m76" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=411 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m76.DMOV" + } + } + rectangle { + object { + x=411 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=411 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="76" + align="horiz. centered" + } + } + } + rectangle { + object { + x=410 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=411 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m77.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=445 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m77_able.VAL" + } + } + rectangle { + object { + x=435 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m77.LLS" + } + } + rectangle { + object { + x=435 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m77.LVIO" + } + } + rectangle { + object { + x=435 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m77.HLS" + } + } + composite { + object { + x=411 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=411 + y=175 + width=24 + height=12 + } + display[0] { + label="m5" + name="motorx_more.adl" + args="P=$(P),M=m77" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=411 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m77.DMOV" + } + } + rectangle { + object { + x=411 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=411 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="77" + align="horiz. centered" + } + } + } + rectangle { + object { + x=410 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=411 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m78.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=445 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m78_able.VAL" + } + } + rectangle { + object { + x=435 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m78.LLS" + } + } + rectangle { + object { + x=435 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m78.LVIO" + } + } + rectangle { + object { + x=435 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m78.HLS" + } + } + composite { + object { + x=411 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=411 + y=211 + width=24 + height=12 + } + display[0] { + label="m6" + name="motorx_more.adl" + args="P=$(P),M=m78" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=411 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m78.DMOV" + } + } + rectangle { + object { + x=411 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=411 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="78" + align="horiz. centered" + } + } + } + rectangle { + object { + x=410 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=411 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m79.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=445 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m79_able.VAL" + } + } + rectangle { + object { + x=435 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m79.LLS" + } + } + rectangle { + object { + x=435 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m79.LVIO" + } + } + rectangle { + object { + x=435 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m79.HLS" + } + } + composite { + object { + x=411 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=411 + y=247 + width=24 + height=12 + } + display[0] { + label="m7" + name="motorx_more.adl" + args="P=$(P),M=m79" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=411 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m79.DMOV" + } + } + rectangle { + object { + x=411 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=411 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="79" + align="horiz. centered" + } + } + } + rectangle { + object { + x=410 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=411 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m80.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=445 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m80_able.VAL" + } + } + rectangle { + object { + x=435 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m80.LLS" + } + } + rectangle { + object { + x=435 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m80.LVIO" + } + } + rectangle { + object { + x=435 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m80.HLS" + } + } + composite { + object { + x=411 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=411 + y=283 + width=24 + height=12 + } + display[0] { + label="m8" + name="motorx_more.adl" + args="P=$(P),M=m80" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=411 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m80.DMOV" + } + } + rectangle { + object { + x=411 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=411 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="80" + align="horiz. centered" + } + } + } + rectangle { + object { + x=410 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=411 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m73.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=445 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m73_able.VAL" + } + } + rectangle { + object { + x=435 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m73.LLS" + } + } + rectangle { + object { + x=435 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m73.LVIO" + } + } + rectangle { + object { + x=435 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m73.HLS" + } + } + composite { + object { + x=411 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=411 + y=31 + width=24 + height=12 + } + display[0] { + label="m1" + name="motorx_more.adl" + args="P=$(P),M=m73" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=411 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m73.DMOV" + } + } + rectangle { + object { + x=411 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=411 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="73" + align="horiz. centered" + } + } + } + rectangle { + object { + x=410 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=411 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m74.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=445 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m74_able.VAL" + } + } + rectangle { + object { + x=435 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m74.LLS" + } + } + rectangle { + object { + x=435 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m74.LVIO" + } + } + rectangle { + object { + x=435 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m74.HLS" + } + } + composite { + object { + x=411 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=411 + y=67 + width=24 + height=12 + } + display[0] { + label="m2" + name="motorx_more.adl" + args="P=$(P),M=m74" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=411 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m74.DMOV" + } + } + rectangle { + object { + x=411 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=411 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="74" + align="horiz. centered" + } + } + } + "text update" { + object { + x=411 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m73.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=411 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m74.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=411 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m75.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=411 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m76.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=411 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m77.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=411 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m78.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=411 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m79.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=411 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m80.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=455 + y=20 + width=40 + height=285 + } + "composite name"="" + children { + rectangle { + object { + x=455 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=456 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m83.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=490 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m83_able.VAL" + } + } + rectangle { + object { + x=480 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m83.LLS" + } + } + rectangle { + object { + x=480 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m83.LVIO" + } + } + rectangle { + object { + x=480 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m83.HLS" + } + } + composite { + object { + x=456 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=456 + y=103 + width=24 + height=12 + } + display[0] { + label="m3" + name="motorx_more.adl" + args="P=$(P),M=m83" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=456 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m83.DMOV" + } + } + rectangle { + object { + x=456 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=456 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="83" + align="horiz. centered" + } + } + } + rectangle { + object { + x=455 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=456 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m84.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=490 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m84_able.VAL" + } + } + rectangle { + object { + x=480 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m84.LLS" + } + } + rectangle { + object { + x=480 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m84.LVIO" + } + } + rectangle { + object { + x=480 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m84.HLS" + } + } + composite { + object { + x=456 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=456 + y=139 + width=24 + height=12 + } + display[0] { + label="m4" + name="motorx_more.adl" + args="P=$(P),M=m84" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=456 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m84.DMOV" + } + } + rectangle { + object { + x=456 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=456 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="84" + align="horiz. centered" + } + } + } + rectangle { + object { + x=455 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=456 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m85.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=490 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m85_able.VAL" + } + } + rectangle { + object { + x=480 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m85.LLS" + } + } + rectangle { + object { + x=480 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m85.LVIO" + } + } + rectangle { + object { + x=480 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m85.HLS" + } + } + composite { + object { + x=456 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=456 + y=175 + width=24 + height=12 + } + display[0] { + label="m5" + name="motorx_more.adl" + args="P=$(P),M=m85" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=456 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m85.DMOV" + } + } + rectangle { + object { + x=456 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=456 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="85" + align="horiz. centered" + } + } + } + rectangle { + object { + x=455 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=456 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m86.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=490 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m86_able.VAL" + } + } + rectangle { + object { + x=480 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m86.LLS" + } + } + rectangle { + object { + x=480 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m86.LVIO" + } + } + rectangle { + object { + x=480 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m86.HLS" + } + } + composite { + object { + x=456 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=456 + y=211 + width=24 + height=12 + } + display[0] { + label="m6" + name="motorx_more.adl" + args="P=$(P),M=m86" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=456 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m86.DMOV" + } + } + rectangle { + object { + x=456 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=456 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="86" + align="horiz. centered" + } + } + } + rectangle { + object { + x=455 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=456 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m87.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=490 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m87_able.VAL" + } + } + rectangle { + object { + x=480 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m87.LLS" + } + } + rectangle { + object { + x=480 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m87.LVIO" + } + } + rectangle { + object { + x=480 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m87.HLS" + } + } + composite { + object { + x=456 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=456 + y=247 + width=24 + height=12 + } + display[0] { + label="m7" + name="motorx_more.adl" + args="P=$(P),M=m87" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=456 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m87.DMOV" + } + } + rectangle { + object { + x=456 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=456 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="87" + align="horiz. centered" + } + } + } + rectangle { + object { + x=455 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=456 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m88.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=490 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m88_able.VAL" + } + } + rectangle { + object { + x=480 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m88.LLS" + } + } + rectangle { + object { + x=480 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m88.LVIO" + } + } + rectangle { + object { + x=480 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m88.HLS" + } + } + composite { + object { + x=456 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=456 + y=283 + width=24 + height=12 + } + display[0] { + label="m8" + name="motorx_more.adl" + args="P=$(P),M=m88" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=456 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m88.DMOV" + } + } + rectangle { + object { + x=456 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=456 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="88" + align="horiz. centered" + } + } + } + rectangle { + object { + x=455 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=456 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m81.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=490 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m81_able.VAL" + } + } + rectangle { + object { + x=480 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m81.LLS" + } + } + rectangle { + object { + x=480 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m81.LVIO" + } + } + rectangle { + object { + x=480 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m81.HLS" + } + } + composite { + object { + x=456 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=456 + y=31 + width=24 + height=12 + } + display[0] { + label="m1" + name="motorx_more.adl" + args="P=$(P),M=m81" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=456 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m81.DMOV" + } + } + rectangle { + object { + x=456 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=456 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="81" + align="horiz. centered" + } + } + } + rectangle { + object { + x=455 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=456 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m82.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=490 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m82_able.VAL" + } + } + rectangle { + object { + x=480 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m82.LLS" + } + } + rectangle { + object { + x=480 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m82.LVIO" + } + } + rectangle { + object { + x=480 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m82.HLS" + } + } + composite { + object { + x=456 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=456 + y=67 + width=24 + height=12 + } + display[0] { + label="m2" + name="motorx_more.adl" + args="P=$(P),M=m82" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=456 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m82.DMOV" + } + } + rectangle { + object { + x=456 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=456 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="82" + align="horiz. centered" + } + } + } + "text update" { + object { + x=456 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m81.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=456 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m82.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=456 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m83.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=456 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m84.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=456 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m85.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=456 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m86.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=456 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m87.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=456 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m88.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} +composite { + object { + x=495 + y=20 + width=40 + height=285 + } + "composite name"="" + children { + rectangle { + object { + x=495 + y=92 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=496 + y=93 + width=38 + height=10 + } + monitor { + chan="$(P)m91.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=530 + y=103 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m91_able.VAL" + } + } + rectangle { + object { + x=520 + y=111 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m91.LLS" + } + } + rectangle { + object { + x=520 + y=107 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m91.LVIO" + } + } + rectangle { + object { + x=520 + y=103 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m91.HLS" + } + } + composite { + object { + x=496 + y=102 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=496 + y=103 + width=24 + height=12 + } + display[0] { + label="m3" + name="motorx_more.adl" + args="P=$(P),M=m91" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=496 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m91.DMOV" + } + } + rectangle { + object { + x=496 + y=103 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=496 + y=102 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="91" + align="horiz. centered" + } + } + } + rectangle { + object { + x=495 + y=128 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=496 + y=129 + width=38 + height=10 + } + monitor { + chan="$(P)m92.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=530 + y=139 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m92_able.VAL" + } + } + rectangle { + object { + x=520 + y=147 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m92.LLS" + } + } + rectangle { + object { + x=520 + y=143 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m92.LVIO" + } + } + rectangle { + object { + x=520 + y=139 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m92.HLS" + } + } + composite { + object { + x=496 + y=138 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=496 + y=139 + width=24 + height=12 + } + display[0] { + label="m4" + name="motorx_more.adl" + args="P=$(P),M=m92" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=496 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m92.DMOV" + } + } + rectangle { + object { + x=496 + y=139 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=496 + y=138 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="92" + align="horiz. centered" + } + } + } + rectangle { + object { + x=495 + y=164 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=496 + y=165 + width=38 + height=10 + } + monitor { + chan="$(P)m93.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=530 + y=175 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m93_able.VAL" + } + } + rectangle { + object { + x=520 + y=183 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m93.LLS" + } + } + rectangle { + object { + x=520 + y=179 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m93.LVIO" + } + } + rectangle { + object { + x=520 + y=175 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m93.HLS" + } + } + composite { + object { + x=496 + y=174 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=496 + y=175 + width=24 + height=12 + } + display[0] { + label="m5" + name="motorx_more.adl" + args="P=$(P),M=m93" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=496 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m93.DMOV" + } + } + rectangle { + object { + x=496 + y=175 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=496 + y=174 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="93" + align="horiz. centered" + } + } + } + rectangle { + object { + x=495 + y=200 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=496 + y=201 + width=38 + height=10 + } + monitor { + chan="$(P)m94.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=530 + y=211 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m94_able.VAL" + } + } + rectangle { + object { + x=520 + y=219 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m94.LLS" + } + } + rectangle { + object { + x=520 + y=215 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m94.LVIO" + } + } + rectangle { + object { + x=520 + y=211 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m94.HLS" + } + } + composite { + object { + x=496 + y=210 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=496 + y=211 + width=24 + height=12 + } + display[0] { + label="m6" + name="motorx_more.adl" + args="P=$(P),M=m94" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=496 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m94.DMOV" + } + } + rectangle { + object { + x=496 + y=211 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=496 + y=210 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="94" + align="horiz. centered" + } + } + } + rectangle { + object { + x=495 + y=236 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=496 + y=237 + width=38 + height=10 + } + monitor { + chan="$(P)m95.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=530 + y=247 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m95_able.VAL" + } + } + rectangle { + object { + x=520 + y=255 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m95.LLS" + } + } + rectangle { + object { + x=520 + y=251 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m95.LVIO" + } + } + rectangle { + object { + x=520 + y=247 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m95.HLS" + } + } + composite { + object { + x=496 + y=246 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=496 + y=247 + width=24 + height=12 + } + display[0] { + label="m7" + name="motorx_more.adl" + args="P=$(P),M=m95" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=496 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m95.DMOV" + } + } + rectangle { + object { + x=496 + y=247 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=496 + y=246 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="95" + align="horiz. centered" + } + } + } + rectangle { + object { + x=495 + y=272 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=496 + y=273 + width=38 + height=10 + } + monitor { + chan="$(P)m96.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=530 + y=283 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m96_able.VAL" + } + } + rectangle { + object { + x=520 + y=291 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m96.LLS" + } + } + rectangle { + object { + x=520 + y=287 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m96.LVIO" + } + } + rectangle { + object { + x=520 + y=283 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m96.HLS" + } + } + composite { + object { + x=496 + y=282 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=496 + y=283 + width=24 + height=12 + } + display[0] { + label="m8" + name="motorx_more.adl" + args="P=$(P),M=m96" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=496 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m96.DMOV" + } + } + rectangle { + object { + x=496 + y=283 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=496 + y=282 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="96" + align="horiz. centered" + } + } + } + rectangle { + object { + x=495 + y=20 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=496 + y=21 + width=38 + height=10 + } + monitor { + chan="$(P)m89.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=530 + y=31 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m89_able.VAL" + } + } + rectangle { + object { + x=520 + y=39 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m89.LLS" + } + } + rectangle { + object { + x=520 + y=35 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m89.LVIO" + } + } + rectangle { + object { + x=520 + y=31 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m89.HLS" + } + } + composite { + object { + x=496 + y=30 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=496 + y=31 + width=24 + height=12 + } + display[0] { + label="m1" + name="motorx_more.adl" + args="P=$(P),M=m89" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=496 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m89.DMOV" + } + } + rectangle { + object { + x=496 + y=31 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=496 + y=30 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="89" + align="horiz. centered" + } + } + } + rectangle { + object { + x=495 + y=56 + width=40 + height=33 + } + "basic attribute" { + clr=14 + fill="outline" + } + } + "text update" { + object { + x=496 + y=57 + width=38 + height=10 + } + monitor { + chan="$(P)m90.DESC" + clr=14 + bclr=0 + } + limits { + } + } + rectangle { + object { + x=530 + y=67 + width=5 + height=12 + } + "basic attribute" { + clr=14 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m90_able.VAL" + } + } + rectangle { + object { + x=520 + y=75 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m90.LLS" + } + } + rectangle { + object { + x=520 + y=71 + width=10 + height=4 + } + "basic attribute" { + clr=30 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m90.LVIO" + } + } + rectangle { + object { + x=520 + y=67 + width=10 + height=4 + } + "basic attribute" { + clr=20 + } + "dynamic attribute" { + vis="if not zero" + chan="$(P)m90.HLS" + } + } + composite { + object { + x=496 + y=66 + width=24 + height=14 + } + "composite name"="" + children { + "related display" { + object { + x=496 + y=67 + width=24 + height=12 + } + display[0] { + label="m2" + name="motorx_more.adl" + args="P=$(P),M=m90" + } + clr=14 + bclr=51 + visual="invisible" + } + rectangle { + object { + x=496 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=60 + fill="outline" + width=2 + } + "dynamic attribute" { + vis="if zero" + chan="$(P)m90.DMOV" + } + } + rectangle { + object { + x=496 + y=67 + width=24 + height=12 + } + "basic attribute" { + clr=5 + } + } + text { + object { + x=496 + y=66 + width=24 + height=14 + } + "basic attribute" { + clr=14 + } + textix="90" + align="horiz. centered" + } + } + } + "text update" { + object { + x=496 + y=43 + width=38 + height=10 + } + monitor { + chan="$(P)m89.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=496 + y=79 + width=38 + height=10 + } + monitor { + chan="$(P)m90.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=496 + y=115 + width=38 + height=10 + } + monitor { + chan="$(P)m91.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=496 + y=151 + width=38 + height=10 + } + monitor { + chan="$(P)m92.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=496 + y=187 + width=38 + height=10 + } + monitor { + chan="$(P)m93.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=496 + y=223 + width=38 + height=10 + } + monitor { + chan="$(P)m94.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=496 + y=259 + width=38 + height=10 + } + monitor { + chan="$(P)m95.RBV" + clr=14 + bclr=0 + } + limits { + } + } + "text update" { + object { + x=496 + y=295 + width=38 + height=10 + } + monitor { + chan="$(P)m96.RBV" + clr=14 + bclr=0 + } + limits { + } + } + } +} diff --git a/motorApp/op/adl/motorx_msta_detail.adl b/motorApp/op/adl/motorx_msta_detail.adl index ea380cf..af8383f 100644 --- a/motorApp/op/adl/motorx_msta_detail.adl +++ b/motorApp/op/adl/motorx_msta_detail.adl @@ -1,7 +1,7 @@ file { - name="motorx_msta_detail.adl" - version=030102 + name="/home/oxygen/MOONEY/epics/synApps/support/motor/motorApp/op/adl/motorx_msta_detail.adl" + version=030107 } display { object { @@ -15,7 +15,7 @@ display { cmap="" gridSpacing=5 gridOn=0 - snapToGrid=0 + snapToGrid=1 } "color map" { ncolors=65 @@ -182,7 +182,7 @@ text { byte { object { x=5 - y=65 + y=62 width=37 height=320 } @@ -192,207 +192,198 @@ byte { bclr=3 } direction="down" + sbit=0 + ebit=15 +} +text { + object { + x=50 + y=365 + width=171 + height=15 + } + "basic attribute" { + clr=14 + } + textix="Unused" +} +text { + object { + x=50 + y=345 + width=171 + height=15 + } + "basic attribute" { + clr=14 + } + textix="Unused" +} +text { + object { + x=50 + y=325 + width=350 + height=15 + } + "basic attribute" { + clr=14 + } + textix="MINUS_LS: minus limit switch has been hit" +} +text { + object { + x=50 + y=305 + width=350 + height=15 + } + "basic attribute" { + clr=14 + } + textix="COMM_ERR: Communication Error" +} +text { + object { + x=50 + y=285 + width=345 + height=15 + } + "basic attribute" { + clr=14 + } + textix="GAIN_SUPPORT: motor supports closed-loop position control" +} +text { + object { + x=50 + y=265 + width=350 + height=15 + } + "basic attribute" { + clr=14 + } + textix="MOVING: non-zero velocity present" +} +text { + object { + x=50 + y=245 + width=350 + height=15 + } + "basic attribute" { + clr=14 + } + textix="PROBLEM: driver stopped polling" +} +text { + object { + x=50 + y=225 + width=350 + height=15 + } + "basic attribute" { + clr=14 + } + textix="PRESENT: encoder is present" +} +text { + object { + x=50 + y=205 + width=350 + height=15 + } + "basic attribute" { + clr=14 + } + textix="HOME: if at home position" } -composite { +text { object { x=50 - y=68 + y=185 width=350 - height=315 - } - "composite name"="" - children { - text { - object { - x=50 - y=68 - width=171 - height=15 - } - "basic attribute" { - clr=14 - } - textix="Unused" - } - text { - object { - x=50 - y=88 - width=171 - height=15 - } - "basic attribute" { - clr=14 - } - textix="Unused" - } - text { - object { - x=50 - y=108 - width=350 - height=15 - } - "basic attribute" { - clr=14 - } - textix="MINUS_LS: minus limit switch has been hit" - } - text { - object { - x=50 - y=128 - width=350 - height=15 - } - "basic attribute" { - clr=14 - } - textix="COMM_ERR: Communication Error" - } - text { - object { - x=50 - y=148 - width=345 - height=15 - } - "basic attribute" { - clr=14 - } - textix="GAIN_SUPPORT: motor supports closed-loop position control" - } - text { - object { - x=50 - y=168 - width=350 - height=15 - } - "basic attribute" { - clr=14 - } - textix="MOVING: non-zero velocity present" - } - text { - object { - x=50 - y=188 - width=350 - height=15 - } - "basic attribute" { - clr=14 - } - textix="PROBLEM: driver stopped polling" - } - text { - object { - x=50 - y=208 - width=350 - height=15 - } - "basic attribute" { - clr=14 - } - textix="PRESENT: encoder is present" - } - text { - object { - x=50 - y=228 - width=350 - height=15 - } - "basic attribute" { - clr=14 - } - textix="HOME: if at home position" - } - text { - object { - x=50 - y=248 - width=350 - height=15 - } - "basic attribute" { - clr=14 - } - textix="Unused" - } - text { - object { - x=50 - y=268 - width=350 - height=15 - } - "basic attribute" { - clr=14 - } - textix="POSITION: closed-loop position control enabled" - } - text { - object { - x=50 - y=288 - width=350 - height=15 - } - "basic attribute" { - clr=14 - } - textix="Unused" - } - text { - object { - x=50 - y=308 - width=350 - height=15 - } - "basic attribute" { - clr=14 - } - textix="HOMELS: state of home limit switch" - } - text { - object { - x=50 - y=328 - width=350 - height=15 - } - "basic attribute" { - clr=14 - } - textix="PLUS_LS: plus limit has been hit" - } - text { - object { - x=50 - y=348 - width=350 - height=15 - } - "basic attribute" { - clr=14 - } - textix="DONE: motion is complete" - } - text { - object { - x=50 - y=368 - width=350 - height=15 - } - "basic attribute" { - clr=14 - } - textix="DIRECTION: last raw (0:Neg, 1:Pos)" - } + height=15 + } + "basic attribute" { + clr=14 + } + textix="Unused" +} +text { + object { + x=50 + y=165 + width=350 + height=15 + } + "basic attribute" { + clr=14 + } + textix="POSITION: closed-loop position control enabled" +} +text { + object { + x=50 + y=145 + width=350 + height=15 + } + "basic attribute" { + clr=14 + } + textix="Unused" +} +text { + object { + x=50 + y=125 + width=350 + height=15 + } + "basic attribute" { + clr=14 + } + textix="HOMELS: state of home limit switch" +} +text { + object { + x=50 + y=105 + width=350 + height=15 + } + "basic attribute" { + clr=14 + } + textix="PLUS_LS: plus limit has been hit" +} +text { + object { + x=50 + y=85 + width=350 + height=15 + } + "basic attribute" { + clr=14 + } + textix="DONE: motion is complete" +} +text { + object { + x=50 + y=65 + width=350 + height=15 + } + "basic attribute" { + clr=14 } + textix="DIRECTION: last raw (0:Neg, 1:Pos)" } diff --git a/motorApp/op/opi/4motor_form.opi b/motorApp/op/opi/4motor_form.opi index 58a617f..0e2c5fa 100644 --- a/motorApp/op/opi/4motor_form.opi +++ b/motorApp/op/opi/4motor_form.opi @@ -583,230 +583,6 @@ $(pv_value) 950 - - false - true - 1 - false - false - - 16 - false - true - - - - Text Input - true - - - - - 50 - 3 - - 1 - Infinity - -Infinity - false - 39872d87:13e14015f61:-38de - 0.0 - Text Input - - true - true - false - - 1 - false - 0 - $(P)$(M5).BACC - - - - false - 0 - - - false - - - - 0 - - 113 - $(pv_name) -$(pv_value) - 1000 - - - false - true - 1 - false - false - - 16 - false - true - - - - Text Input - true - - - - - 50 - 3 - - 1 - Infinity - -Infinity - false - 39872d87:13e14015f61:-38dd - 0.0 - Text Input - - true - true - false - - 1 - false - 0 - $(P)$(M6).BACC - - - - false - 0 - - - false - - - - 0 - - 128 - $(pv_name) -$(pv_value) - 1000 - - - false - true - 1 - false - false - - 16 - false - true - - - - Text Input - true - - - - - 50 - 3 - - 1 - Infinity - -Infinity - false - 39872d87:13e14015f61:-38dc - 0.0 - Text Input - - true - true - false - - 1 - false - 0 - $(P)$(M7).BACC - - - - false - 0 - - - false - - - - 0 - - 143 - $(pv_name) -$(pv_value) - 1000 - - - false - true - 1 - false - false - - 16 - false - true - - - - Text Input - true - - - - - 50 - 3 - - 1 - Infinity - -Infinity - false - 39872d87:13e14015f61:-38db - 0.0 - Text Input - - true - true - false - - 1 - false - 0 - $(P)$(M8).BACC - - - - false - 0 - - - false - - - - 0 - - 158 - $(pv_name) -$(pv_value) - 1000 - false true @@ -5920,4 +5696,4 @@ $(pv_value) $(pv_value) 0 - \ No newline at end of file + diff --git a/motorApp/op/ui/16motor_form.ui b/motorApp/op/ui/autoconvert/16motor_form.ui similarity index 100% rename from motorApp/op/ui/16motor_form.ui rename to motorApp/op/ui/autoconvert/16motor_form.ui diff --git a/motorApp/op/ui/4motor_form.ui b/motorApp/op/ui/autoconvert/4motor_form.ui similarity index 96% rename from motorApp/op/ui/4motor_form.ui rename to motorApp/op/ui/autoconvert/4motor_form.ui index e61fe50..b41b2b9 100644 --- a/motorApp/op/ui/4motor_form.ui +++ b/motorApp/op/ui/autoconvert/4motor_form.ui @@ -451,150 +451,6 @@ QPushButton::menu-indicator {image: url(none.png); width: 0} - - - - 1000 - 113 - 50 - 16 - - - - caLineEdit::WidthAndHeight - - - $(P)$(M5).BACC - - - - 0 - 0 - 0 - - - - - 218 - 218 - 218 - - - - caLineEdit::Static - - - decimal - - - - - - 1000 - 128 - 50 - 16 - - - - caLineEdit::WidthAndHeight - - - $(P)$(M6).BACC - - - - 0 - 0 - 0 - - - - - 218 - 218 - 218 - - - - caLineEdit::Static - - - decimal - - - - - - 1000 - 143 - 50 - 16 - - - - caLineEdit::WidthAndHeight - - - $(P)$(M7).BACC - - - - 0 - 0 - 0 - - - - - 218 - 218 - 218 - - - - caLineEdit::Static - - - decimal - - - - - - 1000 - 158 - 50 - 16 - - - - caLineEdit::WidthAndHeight - - - $(P)$(M8).BACC - - - - 0 - 0 - 0 - - - - - 218 - 218 - 218 - - - - caLineEdit::Static - - - decimal - - @@ -4401,4 +4257,4 @@ QPushButton::menu-indicator {image: url(none.png); width: 0} caTextEntry_63 - \ No newline at end of file + diff --git a/motorApp/op/ui/8motor_form.ui b/motorApp/op/ui/autoconvert/8motor_form.ui similarity index 100% rename from motorApp/op/ui/8motor_form.ui rename to motorApp/op/ui/autoconvert/8motor_form.ui diff --git a/motorApp/op/ui/ACRAux.ui b/motorApp/op/ui/autoconvert/ACRAux.ui similarity index 100% rename from motorApp/op/ui/ACRAux.ui rename to motorApp/op/ui/autoconvert/ACRAux.ui diff --git a/motorApp/op/ui/ACRTop.ui b/motorApp/op/ui/autoconvert/ACRTop.ui similarity index 100% rename from motorApp/op/ui/ACRTop.ui rename to motorApp/op/ui/autoconvert/ACRTop.ui diff --git a/motorApp/op/ui/EnsemblePSOFly.ui b/motorApp/op/ui/autoconvert/EnsemblePSOFly.ui similarity index 100% rename from motorApp/op/ui/EnsemblePSOFly.ui rename to motorApp/op/ui/autoconvert/EnsemblePSOFly.ui diff --git a/motorApp/op/ui/EnsemblePSOFly_graphic.ui b/motorApp/op/ui/autoconvert/EnsemblePSOFly_graphic.ui similarity index 100% rename from motorApp/op/ui/EnsemblePSOFly_graphic.ui rename to motorApp/op/ui/autoconvert/EnsemblePSOFly_graphic.ui diff --git a/motorApp/op/ui/EnsemblePSOFly_more.ui b/motorApp/op/ui/autoconvert/EnsemblePSOFly_more.ui similarity index 100% rename from motorApp/op/ui/EnsemblePSOFly_more.ui rename to motorApp/op/ui/autoconvert/EnsemblePSOFly_more.ui diff --git a/motorApp/op/ui/EnsemblePVErr.ui b/motorApp/op/ui/autoconvert/EnsemblePVErr.ui similarity index 100% rename from motorApp/op/ui/EnsemblePVErr.ui rename to motorApp/op/ui/autoconvert/EnsemblePVErr.ui diff --git a/motorApp/op/ui/HXP.ui b/motorApp/op/ui/autoconvert/HXP.ui similarity index 100% rename from motorApp/op/ui/HXP.ui rename to motorApp/op/ui/autoconvert/HXP.ui diff --git a/motorApp/op/ui/HXP_coordSys.ui b/motorApp/op/ui/autoconvert/HXP_coordSys.ui similarity index 100% rename from motorApp/op/ui/HXP_coordSys.ui rename to motorApp/op/ui/autoconvert/HXP_coordSys.ui diff --git a/motorApp/op/ui/HXP_extra.ui b/motorApp/op/ui/autoconvert/HXP_extra.ui similarity index 100% rename from motorApp/op/ui/HXP_extra.ui rename to motorApp/op/ui/autoconvert/HXP_extra.ui diff --git a/motorApp/op/ui/HXP_motors.ui b/motorApp/op/ui/autoconvert/HXP_motors.ui similarity index 100% rename from motorApp/op/ui/HXP_motors.ui rename to motorApp/op/ui/autoconvert/HXP_motors.ui diff --git a/motorApp/op/ui/HXP_moveAll.ui b/motorApp/op/ui/autoconvert/HXP_moveAll.ui similarity index 100% rename from motorApp/op/ui/HXP_moveAll.ui rename to motorApp/op/ui/autoconvert/HXP_moveAll.ui diff --git a/motorApp/op/ui/MAX_trajectoryPlot.ui b/motorApp/op/ui/autoconvert/MAX_trajectoryPlot.ui similarity index 100% rename from motorApp/op/ui/MAX_trajectoryPlot.ui rename to motorApp/op/ui/autoconvert/MAX_trajectoryPlot.ui diff --git a/motorApp/op/ui/MAX_trajectoryPlot2.ui b/motorApp/op/ui/autoconvert/MAX_trajectoryPlot2.ui similarity index 100% rename from motorApp/op/ui/MAX_trajectoryPlot2.ui rename to motorApp/op/ui/autoconvert/MAX_trajectoryPlot2.ui diff --git a/motorApp/op/ui/MAX_trajectoryScan.ui b/motorApp/op/ui/autoconvert/MAX_trajectoryScan.ui similarity index 100% rename from motorApp/op/ui/MAX_trajectoryScan.ui rename to motorApp/op/ui/autoconvert/MAX_trajectoryScan.ui diff --git a/motorApp/op/ui/MAX_trajectoryScan1.ui b/motorApp/op/ui/autoconvert/MAX_trajectoryScan1.ui similarity index 100% rename from motorApp/op/ui/MAX_trajectoryScan1.ui rename to motorApp/op/ui/autoconvert/MAX_trajectoryScan1.ui diff --git a/motorApp/op/ui/MAX_trajectoryScan2.ui b/motorApp/op/ui/autoconvert/MAX_trajectoryScan2.ui similarity index 100% rename from motorApp/op/ui/MAX_trajectoryScan2.ui rename to motorApp/op/ui/autoconvert/MAX_trajectoryScan2.ui diff --git a/motorApp/op/ui/MAX_trajectoryScanDebug.ui b/motorApp/op/ui/autoconvert/MAX_trajectoryScanDebug.ui similarity index 100% rename from motorApp/op/ui/MAX_trajectoryScanDebug.ui rename to motorApp/op/ui/autoconvert/MAX_trajectoryScanDebug.ui diff --git a/motorApp/op/ui/MAX_trajectoryScanSpeed.ui b/motorApp/op/ui/autoconvert/MAX_trajectoryScanSpeed.ui similarity index 100% rename from motorApp/op/ui/MAX_trajectoryScanSpeed.ui rename to motorApp/op/ui/autoconvert/MAX_trajectoryScanSpeed.ui diff --git a/motorApp/op/ui/PSOarrayPlot.ui b/motorApp/op/ui/autoconvert/PSOarrayPlot.ui similarity index 100% rename from motorApp/op/ui/PSOarrayPlot.ui rename to motorApp/op/ui/autoconvert/PSOarrayPlot.ui diff --git a/motorApp/op/ui/XPSAux.ui b/motorApp/op/ui/autoconvert/XPSAux.ui similarity index 100% rename from motorApp/op/ui/XPSAux.ui rename to motorApp/op/ui/autoconvert/XPSAux.ui diff --git a/motorApp/op/ui/XPSAuxBi_more.ui b/motorApp/op/ui/autoconvert/XPSAuxBi_more.ui similarity index 100% rename from motorApp/op/ui/XPSAuxBi_more.ui rename to motorApp/op/ui/autoconvert/XPSAuxBi_more.ui diff --git a/motorApp/op/ui/XPSAuxTest.ui b/motorApp/op/ui/autoconvert/XPSAuxTest.ui similarity index 100% rename from motorApp/op/ui/XPSAuxTest.ui rename to motorApp/op/ui/autoconvert/XPSAuxTest.ui diff --git a/motorApp/op/ui/XPSExtra.ui b/motorApp/op/ui/autoconvert/XPSExtra.ui similarity index 100% rename from motorApp/op/ui/XPSExtra.ui rename to motorApp/op/ui/autoconvert/XPSExtra.ui diff --git a/motorApp/op/ui/XPSTest.ui b/motorApp/op/ui/autoconvert/XPSTest.ui similarity index 100% rename from motorApp/op/ui/XPSTest.ui rename to motorApp/op/ui/autoconvert/XPSTest.ui diff --git a/motorApp/op/ui/XPSTop.ui b/motorApp/op/ui/autoconvert/XPSTop.ui similarity index 100% rename from motorApp/op/ui/XPSTop.ui rename to motorApp/op/ui/autoconvert/XPSTop.ui diff --git a/motorApp/op/ui/motor2x.ui b/motorApp/op/ui/autoconvert/motor2x.ui similarity index 100% rename from motorApp/op/ui/motor2x.ui rename to motorApp/op/ui/autoconvert/motor2x.ui diff --git a/motorApp/op/ui/motor3x.ui b/motorApp/op/ui/autoconvert/motor3x.ui similarity index 100% rename from motorApp/op/ui/motor3x.ui rename to motorApp/op/ui/autoconvert/motor3x.ui diff --git a/motorApp/op/ui/motor4x.ui b/motorApp/op/ui/autoconvert/motor4x.ui similarity index 100% rename from motorApp/op/ui/motor4x.ui rename to motorApp/op/ui/autoconvert/motor4x.ui diff --git a/motorApp/op/ui/motor5x.ui b/motorApp/op/ui/autoconvert/motor5x.ui similarity index 100% rename from motorApp/op/ui/motor5x.ui rename to motorApp/op/ui/autoconvert/motor5x.ui diff --git a/motorApp/op/ui/motor6x.ui b/motorApp/op/ui/autoconvert/motor6x.ui similarity index 100% rename from motorApp/op/ui/motor6x.ui rename to motorApp/op/ui/autoconvert/motor6x.ui diff --git a/motorApp/op/ui/motor8x.ui b/motorApp/op/ui/autoconvert/motor8x.ui similarity index 100% rename from motorApp/op/ui/motor8x.ui rename to motorApp/op/ui/autoconvert/motor8x.ui diff --git a/motorApp/op/ui/motorStatus104.ui b/motorApp/op/ui/autoconvert/motorStatus104.ui similarity index 100% rename from motorApp/op/ui/motorStatus104.ui rename to motorApp/op/ui/autoconvert/motorStatus104.ui diff --git a/motorApp/op/ui/motorStatus16.ui b/motorApp/op/ui/autoconvert/motorStatus16.ui similarity index 100% rename from motorApp/op/ui/motorStatus16.ui rename to motorApp/op/ui/autoconvert/motorStatus16.ui diff --git a/motorApp/op/ui/motorStatus24.ui b/motorApp/op/ui/autoconvert/motorStatus24.ui similarity index 100% rename from motorApp/op/ui/motorStatus24.ui rename to motorApp/op/ui/autoconvert/motorStatus24.ui diff --git a/motorApp/op/ui/motorStatus32.ui b/motorApp/op/ui/autoconvert/motorStatus32.ui similarity index 100% rename from motorApp/op/ui/motorStatus32.ui rename to motorApp/op/ui/autoconvert/motorStatus32.ui diff --git a/motorApp/op/ui/motorStatus40.ui b/motorApp/op/ui/autoconvert/motorStatus40.ui similarity index 100% rename from motorApp/op/ui/motorStatus40.ui rename to motorApp/op/ui/autoconvert/motorStatus40.ui diff --git a/motorApp/op/ui/motorStatus48.ui b/motorApp/op/ui/autoconvert/motorStatus48.ui similarity index 100% rename from motorApp/op/ui/motorStatus48.ui rename to motorApp/op/ui/autoconvert/motorStatus48.ui diff --git a/motorApp/op/ui/motorStatus56.ui b/motorApp/op/ui/autoconvert/motorStatus56.ui similarity index 100% rename from motorApp/op/ui/motorStatus56.ui rename to motorApp/op/ui/autoconvert/motorStatus56.ui diff --git a/motorApp/op/ui/motorStatus64.ui b/motorApp/op/ui/autoconvert/motorStatus64.ui similarity index 100% rename from motorApp/op/ui/motorStatus64.ui rename to motorApp/op/ui/autoconvert/motorStatus64.ui diff --git a/motorApp/op/ui/motorStatus72.ui b/motorApp/op/ui/autoconvert/motorStatus72.ui similarity index 100% rename from motorApp/op/ui/motorStatus72.ui rename to motorApp/op/ui/autoconvert/motorStatus72.ui diff --git a/motorApp/op/ui/motorStatus8.ui b/motorApp/op/ui/autoconvert/motorStatus8.ui similarity index 100% rename from motorApp/op/ui/motorStatus8.ui rename to motorApp/op/ui/autoconvert/motorStatus8.ui diff --git a/motorApp/op/ui/motorStatus80.ui b/motorApp/op/ui/autoconvert/motorStatus80.ui similarity index 100% rename from motorApp/op/ui/motorStatus80.ui rename to motorApp/op/ui/autoconvert/motorStatus80.ui diff --git a/motorApp/op/ui/motorStatus88.ui b/motorApp/op/ui/autoconvert/motorStatus88.ui similarity index 100% rename from motorApp/op/ui/motorStatus88.ui rename to motorApp/op/ui/autoconvert/motorStatus88.ui diff --git a/motorApp/op/ui/motors.ui b/motorApp/op/ui/autoconvert/motors.ui similarity index 100% rename from motorApp/op/ui/motors.ui rename to motorApp/op/ui/autoconvert/motors.ui diff --git a/motorApp/op/ui/motors_s.ui b/motorApp/op/ui/autoconvert/motors_s.ui similarity index 100% rename from motorApp/op/ui/motors_s.ui rename to motorApp/op/ui/autoconvert/motors_s.ui diff --git a/motorApp/op/ui/motorx.ui b/motorApp/op/ui/autoconvert/motorx.ui similarity index 100% rename from motorApp/op/ui/motorx.ui rename to motorApp/op/ui/autoconvert/motorx.ui diff --git a/motorApp/op/ui/motorxU.ui b/motorApp/op/ui/autoconvert/motorxU.ui similarity index 100% rename from motorApp/op/ui/motorxU.ui rename to motorApp/op/ui/autoconvert/motorxU.ui diff --git a/motorApp/op/ui/motorx_all.ui b/motorApp/op/ui/autoconvert/motorx_all.ui similarity index 100% rename from motorApp/op/ui/motorx_all.ui rename to motorApp/op/ui/autoconvert/motorx_all.ui diff --git a/motorApp/op/ui/motorx_bare.ui b/motorApp/op/ui/autoconvert/motorx_bare.ui similarity index 100% rename from motorApp/op/ui/motorx_bare.ui rename to motorApp/op/ui/autoconvert/motorx_bare.ui diff --git a/motorApp/op/ui/motorx_help.ui b/motorApp/op/ui/autoconvert/motorx_help.ui similarity index 100% rename from motorApp/op/ui/motorx_help.ui rename to motorApp/op/ui/autoconvert/motorx_help.ui diff --git a/motorApp/op/ui/motorx_more.ui b/motorApp/op/ui/autoconvert/motorx_more.ui similarity index 100% rename from motorApp/op/ui/motorx_more.ui rename to motorApp/op/ui/autoconvert/motorx_more.ui diff --git a/motorApp/op/ui/autoconvert/motorx_msta_detail.ui b/motorApp/op/ui/autoconvert/motorx_msta_detail.ui new file mode 100644 index 0000000..965fdd7 --- /dev/null +++ b/motorApp/op/ui/autoconvert/motorx_msta_detail.ui @@ -0,0 +1,968 @@ + + + MainWindow + + + + 0 + 0 + 400 + 400 + + + + + +QWidget#centralWidget {background: rgba(200, 200, 200, 255);} + + + + + + + + 0 + 31 + 100 + 25 + + + + + 10 + 0 + 184 + + + + caGraphics::Solid + + + caGraphics::Filled + + + + 10 + 0 + 184 + + + + caGraphics::Rectangle + + + + + + 0 + 0 + 398 + 30 + + + + + 255 + 255 + 255 + + + + caGraphics::Solid + + + caGraphics::Filled + + + + 255 + 255 + 255 + + + + caGraphics::Rectangle + + + + + + 0 + 30 + 402 + 3 + + + + + 10 + 0 + 184 + + + + caPolyLine::Solid + + + 3 + + + + 10 + 0 + 184 + + + + 1,1;400,1 + + + caPolyLine::Filled + + + + + + 4 + 5 + 153 + 20 + + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + $(P)$(M).DESC + + + + 10 + 0 + 184 + + + + + 255 + 255 + 255 + + + + caLineEdit::Static + + + caLineEdit::Channel + + + caLineEdit::Channel + + + 1.000000000000000 + + + 0.000000000000000 + + + caLineEdit::Height + + + caLineEdit::decimal + + + + + + 289 + 5 + 100 + 20 + + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + $(P)$(M).DTYP + + + + 10 + 0 + 184 + + + + + 255 + 255 + 255 + + + + caLineEdit::Static + + + caLineEdit::Channel + + + caLineEdit::Channel + + + 1.000000000000000 + + + 0.000000000000000 + + + caLineEdit::Height + + + caLineEdit::decimal + + + + + + 171 + 5 + 51 + 20 + + + + QFrame::NoFrame + + + $(P)$(M) + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 2 + 34 + 95 + 20 + + + + QFrame::NoFrame + + + Status Detail + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 255 + 255 + 255 + + + + + 255 + 255 + 255 + + + + + + + 5 + 65 + 37 + 320 + + + + $(P)$(M).MSTA + + + caByte::Up + + + 0 + + + 15 + + + caByte::Static + + + + 30 + 187 + 0 + + + + + 200 + 200 + 200 + + + + + + + 50 + 68 + 352 + 317 + + + + + + 0 + 0 + 171 + 15 + + + + QFrame::NoFrame + + + Unused + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 20 + 171 + 15 + + + + QFrame::NoFrame + + + Unused + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 40 + 350 + 15 + + + + QFrame::NoFrame + + + MINUS_LS: minus limit switch has been hit + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 60 + 350 + 15 + + + + QFrame::NoFrame + + + COMM_ERR: Communication Error + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 80 + 345 + 15 + + + + QFrame::NoFrame + + + GAIN_SUPPORT: motor supports closed-loop position control + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 100 + 350 + 15 + + + + QFrame::NoFrame + + + MOVING: non-zero velocity present + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 120 + 350 + 15 + + + + QFrame::NoFrame + + + PROBLEM: driver stopped polling + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 140 + 350 + 15 + + + + QFrame::NoFrame + + + PRESENT: encoder is present + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 160 + 350 + 15 + + + + QFrame::NoFrame + + + HOME: if at home position + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 180 + 350 + 15 + + + + QFrame::NoFrame + + + Unused + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 200 + 350 + 15 + + + + QFrame::NoFrame + + + POSITION: closed-loop position control enabled + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 220 + 350 + 15 + + + + QFrame::NoFrame + + + Unused + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 240 + 350 + 15 + + + + QFrame::NoFrame + + + HOMELS: state of home limit switch + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 260 + 350 + 15 + + + + QFrame::NoFrame + + + PLUS_LS: plus limit has been hit + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 280 + 350 + 15 + + + + QFrame::NoFrame + + + DONE: motion is complete + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + + + 0 + 300 + 350 + 15 + + + + QFrame::NoFrame + + + DIRECTION: last raw (0:Neg, 1:Pos) + + + Qt::AlignAbsolute|Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + ESimpleLabel::Height + + + + 0 + 0 + 0 + + + + + 0 + 0 + 0 + + + + + caRectangle_0 + caRectangle_1 + caPolyLine_0 + caLabel_0 + caLabel_1 + caFrame_0 + caLineEdit_0 + caLineEdit_1 + caByte_0 + + + + + caFrame + QFrame +
    caFrame
    + 1 +
    + + caLabel + QLabel +
    caLabel
    +
    + + caGraphics + QWidget +
    caGraphics
    +
    + + caPolyLine + QWidget +
    caPolyLine
    +
    + + caLineEdit + QLineEdit +
    caLineEdit
    +
    + + caByte + QWidget +
    caByte
    +
    +
    + + +
    diff --git a/motorApp/op/ui/motorx_setup.ui b/motorApp/op/ui/autoconvert/motorx_setup.ui similarity index 100% rename from motorApp/op/ui/motorx_setup.ui rename to motorApp/op/ui/autoconvert/motorx_setup.ui diff --git a/motorApp/op/ui/motorx_tiny.ui b/motorApp/op/ui/autoconvert/motorx_tiny.ui similarity index 100% rename from motorApp/op/ui/motorx_tiny.ui rename to motorApp/op/ui/autoconvert/motorx_tiny.ui diff --git a/motorApp/op/ui/profileMove.ui b/motorApp/op/ui/autoconvert/profileMove.ui similarity index 100% rename from motorApp/op/ui/profileMove.ui rename to motorApp/op/ui/autoconvert/profileMove.ui diff --git a/motorApp/op/ui/profileMoveXPS.ui b/motorApp/op/ui/autoconvert/profileMoveXPS.ui similarity index 100% rename from motorApp/op/ui/profileMoveXPS.ui rename to motorApp/op/ui/autoconvert/profileMoveXPS.ui diff --git a/motorApp/op/ui/topMotors4.ui b/motorApp/op/ui/autoconvert/topMotors4.ui similarity index 100% rename from motorApp/op/ui/topMotors4.ui rename to motorApp/op/ui/autoconvert/topMotors4.ui diff --git a/motorApp/op/ui/topMotors8.ui b/motorApp/op/ui/autoconvert/topMotors8.ui similarity index 100% rename from motorApp/op/ui/topMotors8.ui rename to motorApp/op/ui/autoconvert/topMotors8.ui diff --git a/motorApp/op/ui/topMotors8_more.ui b/motorApp/op/ui/autoconvert/topMotors8_more.ui similarity index 100% rename from motorApp/op/ui/topMotors8_more.ui rename to motorApp/op/ui/autoconvert/topMotors8_more.ui diff --git a/motorApp/op/ui/trajectoryPlot.ui b/motorApp/op/ui/autoconvert/trajectoryPlot.ui similarity index 100% rename from motorApp/op/ui/trajectoryPlot.ui rename to motorApp/op/ui/autoconvert/trajectoryPlot.ui diff --git a/motorApp/op/ui/trajectoryScan.ui b/motorApp/op/ui/autoconvert/trajectoryScan.ui similarity index 100% rename from motorApp/op/ui/trajectoryScan.ui rename to motorApp/op/ui/autoconvert/trajectoryScan.ui diff --git a/motorApp/op/ui/trajectoryScanDebug.ui b/motorApp/op/ui/autoconvert/trajectoryScanDebug.ui similarity index 100% rename from motorApp/op/ui/trajectoryScanDebug.ui rename to motorApp/op/ui/autoconvert/trajectoryScanDebug.ui diff --git a/motorApp/op/ui/trajectoryScan_Ensemble.ui b/motorApp/op/ui/autoconvert/trajectoryScan_Ensemble.ui similarity index 100% rename from motorApp/op/ui/trajectoryScan_Ensemble.ui rename to motorApp/op/ui/autoconvert/trajectoryScan_Ensemble.ui diff --git a/motorApp/op/ui/trajectoryScan_MAXv.ui b/motorApp/op/ui/autoconvert/trajectoryScan_MAXv.ui similarity index 100% rename from motorApp/op/ui/trajectoryScan_MAXv.ui rename to motorApp/op/ui/autoconvert/trajectoryScan_MAXv.ui diff --git a/motorApp/op/ui/motor2xU.ui b/motorApp/op/ui/motor2xU.ui new file mode 100644 index 0000000..826a681 --- /dev/null +++ b/motorApp/op/ui/motor2xU.ui @@ -0,0 +1,60 @@ + + + MainWindow + + + + 0 + 0 + 352 + 282 + + + + MainWindow + + + + + + 0 + 0 + 176 + 282 + + + + P=$(P),M=$(M1) + + + motorxU.ui + + + + + + 176 + 0 + 176 + 282 + + + + P=$(P),M=$(M2) + + + motorxU.ui + + + + + + + caInclude + QWidget +
    caInclude
    +
    +
    + + +
    diff --git a/motorApp/op/ui/motor3xU.ui b/motorApp/op/ui/motor3xU.ui new file mode 100644 index 0000000..13cee66 --- /dev/null +++ b/motorApp/op/ui/motor3xU.ui @@ -0,0 +1,76 @@ + + + MainWindow + + + + 0 + 0 + 528 + 282 + + + + MainWindow + + + + + + 0 + 0 + 176 + 282 + + + + P=$(P),M=$(M1) + + + motorxU.ui + + + + + + 176 + 0 + 176 + 282 + + + + P=$(P),M=$(M2) + + + motorxU.ui + + + + + + 352 + 0 + 176 + 282 + + + + P=$(P),M=$(M3) + + + motorxU.ui + + + + + + + caInclude + QWidget +
    caInclude
    +
    +
    + + +
    diff --git a/motorApp/op/ui/motor4xU.ui b/motorApp/op/ui/motor4xU.ui new file mode 100644 index 0000000..147d9e8 --- /dev/null +++ b/motorApp/op/ui/motor4xU.ui @@ -0,0 +1,92 @@ + + + MainWindow + + + + 0 + 0 + 704 + 282 + + + + MainWindow + + + + + + 0 + 0 + 176 + 282 + + + + P=$(P),M=$(M1) + + + motorxU.ui + + + + + + 176 + 0 + 176 + 282 + + + + P=$(P),M=$(M2) + + + motorxU.ui + + + + + + 352 + 0 + 176 + 282 + + + + P=$(P),M=$(M3) + + + motorxU.ui + + + + + + 528 + 0 + 176 + 282 + + + + P=$(P),M=$(M4) + + + motorxU.ui + + + + + + + caInclude + QWidget +
    caInclude
    +
    +
    + + +
    diff --git a/motorApp/op/ui/motor5xU.ui b/motorApp/op/ui/motor5xU.ui new file mode 100644 index 0000000..ca45d7d --- /dev/null +++ b/motorApp/op/ui/motor5xU.ui @@ -0,0 +1,108 @@ + + + MainWindow + + + + 0 + 0 + 880 + 282 + + + + MainWindow + + + + + + 0 + 0 + 176 + 282 + + + + P=$(P),M=$(M1) + + + motorxU.ui + + + + + + 176 + 0 + 176 + 282 + + + + P=$(P),M=$(M2) + + + motorxU.ui + + + + + + 352 + 0 + 176 + 282 + + + + P=$(P),M=$(M3) + + + motorxU.ui + + + + + + 528 + 0 + 176 + 282 + + + + P=$(P),M=$(M5) + + + motorxU.ui + + + + + + 704 + 0 + 176 + 282 + + + + P=$(P),M=$(M5) + + + motorxU.ui + + + + + + + caInclude + QWidget +
    caInclude
    +
    +
    + + +
    diff --git a/motorApp/op/ui/motor6xU.ui b/motorApp/op/ui/motor6xU.ui new file mode 100644 index 0000000..2de5181 --- /dev/null +++ b/motorApp/op/ui/motor6xU.ui @@ -0,0 +1,124 @@ + + + MainWindow + + + + 0 + 0 + 528 + 564 + + + + MainWindow + + + + + + 0 + 0 + 176 + 282 + + + + P=$(P),M=$(M1) + + + motorxU.ui + + + + + + 176 + 0 + 176 + 282 + + + + P=$(P),M=$(M2) + + + motorxU.ui + + + + + + 352 + 0 + 176 + 282 + + + + P=$(P),M=$(M3) + + + motorxU.ui + + + + + + 0 + 282 + 176 + 282 + + + + P=$(P),M=$(M4) + + + motorxU.ui + + + + + + 176 + 282 + 176 + 282 + + + + P=$(P),M=$(M5) + + + motorxU.ui + + + + + + 352 + 282 + 176 + 282 + + + + P=$(P),M=$(M6) + + + motorxU.ui + + + + + + + caInclude + QWidget +
    caInclude
    +
    +
    + + +
    diff --git a/motorApp/op/ui/motor7xU.ui b/motorApp/op/ui/motor7xU.ui new file mode 100644 index 0000000..f29081c --- /dev/null +++ b/motorApp/op/ui/motor7xU.ui @@ -0,0 +1,140 @@ + + + MainWindow + + + + 0 + 0 + 704 + 564 + + + + MainWindow + + + + + + 0 + 0 + 176 + 282 + + + + P=$(P),M=$(M1) + + + motorxU.ui + + + + + + 176 + 0 + 176 + 282 + + + + P=$(P),M=$(M2) + + + motorxU.ui + + + + + + 352 + 0 + 176 + 282 + + + + P=$(P),M=$(M3) + + + motorxU.ui + + + + + + 528 + 0 + 176 + 282 + + + + P=$(P),M=$(M4) + + + motorxU.ui + + + + + + 0 + 282 + 176 + 282 + + + + P=$(P),M=$(M5) + + + motorxU.ui + + + + + + 176 + 282 + 176 + 282 + + + + P=$(P),M=$(M6) + + + motorxU.ui + + + + + + 352 + 282 + 176 + 282 + + + + P=$(P),M=$(M7) + + + motorxU.ui + + + + + + + caInclude + QWidget +
    caInclude
    +
    +
    + + +
    diff --git a/motorApp/op/ui/motor8xU.ui b/motorApp/op/ui/motor8xU.ui new file mode 100644 index 0000000..8a6d044 --- /dev/null +++ b/motorApp/op/ui/motor8xU.ui @@ -0,0 +1,156 @@ + + + MainWindow + + + + 0 + 0 + 704 + 564 + + + + MainWindow + + + + + + 0 + 0 + 176 + 282 + + + + P=$(P),M=$(M1) + + + motorxU.ui + + + + + + 176 + 0 + 176 + 282 + + + + P=$(P),M=$(M2) + + + motorxU.ui + + + + + + 352 + 0 + 176 + 282 + + + + P=$(P),M=$(M3) + + + motorxU.ui + + + + + + 528 + 0 + 176 + 282 + + + + P=$(P),M=$(M4) + + + motorxU.ui + + + + + + 0 + 282 + 176 + 282 + + + + P=$(P),M=$(M5) + + + motorxU.ui + + + + + + 176 + 282 + 176 + 282 + + + + P=$(P),M=$(M6) + + + motorxU.ui + + + + + + 352 + 282 + 176 + 282 + + + + P=$(P),M=$(M7) + + + motorxU.ui + + + + + + 528 + 282 + 176 + 282 + + + + P=$(P),M=$(M8) + + + motorxU.ui + + + + + + + caInclude + QWidget +
    caInclude
    +
    +
    + + +
    diff --git a/motorApp/op/ui/motorx_msta_detail.ui b/motorApp/op/ui/motorx_msta_detail.ui deleted file mode 100644 index 7b4499c..0000000 --- a/motorApp/op/ui/motorx_msta_detail.ui +++ /dev/null @@ -1,956 +0,0 @@ - - -MainWindow - - - - 549 - 406 - 400 - 400 - - - - - -QWidget#centralWidget {background: rgba(200, 200, 200, 255);} -QPushButton::menu-indicator {image: url(none.png); width: 0} - - - - - - - caGraphics::Rectangle - - - - 0 - 31 - 100 - 25 - - - - - 10 - 0 - 184 - - - - Filled - - - - 10 - 0 - 184 - - - - Solid - - - - - caGraphics::Rectangle - - - - 0 - 0 - 398 - 30 - - - - - 255 - 255 - 255 - - - - Filled - - - - 255 - 255 - 255 - - - - Solid - - - - - - 0 - 30 - 402 - 3 - - - - 3 - - - - 10 - 0 - 184 - - - - Filled - - - - 10 - 0 - 184 - - - - Solid - - - 1,1;400,1; - - - - - - 4 - 5 - 153 - 20 - - - - caLineEdit::WidthAndHeight - - - $(P)$(M).DESC - - - - 10 - 0 - 184 - - - - - 255 - 255 - 255 - - - - caLineEdit::Channel - - - caLineEdit::Channel - - - caLineEdit::Channel - - - 0.0 - - - 1.0 - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - decimal - - - caLineEdit::Static - - - - - - 289 - 5 - 100 - 20 - - - - caLineEdit::WidthAndHeight - - - $(P)$(M).DTYP - - - - 10 - 0 - 184 - - - - - 255 - 255 - 255 - - - - caLineEdit::Channel - - - caLineEdit::Channel - - - caLineEdit::Channel - - - 0.0 - - - 1.0 - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - decimal - - - caLineEdit::Static - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - $(P)$(M) - - - ESimpleLabel::WidthAndHeight - - - - 171 - 5 - 96 - 20 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 255 - 255 - 255 - - - - - 255 - 255 - 255 - - - - Status Detail - - - ESimpleLabel::WidthAndHeight - - - - 2 - 34 - 156 - 20 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 5 - 65 - 37 - 320 - - - - $(P)$(M).MSTA - - - - 30 - 187 - 0 - - - - - 200 - 200 - 200 - - - - caByte::Static - - - 0 - - - 15 - - - Down - - - - - - 50 - 68 - 352 - 317 - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - Unused - - - ESimpleLabel::WidthAndHeight - - - - 0 - 0 - 171 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - Unused - - - ESimpleLabel::WidthAndHeight - - - - 0 - 20 - 171 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - MINUS_LS: minus limit switch has been hit - - - ESimpleLabel::WidthAndHeight - - - - 0 - 40 - 369 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - COMM_ERR: Communication Error - - - ESimpleLabel::WidthAndHeight - - - - 0 - 60 - 350 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - GAIN_SUPPORT: motor supports closed-loop position control - - - ESimpleLabel::WidthAndHeight - - - - 0 - 80 - 513 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - MOVING: non-zero velocity present - - - ESimpleLabel::WidthAndHeight - - - - 0 - 100 - 350 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - PROBLEM: driver stopped polling - - - ESimpleLabel::WidthAndHeight - - - - 0 - 120 - 350 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - PRESENT: encoder is present - - - ESimpleLabel::WidthAndHeight - - - - 0 - 140 - 350 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - HOME: if at home position - - - ESimpleLabel::WidthAndHeight - - - - 0 - 160 - 350 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - Unused - - - ESimpleLabel::WidthAndHeight - - - - 0 - 180 - 350 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - POSITION: closed-loop position control enabled - - - ESimpleLabel::WidthAndHeight - - - - 0 - 200 - 414 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - Unused - - - ESimpleLabel::WidthAndHeight - - - - 0 - 220 - 350 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - HOMELS: state of home limit switch - - - ESimpleLabel::WidthAndHeight - - - - 0 - 240 - 350 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - PLUS_LS: plus limit has been hit - - - ESimpleLabel::WidthAndHeight - - - - 0 - 260 - 350 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - DONE: motion is complete - - - ESimpleLabel::WidthAndHeight - - - - 0 - 280 - 350 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - - QFrame::NoFrame - - - - 0 - 0 - 0 - - - - - 0 - 0 - 0 - - - - DIRECTION: last raw (0:Neg, 1:Pos) - - - ESimpleLabel::WidthAndHeight - - - - 0 - 300 - 350 - 15 - - - - Qt::AlignAbsolute|Qt::AlignLeft|Qt::AlignVCenter - - - - caRectangle_0 - caRectangle_1 - caPolyLine_0 - caLabel_0 - caLabel_1 - caLabel_2 - caLabel_3 - caLabel_4 - caLabel_5 - caLabel_6 - caLabel_7 - caLabel_8 - caLabel_9 - caLabel_10 - caLabel_11 - caLabel_12 - caLabel_13 - caLabel_14 - caLabel_15 - caLabel_16 - caLabel_17 - caFrame_0 - caLineEdit_0 - caLineEdit_1 - caByte_0 - - - \ No newline at end of file diff --git a/motorExApp/NoAsyn/Makefile b/motorExApp/NoAsyn/Makefile index 64b6a95..c2dc693 100644 --- a/motorExApp/NoAsyn/Makefile +++ b/motorExApp/NoAsyn/Makefile @@ -1,10 +1,6 @@ #FILENAME... Makefile #USAGE... Makefile for motor application example without Asyn -#Version: $Revision$ -#Modified By: $Author$ -#Last Modified: $Date$ -#HeadURL: $URL$ # "#!" marks lines that can be uncommented. diff --git a/motorExApp/WithAsyn/Makefile b/motorExApp/WithAsyn/Makefile index f002a2b..268cbfe 100644 --- a/motorExApp/WithAsyn/Makefile +++ b/motorExApp/WithAsyn/Makefile @@ -1,10 +1,6 @@ #FILENAME... Makefile #USAGE... Makefile for motor application example with Asyn -#Version: $Revision: 18552 $ -#Modified By: $Author: sluiter $ -#Last Modified: $Date: 2015-01-07 09:33:30 -0600 (Wed, 07 Jan 2015) $ -#HeadURL: $URL: https://subversion.xray.aps.anl.gov/synApps/motor/tags/R6-9/motorExApp/WithAsyn/Makefile $ # "#!" marks lines that can be uncommented. @@ -24,6 +20,7 @@ COMMONDBDS += devMicroMo.dbd COMMONDBDS += devNewport.dbd ifdef SNCSEQ COMMONDBDS += LdevNewportTS.dbd +COMMONDBDS += devAerotechSeq.dbd endif COMMONDBDS += devPIMotor.dbd COMMONDBDS += devOms.dbd @@ -43,11 +40,20 @@ ifdef BUSY endif COMMONDBDS += PI_GCS2Support.dbd COMMONDBDS += phytron.dbd +ifdef LUA +COMMONDBDS += ScriptMotorDriver.dbd +endif DBD += WithAsyn.dbd WithAsyn_DBD += $(COMMONDBDS) ifdef SNCSEQ -WithAsyn_DBD += devSequencer.dbd + # seq-2-1 and earlier has devSequencer + ifeq (seq-2-1, $(findstring seq-2-1, $(SNCSEQ))) + WithAsyn_DBD += devSequencer.dbd + else ifeq (seq-2.1, $(findstring seq-2.1, $(SNCSEQ))) + WithAsyn_DBD += devSequencer.dbd + endif + endif DBD += WithAsynVx.dbd @@ -81,12 +87,24 @@ COMMONLIBS += ACRMotor COMMONLIBS += PI_GCS2Support COMMONLIBS += phytronAxisMotor COMMONLIBS += motor +ifdef LUA +COMMONLIBS += ScriptMotor +COMMONLIBS += lua +endif # Needed for Newport SNL programs WithAsyn_LIBS += $(COMMONLIBS) WithAsyn_LIBS += asyn ifdef SNCSEQ -WithAsyn_LIBS += seqDev seq pv + # seq-2-1 and earlier has devSequencer + ifeq (seq-2-1, $(findstring seq-2-1, $(SNCSEQ))) + WithAsyn_LIBS += seqDev seq pv + else ifeq (seq-2.1, $(findstring seq-2.1, $(SNCSEQ))) + WithAsyn_LIBS += seqDev seq pv + else + # seq 2.2. + WithAsyn_LIBS += seq pv + endif endif WithAsyn_LIBS += $(EPICS_BASE_IOC_LIBS) @@ -97,7 +115,14 @@ endif WithAsynVx_LIBS += asyn # Needed for Newport SNL programs ifdef SNCSEQ -WithAsynVx_LIBS += seqDev seq pv + ifeq (seq-2-1, $(findstring seq-2-1, $(SNCSEQ))) + WithAsynVx_LIBS += seqDev seq pv + else ifeq (seq-2.1, $(findstring seq-2.1, $(SNCSEQ))) + WithAsynVx_LIBS += seqDev seq pv + else + # seq 2.2. + WithAsynVx_LIBS += seq pv + endif endif WithAsynVx_LIBS += $(EPICS_BASE_IOC_LIBS)

    3I_A8Lw?{qSjUe7q?OvvXBboUE~MMLWIHt+rx$ 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