forked from epics_driver_modules/motorBase
Add PI GCS2 module
This commit is contained in:
@@ -39,6 +39,9 @@ MclennanSrc_DEPEND_DIRS = MotorSrc
|
||||
DIRS += PiSrc
|
||||
PiSrc_DEPEND_DIRS = MotorSrc
|
||||
|
||||
DIRS += PIGCS2Src
|
||||
PIGCS2Src_DEPEND_DIRS = MotorSrc
|
||||
|
||||
DIRS += MicroMoSrc
|
||||
MicroMoSrc_DEPEND_DIRS = MotorSrc
|
||||
|
||||
|
||||
Executable
+586
@@ -0,0 +1,586 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?>
|
||||
|
||||
<cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<cconfiguration id="0.1864894712">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="0.1864894712" moduleId="org.eclipse.cdt.core.settings" name="Debug">
|
||||
<macros>
|
||||
<stringMacro name="EPICS_HOST_ARCH" type="VALUE_TEXT" value="linux-x86-debug"/>
|
||||
</macros>
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactName="PIasynSrcHg" buildProperties="" description="linux-x86-debug" id="0.1864894712" name="Debug" parent="org.eclipse.cdt.build.core.prefbase.cfg">
|
||||
<folderInfo id="0.1864894712." name="/" resourcePath="">
|
||||
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.989405490" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
|
||||
<targetPlatform id="org.eclipse.cdt.build.core.prefbase.toolchain.989405490.193624300" name=""/>
|
||||
<builder buildPath="${workspace_loc:/PIasynSrcHg}" id="org.eclipse.cdt.build.core.settings.default.builder.1962974436" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.214165044" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.561098644" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.444003453" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.708287581" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1675982262" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.1921784774" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.141379334" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="makefileGenerator">
|
||||
<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<scannerConfigBuildInfo instanceId="0.1624471516">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="makefileGenerator">
|
||||
<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="0.1864894712">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="makefileGenerator">
|
||||
<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
|
||||
</cconfiguration>
|
||||
<cconfiguration id="0.1864894712.1771981055">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="0.1864894712.1771981055" moduleId="org.eclipse.cdt.core.settings" name="Release">
|
||||
<macros>
|
||||
<stringMacro name="EPICS_HOST_ARCH" type="VALUE_TEXT" value="linux-x86"/>
|
||||
</macros>
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration buildProperties="" description="linux-x86" id="0.1864894712.1771981055" name="Release" parent="org.eclipse.cdt.build.core.prefbase.cfg">
|
||||
<folderInfo id="0.1864894712.1771981055." name="/" resourcePath="">
|
||||
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.868478225" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
|
||||
<targetPlatform id="org.eclipse.cdt.build.core.prefbase.toolchain.868478225.132781498" name=""/>
|
||||
<builder id="org.eclipse.cdt.build.core.settings.default.builder.769300020" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder"/>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.237853117" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.63972889" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.894030566" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.556486508" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.849152430" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
<tool id="org.eclipse.cdt.build.core.settings.holder.2054850057" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1101777661" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||
</tool>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="makefileGenerator">
|
||||
<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<scannerConfigBuildInfo instanceId="0.1624471516">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="makefileGenerator">
|
||||
<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="0.1864894712">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="makefileGenerator">
|
||||
<runAction arguments="-E -P -v -dD" command="" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/${specs_file}" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.cpp" command="g++" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-E -P -v -dD ${plugin_state_location}/specs.c" command="gcc" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfile">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/${specs_file}"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'g++ -E -P -v -dD "${plugin_state_location}/specs.cpp"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
<profile id="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileC">
|
||||
<buildOutputProvider>
|
||||
<openAction enabled="true" filePath=""/>
|
||||
<parser enabled="true"/>
|
||||
</buildOutputProvider>
|
||||
<scannerInfoProvider id="specsFile">
|
||||
<runAction arguments="-c 'gcc -E -P -v -dD "${plugin_state_location}/specs.c"'" command="sh" useDefault="true"/>
|
||||
<parser enabled="true"/>
|
||||
</scannerInfoProvider>
|
||||
</profile>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.language.mapping"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<project id="PIasynSrcHg.null.746367885" name="PIasynSrcHg"/>
|
||||
</storageModule>
|
||||
</cproject>
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>PIasynSrcHg</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>?name?</key>
|
||||
<value></value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.append_environment</key>
|
||||
<value>true</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.autoBuildTarget</key>
|
||||
<value>all</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.buildArguments</key>
|
||||
<value></value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.buildCommand</key>
|
||||
<value>make</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.buildLocation</key>
|
||||
<value>${workspace_loc:/PIasynSrcHg}</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>
|
||||
<value>clean</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.contents</key>
|
||||
<value>org.eclipse.cdt.make.core.activeConfigSettings</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.enableAutoBuild</key>
|
||||
<value>false</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.enableCleanBuild</key>
|
||||
<value>true</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.enableFullBuild</key>
|
||||
<value>true</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.fullBuildTarget</key>
|
||||
<value>all</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.stopOnError</key>
|
||||
<value>true</value>
|
||||
</dictionary>
|
||||
<dictionary>
|
||||
<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>
|
||||
<value>true</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.core.ccnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
TOP=../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
#----------------------------------------
|
||||
# ADD MACRO DEFINITIONS AFTER THIS LINE
|
||||
|
||||
#----------------------------------------------------
|
||||
# Optimization of db files using dbst (DEFAULT: NO)
|
||||
#DB_OPT = YES
|
||||
|
||||
#----------------------------------------------------
|
||||
# Create and install (or just install) into <top>/db
|
||||
# databases, templates, substitutions like this
|
||||
DB += PI_Support.db
|
||||
DB += PI_SupportCtrl.db
|
||||
|
||||
#----------------------------------------------------
|
||||
# If <anyname>.db template is not named <anyname>*.template add
|
||||
# <anyname>_template = <templatename>
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *src*))
|
||||
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *Src*))
|
||||
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *db*))
|
||||
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *Db*))
|
||||
include $(TOP)/configure/RULES_DIRS
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
TOP=../..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
#----------------------------------------
|
||||
# ADD MACRO DEFINITIONS AFTER THIS LINE
|
||||
#=============================
|
||||
|
||||
#==================================================
|
||||
# Build an IOC support library
|
||||
|
||||
LIBRARY_IOC += PI_GCS2Support
|
||||
|
||||
# motorRecord.h will be created from motorRecord.dbd
|
||||
# install devMotorSoft.dbd into <top>/dbd
|
||||
DBD += PI_GCS2Support.dbd
|
||||
|
||||
# The following are compiled and added to the Support library
|
||||
PI_GCS2Support_SRCS += PIasynController.cpp
|
||||
PI_GCS2Support_SRCS += PIasynAxis.cpp
|
||||
PI_GCS2Support_SRCS += PIGCSController.cpp
|
||||
PI_GCS2Support_SRCS += PIGCSMotorController.cpp
|
||||
PI_GCS2Support_SRCS += PIGCSPiezoController.cpp
|
||||
PI_GCS2Support_SRCS += PIE517Controller.cpp
|
||||
PI_GCS2Support_SRCS += PIE755Controller.cpp
|
||||
PI_GCS2Support_SRCS += PIHexapodController.cpp
|
||||
PI_GCS2Support_SRCS += PIC702Controller.cpp
|
||||
PI_GCS2Support_SRCS += translateerror.c
|
||||
|
||||
PI_GCS2Support_LIBS += motor
|
||||
PI_GCS2Support_LIBS += asyn
|
||||
PI_GCS2Support_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* PIC702Controller
|
||||
*
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#include "PIC702Controller.h"
|
||||
#include "PIasynAxis.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
//#undef asynPrint
|
||||
//#define asynPrint(user,reason,format...) 0
|
||||
|
||||
|
||||
asynStatus PIC702Controller::getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl)
|
||||
{
|
||||
int busy;
|
||||
|
||||
epicsTimeStamp now;
|
||||
epicsTimeGetCurrent(&now);
|
||||
if(epicsTimeDiffInSeconds(&now,&m_timeREFstarted) < 1.0)
|
||||
{
|
||||
homing = 1;
|
||||
moving = 1;
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
|
||||
asynStatus status = getBusy(pAxis, busy);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
negLimit = 0;
|
||||
posLimit = 0;
|
||||
homing = busy;
|
||||
if (busy)
|
||||
{
|
||||
moving = busy;
|
||||
return status;
|
||||
}
|
||||
|
||||
status = getMoving(pAxis, moving);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIC702Controller::findConnectedAxes()
|
||||
{
|
||||
// GCS! - axes are not separated by LineFeeds
|
||||
// axis identifier is only one single char, all axes returned as single "word"
|
||||
m_nrFoundAxes = 0;
|
||||
for (size_t i=0; i<MAX_NR_AXES; i++)
|
||||
{
|
||||
m_axesIDs[i] = NULL;
|
||||
}
|
||||
char allAxesIDs[127];
|
||||
asynStatus status = PIGCSController::sendAndReceive("SAI?", allAxesIDs, 127);
|
||||
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
m_nrFoundAxes = strlen(allAxesIDs);
|
||||
if (MAX_NR_AXES <= m_nrFoundAxes)
|
||||
{
|
||||
return asynError;
|
||||
}
|
||||
char* p = m_allAxesIDs;
|
||||
for (size_t i=0; i<m_nrFoundAxes; i++)
|
||||
{
|
||||
*p = allAxesIDs[m_nrFoundAxes - 1 - i];
|
||||
m_axesIDs[i] = p;
|
||||
p++;
|
||||
*p = '\0';
|
||||
p++;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIC702Controller::getMaxAcceleration(PIasynAxis* pAxis)
|
||||
{
|
||||
double maxAcc, maxDec;
|
||||
asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_CURR_ACCEL, maxAcc);
|
||||
if (asynSuccess != status)
|
||||
return status;
|
||||
status = getGCSParameter(pAxis, PI_PARA_MOT_CURR_DECEL, maxDec);
|
||||
if (asynSuccess != status)
|
||||
return status;
|
||||
|
||||
if (maxAcc < maxDec)
|
||||
{
|
||||
pAxis->m_maxAcceleration = maxAcc;
|
||||
}
|
||||
else
|
||||
{
|
||||
pAxis->m_maxAcceleration = maxDec;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIC702Controller::hasReferenceSensor(PIasynAxis* pAxis)
|
||||
{
|
||||
double hasref;
|
||||
asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_HAT_REF, hasref);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
pAxis->m_bHasReference = hasref > 0.1;
|
||||
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
|
||||
"PIC702Controller::hasReferenceSwitch() axis has %sreference sensor\n",
|
||||
pAxis->m_bHasReference?"":"no ");
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIC702Controller::getReferencedState(PIasynAxis* pAxis)
|
||||
{
|
||||
double isref;
|
||||
asynStatus status = getGCSParameter(pAxis, PI_PARA_C702_REFERENCED, isref);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
pAxis->m_homed = (isref > 0.1)?1:0;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIC702Controller::referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards)
|
||||
{
|
||||
asynStatus status = setServo(pAxis, 1);
|
||||
if (asynSuccess != status)
|
||||
return status;
|
||||
|
||||
status = setVelocityCts(pAxis, velocity);
|
||||
if (asynSuccess != status)
|
||||
return status;
|
||||
|
||||
char cmd[100];
|
||||
if (pAxis->m_bHasReference)
|
||||
{
|
||||
// call REF - find reference
|
||||
sprintf(cmd,"REF %s", pAxis->m_szAxisName);
|
||||
}
|
||||
else if (pAxis->m_bHasLimitSwitches)
|
||||
{
|
||||
if (forwards)
|
||||
{
|
||||
// call MPL - find positive limit switch
|
||||
sprintf(cmd,"MPL %s", pAxis->m_szAxisName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// call MNL - find negative limit switch
|
||||
sprintf(cmd,"MNL %s", pAxis->m_szAxisName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR,
|
||||
"PIC702Controller::referenceVelCts() failed - axis has no reference/limit switch\n");
|
||||
epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize,
|
||||
"PIC702Controller::referenceVelCts() failed - axis has no reference/limit switch\n");
|
||||
return asynError;
|
||||
}
|
||||
status = sendOnly(cmd);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR,
|
||||
"PIC702Controller::referenceVelCts() failed\n");
|
||||
return status;
|
||||
}
|
||||
pAxis->m_isHoming = 1;
|
||||
epicsTimeGetCurrent(&m_timeREFstarted);
|
||||
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* PIC702Controller.h
|
||||
*
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#ifndef PIC702CONTROLLER_H_
|
||||
#define PIC702CONTROLLER_H_
|
||||
|
||||
#include "PIGCSMotorController.h"
|
||||
#include <epicsTime.h>
|
||||
|
||||
/**
|
||||
* class representing PI C-702.
|
||||
*
|
||||
*/
|
||||
class PIC702Controller : public PIGCSMotorController
|
||||
{
|
||||
public:
|
||||
PIC702Controller(asynUser* pCom, const char* szIDN)
|
||||
: PIGCSMotorController(pCom, szIDN)
|
||||
{
|
||||
}
|
||||
~PIC702Controller() {}
|
||||
|
||||
virtual asynStatus getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl);
|
||||
virtual asynStatus getMaxAcceleration( PIasynAxis* pAxis );
|
||||
virtual asynStatus hasReferenceSensor(PIasynAxis* pAxis);
|
||||
virtual asynStatus getReferencedState(PIasynAxis* axis);
|
||||
virtual asynStatus referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards);
|
||||
|
||||
virtual bool IsGCS2() { return false; }
|
||||
|
||||
protected:
|
||||
virtual asynStatus findConnectedAxes();
|
||||
enum
|
||||
{
|
||||
PI_PARA_C702_REFERENCED = 0x000001CUL
|
||||
};
|
||||
|
||||
private:
|
||||
epicsTimeStamp m_timeREFstarted;
|
||||
};
|
||||
|
||||
#endif /* PIC702CONTROLLER_H_ */
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* PIGCSPiezoController
|
||||
*
|
||||
* Created on: 15.12.2010
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#include "PIE517Controller.h"
|
||||
#include "PIasynAxis.h"
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#undef asynPrint
|
||||
#define asynPrint(user,reason,format...) 0
|
||||
|
||||
|
||||
asynStatus PIE517Controller::init()
|
||||
{
|
||||
asynStatus status;
|
||||
status = PIGCSPiezoController::init();
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// all output channels need to be set "online" before
|
||||
// any commands are accepted over the interface.
|
||||
status = getNrOutputChannels();
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
for (int ch=1; ch<=m_nrOutputChannels; ch++)
|
||||
{
|
||||
status = setOnline(ch, 1);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIE517Controller::setOnline(int channel, int onlineState)
|
||||
{
|
||||
char cmd[100];
|
||||
sprintf(cmd, "ONL %d %d", channel, onlineState);
|
||||
asynStatus status = sendOnly(cmd);
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIE517Controller::getNrOutputChannels()
|
||||
{
|
||||
char buf[255];
|
||||
asynStatus status = sendAndReceive("TPC?", buf, 99);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
m_nrOutputChannels = atoi(buf);
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
asynStatus PIE517Controller::initAxis(PIasynAxis* pAxis)
|
||||
{
|
||||
pAxis->m_movingStateMask = pow(2.0, pAxis->getAxisNo());
|
||||
|
||||
return setServo(pAxis, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* PIGCScontroller.h
|
||||
*
|
||||
* Created on: 15.12.2010
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#ifndef PIE517CONTROLLER_H_
|
||||
#define PIE517CONTROLLER_H_
|
||||
|
||||
#include "PIGCSPiezoController.h"
|
||||
|
||||
/**
|
||||
* class representing PI E-517 and E-545 controllers.
|
||||
*
|
||||
* Basically these controllers have the same functionality as a
|
||||
* digital piezo controller. Specialties are "velocity control" mode
|
||||
* and the "online" state. Output channels must be set to "online" mode
|
||||
* before commands are accepted over the interface. This is done in
|
||||
* init()
|
||||
*/
|
||||
class PIE517Controller : public PIGCSPiezoController
|
||||
{
|
||||
public:
|
||||
PIE517Controller(asynUser* pCom, const char* szIDN)
|
||||
: PIGCSPiezoController(pCom, szIDN)
|
||||
{
|
||||
}
|
||||
~PIE517Controller() {}
|
||||
|
||||
virtual asynStatus init(void);
|
||||
virtual asynStatus initAxis(PIasynAxis* pAxis);
|
||||
|
||||
private:
|
||||
asynStatus setOnline(int outputChannel, int onlineState);
|
||||
asynStatus getNrOutputChannels();
|
||||
|
||||
int m_nrOutputChannels;
|
||||
|
||||
};
|
||||
|
||||
#endif /* PIE517CONTROLLER_H_ */
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* PIE755Controller
|
||||
*
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#include "PIE755Controller.h"
|
||||
#include "PIasynAxis.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#undef asynPrint
|
||||
#define asynPrint(user,reason,format...) 0
|
||||
|
||||
|
||||
asynStatus PIE755Controller::getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl)
|
||||
{
|
||||
int busy;
|
||||
asynStatus status = getBusy(pAxis, busy);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
negLimit = 0;
|
||||
posLimit = 0;
|
||||
homing = busy;
|
||||
if (busy)
|
||||
{
|
||||
moving = busy;
|
||||
return status;
|
||||
}
|
||||
|
||||
status = getMoving(pAxis, moving);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* PIE755Controller.h
|
||||
*
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#ifndef PIE755CONTROLLER_H_
|
||||
#define PIE755CONTROLLER_H_
|
||||
|
||||
#include "PIGCSMotorController.h"
|
||||
|
||||
/**
|
||||
* class representing PI E-755.
|
||||
*
|
||||
* These controllers share most of the parameters with digital piezo controllers.
|
||||
* Encoders for Nexline stages are often only incremental, so they need to be homed.
|
||||
* Homing works with "hard stops" and "Limit switches".
|
||||
* From an EPICS point of view this behaves more like a motor than a piezo controller.
|
||||
*/
|
||||
class PIE755Controller : public PIGCSMotorController
|
||||
{
|
||||
public:
|
||||
PIE755Controller(asynUser* pCom, const char* szIDN)
|
||||
: PIGCSMotorController(pCom, szIDN)
|
||||
{
|
||||
}
|
||||
~PIE755Controller() {}
|
||||
|
||||
virtual asynStatus getResolution(PIasynAxis* pAxis, double& resolution )
|
||||
{
|
||||
return PIGCSController::getResolution(pAxis, resolution);
|
||||
}
|
||||
virtual asynStatus setAccelerationCts( PIasynAxis* pAxis, double acceleration) { return asynSuccess; }
|
||||
virtual asynStatus setAcceleration( PIasynAxis* pAxis, double acceleration) { return asynSuccess; }
|
||||
virtual asynStatus getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl);
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif /* PIE755CONTROLLER_H_ */
|
||||
@@ -0,0 +1,811 @@
|
||||
/*
|
||||
* PIGCSController.cpp
|
||||
*
|
||||
* Created on: 15.12.2010
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#include <asynOctetSyncIO.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "PIGCSController.h"
|
||||
#include "PIasynAxis.h"
|
||||
#include "PIGCSMotorController.h"
|
||||
#include "PIGCSPiezoController.h"
|
||||
#include "PIE517Controller.h"
|
||||
#include "PIE755Controller.h"
|
||||
#include "PIHexapodController.h"
|
||||
#include "PIC702Controller.h"
|
||||
|
||||
|
||||
//#undef asynPrint
|
||||
//#define asynPrint(user,reason,format...) 0
|
||||
|
||||
|
||||
extern "C" {
|
||||
int TranslatePIError(const int error, char* szBuffer, const int maxlen);
|
||||
}
|
||||
|
||||
double PIGCSController::TIMEOUT = 5.0;
|
||||
|
||||
/**
|
||||
* create instance of GCS controller depending on identification (\a szIDN)
|
||||
*/
|
||||
PIGCSController* PIGCSController::CreateGCSController(asynUser* pInterface, const char* szIDN)
|
||||
{
|
||||
if ( strstr(szIDN, "C-663") != NULL
|
||||
|| strstr(szIDN, "C-863") != NULL
|
||||
|| strstr(szIDN, "C-867") != NULL
|
||||
)
|
||||
{
|
||||
return new PIGCSMotorController(pInterface, szIDN);
|
||||
}
|
||||
else if ( strstr(szIDN, "E-517") != NULL)
|
||||
{
|
||||
return new PIE517Controller(pInterface, szIDN);
|
||||
}
|
||||
else if ( strstr(szIDN, "E-755") != NULL)
|
||||
{
|
||||
return new PIE755Controller(pInterface, szIDN);
|
||||
}
|
||||
else if ( strstr(szIDN, "C-702") != NULL)
|
||||
{
|
||||
return new PIC702Controller(pInterface, szIDN);
|
||||
}
|
||||
else if ( strstr(szIDN, "HEXAPOD") != NULL
|
||||
|| strstr(szIDN, "F-HEX") != NULL
|
||||
|| strstr(szIDN, "F-206") != NULL
|
||||
|| strstr(szIDN, "M-8") != NULL
|
||||
|| strstr(szIDN, "C-887") != NULL
|
||||
)
|
||||
{
|
||||
return new PIHexapodController(pInterface, szIDN);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::sendOnly(asynUser* pInterface, const char *outputBuff, asynUser* logSink)
|
||||
{
|
||||
size_t nRequested=strlen(outputBuff);
|
||||
size_t nActual;
|
||||
asynStatus status;
|
||||
|
||||
asynPrint(logSink, ASYN_TRACEIO_DRIVER,
|
||||
"PIGCSController::sendOnly() sending \"%s\"\n", outputBuff);
|
||||
//printf("PIGCSController::sendOnly() sending \"%s\"\n", outputBuff);
|
||||
|
||||
status = pasynOctetSyncIO->write(pInterface, outputBuff,
|
||||
nRequested, TIMEOUT, &nActual);
|
||||
if (nActual != nRequested)
|
||||
status = asynError;
|
||||
status = pasynOctetSyncIO->write(pInterface, "\n",
|
||||
1, TIMEOUT, &nActual);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
asynPrint(logSink, ASYN_TRACE_ERROR|ASYN_TRACEIO_DRIVER,
|
||||
"PIGCSController:sendOnly: error sending command %s, sent=%d, status=%d\n",
|
||||
outputBuff, nActual, status);
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::sendOnly(asynUser* pInterface, char c, asynUser* logSink)
|
||||
{
|
||||
size_t nActual;
|
||||
asynStatus status;
|
||||
|
||||
asynPrint(logSink, ASYN_TRACEIO_DRIVER,
|
||||
"PIGCSController::sendOnly() sending \"#%d\"\n", int(c));
|
||||
//printf("PIGCSController::sendOnly() sending \"#%d\"\n", int(c));
|
||||
|
||||
status = pasynOctetSyncIO->write(pInterface, &c,
|
||||
1, TIMEOUT, &nActual);
|
||||
if (nActual != 1)
|
||||
status = asynError;
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
asynPrint(logSink, ASYN_TRACE_ERROR|ASYN_TRACEIO_DRIVER,
|
||||
"PIGCSController:sendOnly: error sending command %d, sent=%d, status=%d\n",
|
||||
int(c), nActual, status);
|
||||
//printf("PIGCSController::sendOnly() sending \"#%d\"\n", int(c));
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
|
||||
asynStatus PIGCSController::sendAndReceive(asynUser* pInterface, const char *outputBuff, char *inputBuff, int inputSize, asynUser* logSink)
|
||||
{
|
||||
size_t nWriteRequested=strlen(outputBuff);
|
||||
size_t nWrite, nRead;
|
||||
int eomReason;
|
||||
asynStatus status;
|
||||
size_t pos = 0;
|
||||
asynPrint(logSink, ASYN_TRACEIO_DRIVER,
|
||||
"PIGCSController::sendAndReceive() sending \"%s\"\n", outputBuff);
|
||||
// //printf("PIGCSController::sendAndReceive() sending \"%s\"\n", outputBuff);
|
||||
|
||||
status = pasynOctetSyncIO->write(pInterface, outputBuff,
|
||||
nWriteRequested, TIMEOUT, &nWrite);
|
||||
if (nWrite != nWriteRequested)
|
||||
{
|
||||
asynPrint(logSink, ASYN_TRACE_ERROR|ASYN_TRACEIO_DRIVER,
|
||||
"PIGCSController:sendAndReceive error calling write, output=%s status=%d, error=%s\n",
|
||||
outputBuff, status, pInterface->errorMessage);
|
||||
return asynError;
|
||||
}
|
||||
|
||||
status = pasynOctetSyncIO->writeRead(pInterface,
|
||||
"\n", 1,
|
||||
inputBuff, inputSize,
|
||||
TIMEOUT, &nWrite, &nRead, &eomReason);
|
||||
if (nWrite != 1)
|
||||
{
|
||||
asynPrint(logSink, ASYN_TRACE_ERROR|ASYN_TRACEIO_DRIVER,
|
||||
"PIGCSController:sendAndReceive error calling write, output=%s status=%d, error=%s\n",
|
||||
outputBuff, status, pInterface->errorMessage);
|
||||
return asynError;
|
||||
}
|
||||
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
asynPrint(logSink, ASYN_TRACE_ERROR|ASYN_TRACEIO_DRIVER,
|
||||
"PIGCSController:sendAndReceive error calling writeRead, output=%s status=%d, error=%s\n",
|
||||
outputBuff, status, pInterface->errorMessage);
|
||||
}
|
||||
while(inputBuff[strlen(inputBuff)-1] == ' ')
|
||||
{
|
||||
inputBuff[strlen(inputBuff)] = '\n';
|
||||
pos += nRead + 1;
|
||||
status = pasynOctetSyncIO->read(logSink,
|
||||
inputBuff+pos, inputSize-pos,
|
||||
TIMEOUT, &nRead, &eomReason);
|
||||
|
||||
}
|
||||
asynPrint(logSink, ASYN_TRACEIO_DRIVER,
|
||||
"PIGCSController::sendAndReceive() received \"%s\"\n", inputBuff);
|
||||
// //printf("PIGCSController::sendAndReceive() received \"%s\"\n", inputBuff);
|
||||
|
||||
return(status);
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::sendOnly(const char *outputBuff)
|
||||
{
|
||||
asynUser* logSink = m_pCurrentLogSink;
|
||||
if (NULL == logSink)
|
||||
logSink = m_pInterface;
|
||||
m_interfaceMutex.lock();
|
||||
asynStatus status = sendOnly(m_pInterface, outputBuff, logSink);
|
||||
m_interfaceMutex.unlock();
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::sendOnly(char c)
|
||||
{
|
||||
asynUser* logSink = m_pCurrentLogSink;
|
||||
if (NULL == logSink)
|
||||
logSink = m_pInterface;
|
||||
m_interfaceMutex.lock();
|
||||
asynStatus status = sendOnly(m_pInterface, c, logSink);
|
||||
m_interfaceMutex.unlock();
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::sendAndReceive(char c, char *inputBuff, int inputSize)
|
||||
{
|
||||
asynUser* logSink = m_pCurrentLogSink;
|
||||
if (NULL == logSink)
|
||||
logSink = m_pInterface;
|
||||
m_interfaceMutex.lock();
|
||||
asynStatus status = sendAndReceive(m_pInterface, c, inputBuff, inputSize, logSink);
|
||||
m_interfaceMutex.unlock();
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::sendAndReceive(const char* output, char *inputBuff, int inputSize)
|
||||
{
|
||||
asynUser* logSink = m_pCurrentLogSink;
|
||||
if (NULL == logSink)
|
||||
logSink = m_pInterface;
|
||||
m_interfaceMutex.lock();
|
||||
asynStatus status = sendAndReceive(m_pInterface, output, inputBuff, inputSize, logSink);
|
||||
m_interfaceMutex.unlock();
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::sendAndReceive(asynUser* pInterface, char c, char *inputBuff, int inputSize, asynUser* logSink)
|
||||
{
|
||||
size_t nWrite, nRead;
|
||||
int eomReason;
|
||||
asynStatus status;
|
||||
size_t pos = 0;
|
||||
|
||||
asynPrint(logSink, ASYN_TRACEIO_DRIVER,
|
||||
"PIGCSController::sendAndReceive() sending \"#%d\"\n", int(c));
|
||||
//printf("PIGCSController::sendAndReceive() sending \"#%d\"\n", int(c));
|
||||
status = pasynOctetSyncIO->writeRead(pInterface,
|
||||
&c, 1,
|
||||
inputBuff, inputSize,
|
||||
TIMEOUT, &nWrite, &nRead, &eomReason);
|
||||
if (nWrite != 1)
|
||||
status = asynError;
|
||||
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
asynPrint(logSink, ASYN_TRACE_ERROR|ASYN_TRACEIO_DRIVER,
|
||||
"PIGCSController::sendAndReceive error calling writeRead, output=%d status=%d, error=%s\n",
|
||||
int(c), status, pInterface->errorMessage);
|
||||
//printf("PIGCSController::sendAndReceive error calling writeRead, output=%d status=%d, error=%s\n", int(c), status, pInterface->errorMessage);
|
||||
}
|
||||
|
||||
while(inputBuff[strlen(inputBuff)-1] == ' ')
|
||||
{
|
||||
pos += nRead;
|
||||
status = pasynOctetSyncIO->writeRead(logSink,
|
||||
&c, 1,
|
||||
inputBuff+pos, inputSize-pos,
|
||||
TIMEOUT, &nWrite, &nRead, &eomReason);
|
||||
//printf("PIGCSController::sendAndReceive(char) in while loop. inputBuff: \"%s\"\n", inputBuff);
|
||||
}
|
||||
asynPrint(logSink, ASYN_TRACEIO_DRIVER,
|
||||
"PIGCSController::sendAndReceive() received \"%s\"\n", inputBuff);
|
||||
//printf("PIGCSController::sendAndReceive() received \"%s\" - (0x%02X)\n", inputBuff, int(inputBuff[0]));
|
||||
|
||||
return(status);
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::setVelocityCts( PIasynAxis* pAxis, double velocity )
|
||||
{
|
||||
char cmd[100];
|
||||
velocity = fabs(velocity) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator;
|
||||
sprintf(cmd,"VEL %s %f", pAxis->m_szAxisName, velocity);
|
||||
asynStatus status = sendOnly(cmd);
|
||||
if (asynSuccess == status)
|
||||
{
|
||||
pAxis->m_velocity = velocity;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::moveCts( PIasynAxis** pAxesArray, int* pTargetCtsArray, int numAxes)
|
||||
{
|
||||
//TODO: "Use MVE or set vel/acc so axes reach target at the same time""
|
||||
|
||||
|
||||
asynStatus status;
|
||||
char cmd[1000] = "MOV";
|
||||
char subCmd[100];
|
||||
for (int axis = 0; axis <numAxes; axis++)
|
||||
{
|
||||
PIasynAxis* pAxis = pAxesArray[axis];
|
||||
double target = double(pTargetCtsArray[axis]) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator;
|
||||
sprintf(subCmd," %s %f", pAxis->m_szAxisName, target);
|
||||
strcat(cmd, subCmd);
|
||||
pAxis->m_lastDirection = (pTargetCtsArray[axis] > pAxis->m_positionCts) ? 1 : 0;
|
||||
}
|
||||
status = sendOnly(cmd);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
int errorCode = getGCSError();
|
||||
if (errorCode == 0)
|
||||
return asynSuccess;
|
||||
|
||||
asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
|
||||
"PIGCSController::moveCts(array) failed, GCS error %d\n", errorCode);
|
||||
return asynError;
|
||||
}
|
||||
|
||||
|
||||
|
||||
asynStatus PIGCSController::moveCts( PIasynAxis* pAxis, int targetCts )
|
||||
{
|
||||
asynStatus status;
|
||||
char cmd[100];
|
||||
double target = double(targetCts) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator;
|
||||
asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
|
||||
"PIGCSController::moveCts(, %d) \n", targetCts);
|
||||
return move(pAxis, target);
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::move( PIasynAxis* pAxis, double target )
|
||||
{
|
||||
asynStatus status;
|
||||
char cmd[100];
|
||||
sprintf(cmd,"MOV %s %f", pAxis->m_szAxisName, target);
|
||||
status = sendOnly(cmd);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
|
||||
"PIGCSController::move() sent \"%s\"\n", cmd);
|
||||
pAxis->m_lastDirection = (target > pAxis->m_position) ? 1 : 0;
|
||||
int errorCode = getGCSError();
|
||||
if (errorCode == 0)
|
||||
return asynSuccess;
|
||||
|
||||
asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
|
||||
"PIGCSController::move() failed, GCS error %d\n", errorCode);
|
||||
return asynError;
|
||||
}
|
||||
|
||||
int PIGCSController::getGCSError()
|
||||
{
|
||||
char buf[256];
|
||||
asynStatus status = sendAndReceive("ERR?", buf, 255);
|
||||
if (asynTimeout == status)
|
||||
{
|
||||
return COM_TIMEOUT;
|
||||
}
|
||||
else if (asynSuccess != status)
|
||||
{
|
||||
return COM_ERROR;
|
||||
}
|
||||
int errorCode = atoi(buf);
|
||||
if (0 != errorCode)
|
||||
{
|
||||
m_LastError = errorCode;
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"PIGCSController::getGCSError() GCS error code = %d\n",
|
||||
errorCode);
|
||||
char szErrorMsg[1024];
|
||||
if (TranslatePIError(errorCode, szErrorMsg, 1024))
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"PIGCSController::getGCSError() GCS error, %s\n",
|
||||
szErrorMsg);
|
||||
|
||||
}
|
||||
}
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::haltAxis(PIasynAxis* pAxis)
|
||||
{
|
||||
char cmd[100];
|
||||
sprintf(cmd,"HLT %s", pAxis->m_szAxisName);
|
||||
asynStatus status = sendOnly(cmd);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
int err = getGCSError();
|
||||
// controller will set error code to PI_CNTR_STOP (10)
|
||||
if (err != PI_CNTR_STOP)
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
|
||||
"PIGCSController::haltAxis() failed, GCS error %d", err);
|
||||
return asynError;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* get position of axis in physical units (EGU) as defined on the controller
|
||||
*/
|
||||
asynStatus PIGCSController::getAxisPosition(PIasynAxis* pAxis, double& position)
|
||||
{
|
||||
char cmd[100];
|
||||
char buf[255];
|
||||
sprintf(cmd, "POS? %s", pAxis->m_szAxisName);
|
||||
asynStatus status = sendAndReceive(cmd, buf, 99);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
if (!getValue(buf, position))
|
||||
{
|
||||
status = asynError;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* get velocity of axis in physical units (EGU) as defined on the controller
|
||||
* and set PIasynAxis::m_velocity
|
||||
*/
|
||||
asynStatus PIGCSController::getAxisVelocity(PIasynAxis* pAxis)
|
||||
{
|
||||
char cmd[100];
|
||||
char buf[255];
|
||||
sprintf(cmd, "VEL? %s", pAxis->m_szAxisName);
|
||||
asynStatus status = sendAndReceive(cmd, buf, 99);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
if (!getValue(buf, pAxis->m_velocity))
|
||||
{
|
||||
status = asynError;
|
||||
}
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Find travel range for axis.
|
||||
*/
|
||||
asynStatus PIGCSController::getTravelLimits(PIasynAxis* pAxis, double& negLimit, double& posLimit)
|
||||
{
|
||||
char cmd[100];
|
||||
char buf[255];
|
||||
sprintf(cmd, "TMN? %s", pAxis->m_szAxisName);
|
||||
asynStatus status = sendAndReceive(cmd, buf, 99);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
if (!getValue(buf, negLimit))
|
||||
{
|
||||
return asynError;
|
||||
}
|
||||
sprintf(cmd, "TMX? %s", pAxis->m_szAxisName);
|
||||
status = sendAndReceive(cmd, buf, 99);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
if (!getValue(buf, posLimit))
|
||||
{
|
||||
return asynError;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::hasLimitSwitches(PIasynAxis* pAxis)
|
||||
{
|
||||
char cmd[100];
|
||||
char buf[255];
|
||||
sprintf(cmd, "LIM? %s", pAxis->m_szAxisName);
|
||||
asynStatus status = sendAndReceive(cmd, buf, 99);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
if (!getValue(buf, pAxis->m_bHasLimitSwitches))
|
||||
{
|
||||
return asynError;
|
||||
}
|
||||
if (!pAxis->m_bHasLimitSwitches)
|
||||
{
|
||||
sprintf(cmd, "HAR? %s", pAxis->m_szAxisName);
|
||||
asynStatus status = sendAndReceive(cmd, buf, 99);
|
||||
if (status == asynSuccess)
|
||||
{
|
||||
if (!getValue(buf, pAxis->m_bHasLimitSwitches))
|
||||
{
|
||||
return asynError;
|
||||
}
|
||||
}
|
||||
else if (status == asynTimeout)
|
||||
{
|
||||
int err = getGCSError();
|
||||
if (err == PI_CNTR_UNKNOWN_COMMAND)
|
||||
{
|
||||
// "HAR?" not known
|
||||
pAxis->m_bHasLimitSwitches = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
|
||||
"PIGCSController::hasLimitSwitches() axis has %slimit switches\n",
|
||||
pAxis->m_bHasLimitSwitches?"":"no ");
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::hasReferenceSensor(PIasynAxis* pAxis)
|
||||
{
|
||||
char cmd[100];
|
||||
char buf[255];
|
||||
sprintf(cmd, "TRS? %s", pAxis->m_szAxisName);
|
||||
asynStatus status = sendAndReceive(cmd, buf, 99);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!getValue(buf, pAxis->m_bHasReference))
|
||||
{
|
||||
return asynError;
|
||||
}
|
||||
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
|
||||
"PIGCSController::hasReferenceSwitch() axis has %sreference sensor\n",
|
||||
pAxis->m_bHasReference?"":"no ");
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* get position of axis in counts as used in EPICS.
|
||||
* getAxisPosition() is called and position is covnerted to counts using the
|
||||
* counts-per-unit (CPU) fraction of the axis.
|
||||
*/
|
||||
asynStatus PIGCSController::getAxisPositionCts(PIasynAxis* pAxis)
|
||||
{
|
||||
double pos;
|
||||
asynStatus status = getAxisPosition(pAxis, pos);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
pAxis->m_position = pos;
|
||||
if (pAxis->m_CPUdenominator==0 || pAxis->m_CPUnumerator==0)
|
||||
{
|
||||
pAxis->m_positionCts = pos;
|
||||
return status;
|
||||
}
|
||||
|
||||
pAxis->m_positionCts = int( (pos * double(pAxis->m_CPUnumerator) / double(pAxis->m_CPUdenominator))+0.5);
|
||||
if (m_pCurrentLogSink != NULL)
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
|
||||
"PIGCSController::getAxisPositionCts() pos:%d\n",
|
||||
pAxis->m_positionCts);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
//void PIGCSController::calcAxisPositionCts();
|
||||
|
||||
asynStatus PIGCSController::setServo(PIasynAxis* pAxis, int servoState)
|
||||
{
|
||||
char cmd[100];
|
||||
sprintf(cmd, "SVO %s %d", pAxis->m_szAxisName, servoState);
|
||||
asynStatus status = sendOnly(cmd);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
int err = getGCSError();
|
||||
if (COM_NO_ERROR == err)
|
||||
{
|
||||
pAxis->m_bServoControl = (servoState == 1);
|
||||
if (pAxis->m_bProblem && pAxis->m_bServoControl)
|
||||
{
|
||||
pAxis->m_bProblem = false;
|
||||
}
|
||||
return asynSuccess;
|
||||
}
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"Could not set servo state!\n");
|
||||
return asynError;
|
||||
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::getMoving(PIasynAxis* pAxis, int& moving)
|
||||
{
|
||||
char buf[255];
|
||||
asynStatus status = sendAndReceive(char(5), buf, 99);;
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
//printf("PIGCSController::getMoving() failed, status %d", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
char* pStr;
|
||||
long movingState = strtol(buf, &pStr, 16);
|
||||
moving = (movingState & pAxis->m_movingStateMask) != 0 ? 1 : 0;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::getBusy(PIasynAxis* pAxis, int& busy)
|
||||
{
|
||||
char buf[255];
|
||||
asynStatus status = sendAndReceive(char(7), buf, 99);;
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
unsigned char c = (unsigned char)buf[0];
|
||||
busy = (c==0xB0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::setGCSParameter(PIasynAxis* pAxis, unsigned int paramID, double value)
|
||||
{
|
||||
char cmd[100];
|
||||
sprintf(cmd, "SPA %s %d %.12g", pAxis->m_szAxisName, paramID, value);
|
||||
asynStatus status = sendOnly(cmd);
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::getGCSParameter(PIasynAxis* pAxis, unsigned int paramID, double& value)
|
||||
{
|
||||
char cmd[100];
|
||||
char buf[255];
|
||||
sprintf(cmd, "SPA? %s %d", pAxis->m_szAxisName, paramID);
|
||||
asynStatus status = sendAndReceive(cmd, buf, 99);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!getValue(buf, value))
|
||||
{
|
||||
return asynError;
|
||||
}
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
PIGCSController::PIGCSController(asynUser* pCom, const char* szIDN)
|
||||
: m_pCurrentLogSink(NULL)
|
||||
, m_bAnyAxisMoving(false)
|
||||
, m_pInterface(pCom)
|
||||
, m_nrFoundAxes(0)
|
||||
, m_LastError(0)
|
||||
{
|
||||
strncpy(szIdentification, szIDN, 199);
|
||||
}
|
||||
|
||||
PIGCSController::~PIGCSController()
|
||||
{
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::initAxis(PIasynAxis* pAxis)
|
||||
{
|
||||
// read stage name - to have it in logfile and find
|
||||
// problems because of mis/non-configured controllers
|
||||
char cmd[100];
|
||||
char buf[255];
|
||||
sprintf(cmd, "CST? %s", pAxis->m_szAxisName);
|
||||
asynStatus status = sendAndReceive(cmd, buf, 99);;
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
if (NULL != m_pCurrentLogSink)
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
|
||||
"PIGCSController::initAxis() stage configuration: %s\n", buf);
|
||||
}
|
||||
pAxis->m_movingStateMask = pow(2.0, pAxis->getAxisNo());
|
||||
|
||||
return setServo(pAxis, 1);
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::init(void)
|
||||
{
|
||||
asynStatus status;
|
||||
status = findConnectedAxes();
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::findConnectedAxes()
|
||||
{
|
||||
m_nrFoundAxes = 0;
|
||||
for (size_t i=0; i<MAX_NR_AXES; i++)
|
||||
{
|
||||
m_axesIDs[i] = NULL;
|
||||
}
|
||||
asynStatus status = PIGCSController::sendAndReceive("SAI?", m_allAxesIDs, 255);
|
||||
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
char* szAxis = strtok(m_allAxesIDs, "\n");
|
||||
while (szAxis != NULL)
|
||||
{
|
||||
int i=strlen(szAxis)-1;
|
||||
while (szAxis[i] == ' ')
|
||||
{
|
||||
szAxis[i] = '\0';
|
||||
i--;
|
||||
}
|
||||
if (MAX_NR_AXES <= m_nrFoundAxes)
|
||||
{
|
||||
return asynError;
|
||||
}
|
||||
m_axesIDs[m_nrFoundAxes] = szAxis;
|
||||
m_nrFoundAxes++;
|
||||
szAxis = strtok(NULL, "\n");
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::getReferencedState(PIasynAxis* pAxis)
|
||||
{
|
||||
char cmd[100];
|
||||
char buf[255];
|
||||
sprintf(cmd, "FRF? %s", pAxis->m_szAxisName);
|
||||
asynStatus status = sendAndReceive(cmd, buf, 99);;
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
if (getValue(buf, pAxis->m_homed))
|
||||
{
|
||||
return asynError;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::getResolution(PIasynAxis* pAxis, double& resolution )
|
||||
{
|
||||
resolution = 0.0001;
|
||||
pAxis->m_CPUnumerator = 10000;
|
||||
pAxis->m_CPUdenominator = 1;
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::SetPivotX(double value)
|
||||
{
|
||||
if (NULL != m_pCurrentLogSink)
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
|
||||
"PIGCSController::SetPivotX() ignored");
|
||||
}
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::SetPivotY(double value)
|
||||
{
|
||||
if (NULL != m_pCurrentLogSink)
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
|
||||
"PIGCSController::SetPivotY() ignored");
|
||||
}
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
asynStatus PIGCSController::SetPivotZ(double value)
|
||||
{
|
||||
if (NULL != m_pCurrentLogSink)
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
|
||||
"PIGCSController::SetPivotZ() ignored");
|
||||
}
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
bool PIGCSController::getValue(const char* szMsg, double& value)
|
||||
{
|
||||
const char* p = strstr(szMsg, "=");
|
||||
if (p==NULL || *p == '\0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
value = atof(p+1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PIGCSController::getValue(const char* szMsg, int& value)
|
||||
{
|
||||
const char* p = strstr(szMsg, "=");
|
||||
if (p==NULL || *p == '\0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
value = atoi(p+1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PIGCSController::getValue(const char* szMsg, bool& value)
|
||||
{
|
||||
const char* p = strstr(szMsg, "=");
|
||||
if (p==NULL || *p == '\0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int ivalue = atoi(p+1);
|
||||
value = (ivalue =! 0);
|
||||
return true;
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* PIGCScontroller.h
|
||||
*
|
||||
* Created on: 15.12.2010
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#ifndef PIGCSCONTROLLER_H_
|
||||
#define PIGCSCONTROLLER_H_
|
||||
|
||||
#include <asynDriver.h>
|
||||
#include <string.h>
|
||||
#include <epicsMutex.h>
|
||||
#include "picontrollererrors.h"
|
||||
|
||||
|
||||
class PIasynAxis;
|
||||
class asynMotorAxis;
|
||||
|
||||
/**
|
||||
* Base class for all PI GCS(2) controllers.
|
||||
*
|
||||
* Most functions will be implemented here, since for basic functionality
|
||||
* GCS commands are always the same.
|
||||
*/
|
||||
class PIGCSController
|
||||
{
|
||||
public:
|
||||
PIGCSController(asynUser* pCom, const char* szIDN);
|
||||
virtual ~PIGCSController();
|
||||
|
||||
static PIGCSController* CreateGCSController(asynUser* pCom, const char* szIDN);
|
||||
|
||||
virtual asynStatus init(void);
|
||||
virtual asynStatus initAxis(PIasynAxis* pAxis);
|
||||
|
||||
static asynStatus sendOnly(asynUser* pInterface, char c, asynUser* logSink);
|
||||
static asynStatus sendOnly(asynUser* pInterface, const char *outputBuff, asynUser* logSink);
|
||||
static asynStatus sendAndReceive(asynUser* pInterface, const char *outputBuff, char *inputBuff, int inputSize, asynUser* logSink);
|
||||
static asynStatus sendAndReceive(asynUser* pInterface, char c, char *inputBuff, int inputSize, asynUser* logSink);
|
||||
|
||||
bool getValue(const char* szMsg, double& value);
|
||||
bool getValue(const char* szMsg, int& value);
|
||||
bool getValue(const char* szMsg, bool& value);
|
||||
|
||||
virtual asynStatus setVelocityCts( PIasynAxis* pAxis, double velocity );
|
||||
virtual asynStatus setAccelerationCts( PIasynAxis* pAxis, double acceleration) { return asynSuccess; }
|
||||
virtual asynStatus setAcceleration( PIasynAxis* pAxis, double acceleration) { return asynSuccess; }
|
||||
virtual asynStatus move( PIasynAxis* pAxis, double target);
|
||||
virtual asynStatus moveCts( PIasynAxis* pAxis, int target);
|
||||
virtual asynStatus moveCts( PIasynAxis** pAxesArray, int* pTargetCtsArray, int numAxes);
|
||||
virtual asynStatus referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards) { return asynSuccess; }
|
||||
virtual asynStatus haltAxis(PIasynAxis* pAxis);
|
||||
|
||||
virtual asynStatus getAxisPosition(PIasynAxis* pAxis, double& position);
|
||||
virtual asynStatus getAxisVelocity(PIasynAxis* pAxis);
|
||||
virtual asynStatus getAxisPositionCts(PIasynAxis* pAxis);
|
||||
virtual asynStatus setServo(PIasynAxis* pAxis, int servoState);
|
||||
virtual asynStatus getResolution(PIasynAxis* pAxis, double& resolution );
|
||||
virtual asynStatus getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl) = 0;
|
||||
virtual asynStatus getGlobalState( asynMotorAxis** Axes, int numAxes ) { return asynSuccess; }
|
||||
virtual asynStatus getMoving(PIasynAxis* pAxis, int& homing);
|
||||
virtual asynStatus getBusy(PIasynAxis* pAxis, int& busy);
|
||||
virtual asynStatus getTravelLimits(PIasynAxis* pAxis, double& negLimit, double& posLimit);
|
||||
virtual asynStatus hasLimitSwitches(PIasynAxis* pAxis);
|
||||
virtual asynStatus hasReferenceSensor(PIasynAxis* pAxis);
|
||||
virtual asynStatus getReferencedState(PIasynAxis* axis);
|
||||
|
||||
virtual asynStatus SetPivotX(double value);
|
||||
virtual asynStatus SetPivotY(double value);
|
||||
virtual asynStatus SetPivotZ(double value);
|
||||
|
||||
virtual double GetPivotX() { return 0.0; }
|
||||
virtual double GetPivotY() { return 0.0; }
|
||||
virtual double GetPivotZ() { return 0.0; }
|
||||
|
||||
virtual bool AcceptsNewTarget() { return true; }
|
||||
virtual bool CanCommunicateWhileHoming() { return true; }
|
||||
|
||||
asynStatus sendOnly(const char *outputBuff);
|
||||
asynStatus sendOnly(char c);
|
||||
asynStatus sendAndReceive(const char *outputBuff, char *inputBuff, int inputSize);
|
||||
asynStatus sendAndReceive(char c, char *inputBuff, int inputSize);
|
||||
|
||||
const char* getAxesID(size_t axisIdx) { return m_axesIDs[axisIdx]; }
|
||||
size_t getNrFoundAxes() { return m_nrFoundAxes; }
|
||||
|
||||
virtual bool IsGCS2() { return true; }
|
||||
|
||||
int getGCSError();
|
||||
|
||||
int GetLastError() { return m_LastError; }
|
||||
|
||||
asynUser* m_pCurrentLogSink;
|
||||
static const size_t MAX_NR_AXES = 64;
|
||||
bool m_bAnyAxisMoving;
|
||||
protected:
|
||||
asynStatus setGCSParameter(PIasynAxis* pAxis, unsigned int paramID, double value);
|
||||
asynStatus getGCSParameter(PIasynAxis* pAxis, unsigned int paramID, double& value);
|
||||
|
||||
virtual asynStatus findConnectedAxes();
|
||||
|
||||
asynUser* m_pInterface;
|
||||
epicsMutex m_interfaceMutex;
|
||||
static double TIMEOUT;
|
||||
char szIdentification[200];
|
||||
int m_nrAxesOnController;
|
||||
char* m_axesIDs[MAX_NR_AXES];
|
||||
size_t m_nrFoundAxes;
|
||||
char m_allAxesIDs[255];
|
||||
int m_LastError;
|
||||
};
|
||||
|
||||
#endif /* PIGCSCONTROLLER_H_ */
|
||||
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* PIGCSMotorController.cpp
|
||||
*
|
||||
* Created on: 15.12.2010
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#include "PIGCSMotorController.h"
|
||||
#include "PIasynAxis.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
//#undef asynPrint
|
||||
//#define asynPrint(user,reason,format...) 0
|
||||
|
||||
|
||||
asynStatus PIGCSMotorController::initAxis(PIasynAxis* pAxis)
|
||||
{
|
||||
asynStatus status = hasLimitSwitches(pAxis);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
status = hasReferenceSensor(pAxis);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
return PIGCSController::initAxis(pAxis);
|
||||
}
|
||||
|
||||
asynStatus PIGCSMotorController::setAccelerationCts( PIasynAxis* pAxis, double accelerationCts)
|
||||
{
|
||||
double acceleration = fabs(accelerationCts) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator;
|
||||
if (acceleration == pAxis->m_acceleration)
|
||||
return asynSuccess;
|
||||
if (pAxis->m_maxAcceleration < 0)
|
||||
{
|
||||
getMaxAcceleration(pAxis);
|
||||
}
|
||||
if (acceleration > pAxis->m_maxAcceleration)
|
||||
acceleration = pAxis->m_maxAcceleration;
|
||||
|
||||
return setAcceleration(pAxis, acceleration);
|
||||
}
|
||||
|
||||
asynStatus PIGCSMotorController::referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards)
|
||||
{
|
||||
asynStatus status = setServo(pAxis, 1);
|
||||
if (asynSuccess != status)
|
||||
return status;
|
||||
|
||||
char cmd[100];
|
||||
if (velocity != 0)
|
||||
{
|
||||
velocity = fabs(velocity) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator;
|
||||
sprintf(cmd,"SPA %s 0x50 %f", pAxis->m_szAxisName, velocity);
|
||||
sendOnly(cmd);
|
||||
}
|
||||
|
||||
if (pAxis->m_bHasReference)
|
||||
{
|
||||
// call FRF - find reference
|
||||
sprintf(cmd,"FRF %s", pAxis->m_szAxisName);
|
||||
}
|
||||
else if (pAxis->m_bHasLimitSwitches)
|
||||
{
|
||||
if (forwards)
|
||||
{
|
||||
// call FPL - find positive limit switch
|
||||
sprintf(cmd,"FPL %s", pAxis->m_szAxisName);
|
||||
}
|
||||
else
|
||||
{
|
||||
// call FNL - find negative limit switch
|
||||
sprintf(cmd,"FNL %s", pAxis->m_szAxisName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR,
|
||||
"PIGCSMotorController::referenceVelCts() failed - axis has no reference/limit switch\n");
|
||||
epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize,
|
||||
"PIGCSMotorController::referenceVelCts() failed - axis has no reference/limit switch\n");
|
||||
return asynError;
|
||||
}
|
||||
status = sendOnly(cmd);
|
||||
if (asynSuccess != status)
|
||||
return status;
|
||||
int errorCode = getGCSError();
|
||||
if (errorCode == 0)
|
||||
{
|
||||
return asynSuccess;
|
||||
}
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR,
|
||||
"PIGCSMotorController::referenceVelCts() failed\n");
|
||||
epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize,
|
||||
"PIGCSMotorController::referenceVelCts() failed - GCS Error %d\n",errorCode);
|
||||
return asynError;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get encoder resolution from counts-per-unit (CPU) fraction of the axis.
|
||||
*/
|
||||
asynStatus PIGCSMotorController::getResolution(PIasynAxis* pAxis, double& resolution )
|
||||
{
|
||||
// CPU is "Counts Per Unit"
|
||||
// this is stored as two integers in the controller
|
||||
double num, denom;
|
||||
asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_CPU_Z, num);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
status = getGCSParameter(pAxis, PI_PARA_MOT_CPU_N, denom);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
pAxis->m_CPUnumerator = num;
|
||||
pAxis->m_CPUdenominator = denom;
|
||||
resolution = double(pAxis->m_CPUdenominator) / double(pAxis->m_CPUnumerator) ;
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
asynStatus PIGCSMotorController::getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl)
|
||||
{
|
||||
char buf[255];
|
||||
asynStatus status = sendAndReceive(char(4), buf, 99);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
// TODO this is for a single axis C-863/867 controller!!!!
|
||||
// TODO a) change it to multi-axis code.
|
||||
// TODO b) support other controllers which do not understand #4 or have different bit masks
|
||||
|
||||
int idx = 2 + pAxis->getAxisNo()*4;
|
||||
buf[idx+4] = '\0';
|
||||
char* szMask = buf+idx;
|
||||
long mask = strtol(szMask, NULL, 16);
|
||||
moving = (mask & 0x2000) ? 1 : 0;
|
||||
homing = (mask & 0x4000) ? 1 : 0;
|
||||
negLimit = (mask & 0x0001) ? 1 : 0;
|
||||
posLimit = (mask & 0x0004) ? 1 : 0;
|
||||
servoControl = (mask & 0x1000) ? 1 : 0;
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
|
||||
"PIGCSMotorController::getStatus() buf:%s moving %d, svo: %d\n",
|
||||
buf, moving, servoControl);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSMotorController::getMaxAcceleration(PIasynAxis* pAxis)
|
||||
{
|
||||
double maxAcc, maxDec;
|
||||
asynStatus status = getGCSParameter(pAxis, PI_PARA_MOT_MAX_ACCEL, maxAcc);
|
||||
if (asynSuccess != status)
|
||||
return status;
|
||||
status = getGCSParameter(pAxis, PI_PARA_MOT_MAX_DECEL, maxDec);
|
||||
if (asynSuccess != status)
|
||||
return status;
|
||||
|
||||
if (maxAcc < maxDec)
|
||||
{
|
||||
pAxis->m_maxAcceleration = maxAcc;
|
||||
}
|
||||
else
|
||||
{
|
||||
pAxis->m_maxAcceleration = maxDec;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSMotorController::setAcceleration( PIasynAxis* pAxis, double acceleration)
|
||||
{
|
||||
asynStatus status = setGCSParameter(pAxis, PI_PARA_MOT_CURR_ACCEL, acceleration);
|
||||
if (asynSuccess != status)
|
||||
return status;
|
||||
status = setGCSParameter(pAxis, PI_PARA_MOT_CURR_DECEL, acceleration);
|
||||
if (asynSuccess != status)
|
||||
return status;
|
||||
pAxis->m_acceleration = acceleration;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* PIGCScontroller.h
|
||||
*
|
||||
* Created on: 15.12.2010
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#ifndef PIGCSMOTORCONTROLLER_H_
|
||||
#define PIGCSMOTORCONTROLLER_H_
|
||||
|
||||
#include "PIGCSController.h"
|
||||
#include <asynDriver.h>
|
||||
|
||||
/**
|
||||
* class representing PI GCS2 motor controllers.
|
||||
*
|
||||
* "motor" does not strictly restrict the driving principle to DC stages or
|
||||
* stepper but includes other controller families (e.g. for piezo motors) also.
|
||||
*/
|
||||
class PIGCSMotorController : public PIGCSController
|
||||
{
|
||||
public:
|
||||
PIGCSMotorController(asynUser* pCom, const char* szIDN)
|
||||
: PIGCSController(pCom, szIDN)
|
||||
{
|
||||
}
|
||||
~PIGCSMotorController() {}
|
||||
virtual asynStatus initAxis(PIasynAxis* pAxis);
|
||||
|
||||
virtual asynStatus setAccelerationCts( PIasynAxis* pAxis, double acceleration);
|
||||
virtual asynStatus setAcceleration( PIasynAxis* pAxis, double acceleration);
|
||||
virtual asynStatus getMaxAcceleration( PIasynAxis* pAxis );
|
||||
virtual asynStatus referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards);
|
||||
virtual asynStatus getResolution(PIasynAxis* pAxis, double& resolution );
|
||||
virtual asynStatus getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl);
|
||||
|
||||
protected:
|
||||
enum
|
||||
{
|
||||
PI_PARA_MOT_CURR_ACCEL = 0x000000BUL,
|
||||
PI_PARA_MOT_CURR_DECEL = 0x000000CUL,
|
||||
PI_PARA_MOT_CPU_Z = 0x000000EUL,
|
||||
PI_PARA_MOT_CPU_N = 0x000000FUL,
|
||||
PI_PARA_MOT_HAT_REF = 0x0000014UL,
|
||||
PI_PARA_MOT_MAX_ACCEL = 0x000004AUL,
|
||||
PI_PARA_MOT_MAX_DECEL = 0x000004BUL
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif /* PIGCSMOTORCONTROLLER_H_ */
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* PIGCSPiezoController
|
||||
*
|
||||
* Created on: 15.12.2010
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#include "PIGCSPiezoController.h"
|
||||
#include "PIasynAxis.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#undef asynPrint
|
||||
#define asynPrint(user,reason,format...) 0
|
||||
|
||||
|
||||
asynStatus PIGCSPiezoController::getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl)
|
||||
{
|
||||
asynStatus status = getMoving(pAxis, moving);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
homing = 0;
|
||||
negLimit = 0;
|
||||
posLimit = 0;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIGCSPiezoController::getReferencedState(PIasynAxis* pAxis)
|
||||
{
|
||||
pAxis->m_homed = 1;
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* PIGCScontroller.h
|
||||
*
|
||||
* Created on: 15.12.2010
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#ifndef PIGCSPIEZOCONTROLLER_H_
|
||||
#define PIGCSPIEZOCONTROLLER_H_
|
||||
|
||||
#include "PIGCSController.h"
|
||||
#include <asynDriver.h>
|
||||
|
||||
/**
|
||||
* Class representing PI's GCS2 digital piezo controllers.
|
||||
*
|
||||
* Main difference to motor controllers is the usage of absolute sensors.
|
||||
*/
|
||||
class PIGCSPiezoController : public PIGCSController
|
||||
{
|
||||
public:
|
||||
PIGCSPiezoController(asynUser* pCom, const char* szIDN)
|
||||
: PIGCSController(pCom, szIDN)
|
||||
{
|
||||
}
|
||||
~PIGCSPiezoController() {}
|
||||
|
||||
virtual asynStatus init(void) { return PIGCSController::init(); }
|
||||
|
||||
virtual asynStatus getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl);
|
||||
virtual asynStatus getReferencedState(PIasynAxis* pAxis);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif /* PIGCSPIEZOCONTROLLER_H_ */
|
||||
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
* PIE755Controller
|
||||
*
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#include "PIHexapodController.h"
|
||||
#include "PIasynAxis.h"
|
||||
#include <stdlib.h>
|
||||
#include <epicsThread.h>
|
||||
|
||||
//#undef asynPrint
|
||||
//#define asynPrint(user,reason,format...) 0
|
||||
|
||||
asynStatus PIHexapodController::init(void)
|
||||
{
|
||||
asynStatus status = PIGCSController::init();
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// Try to find out if #4 is supported
|
||||
char buf[200];
|
||||
status = sendAndReceive(char(4), buf, 199);
|
||||
if (status == asynSuccess)
|
||||
{
|
||||
m_bCanReadStatusWithChar4 = true;
|
||||
}
|
||||
else if (status == asynTimeout)
|
||||
{
|
||||
m_bCanReadStatusWithChar4 = false;
|
||||
getGCSError(); // clear error UNKNOWN COMMAND
|
||||
}
|
||||
// status = sendAndReceive(char(3), buf, 199);
|
||||
// if (status == asynSuccess)
|
||||
// {
|
||||
// m_bCanReadPosWithChar3 = true;
|
||||
// }
|
||||
// else if (status == asynTimeout)
|
||||
{
|
||||
m_bCanReadPosWithChar3 = false;
|
||||
getGCSError(); // clear error UNKNOWN COMMAND
|
||||
}
|
||||
|
||||
m_bHoming = false;
|
||||
|
||||
ReadPivotSettings();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
asynStatus PIHexapodController::getGlobalState(asynMotorAxis** pAxes, int numAxes)
|
||||
{
|
||||
// do not call moving here, at least simulation software does return
|
||||
// values != 0 with bit 1 not set (e.g. "2")
|
||||
char buf[255];
|
||||
asynStatus status = sendAndReceive(char(5), buf, 99);;
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
printf("PIGCSController::getGlobalState() failed, status %d", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
char* pStr;
|
||||
long moving = strtol(buf, &pStr, 16);
|
||||
m_bAnyAxisMoving = (moving != 0);
|
||||
if (m_bHoming && (moving == 0))
|
||||
{
|
||||
m_bHoming = false;
|
||||
}
|
||||
for(int i=0; i<numAxes; i++)
|
||||
{
|
||||
((PIasynAxis*)pAxes[i])->m_bMoving = (moving != 0);
|
||||
}
|
||||
return asynSuccess;
|
||||
|
||||
}
|
||||
|
||||
asynStatus PIHexapodController::getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl)
|
||||
{
|
||||
negLimit = 0;
|
||||
posLimit = 0;
|
||||
homing = m_bHoming ? 1:0;
|
||||
|
||||
moving = pAxis->m_bMoving || pAxis->deferred_move;
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
asynStatus PIHexapodController::findConnectedAxes()
|
||||
{
|
||||
for (size_t i=0; i<MAX_NR_AXES; i++)
|
||||
{
|
||||
m_axesIDs[i] = NULL;
|
||||
}
|
||||
sprintf(m_allAxesIDs, "X\nY\nZ\nU\nV\nW");
|
||||
char* szAxis = strtok(m_allAxesIDs, "\n");
|
||||
while (szAxis != NULL)
|
||||
{
|
||||
int i=strlen(szAxis)-1;
|
||||
while (szAxis[i] == ' ')
|
||||
{
|
||||
szAxis[i] = '\0';
|
||||
i--;
|
||||
}
|
||||
if (MAX_NR_AXES <= m_nrFoundAxes)
|
||||
{
|
||||
return asynError;
|
||||
}
|
||||
m_axesIDs[m_nrFoundAxes] = szAxis;
|
||||
m_nrFoundAxes++;
|
||||
szAxis = strtok(NULL, "\n");
|
||||
}
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
asynStatus PIHexapodController::initAxis(PIasynAxis* pAxis)
|
||||
{
|
||||
pAxis->m_movingStateMask = 1;
|
||||
return setServo(pAxis, 1);
|
||||
}
|
||||
|
||||
asynStatus PIHexapodController::getReferencedState(PIasynAxis* pAxis)
|
||||
{
|
||||
if (!m_bCanReadStatusWithChar4)
|
||||
{
|
||||
pAxis->m_homed = 1;
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
char buf[255];
|
||||
asynStatus status = sendAndReceive(char(4), buf, 99);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
long mask = strtol(buf, NULL, 10);
|
||||
pAxis->m_homed = (mask & 0x10000) ? 1 : 0;
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIHexapodController::moveCts( PIasynAxis* pAxis, int targetCts )
|
||||
{
|
||||
// printf("PIHexapodController::moveCts(,%d)...\n",targetCts);
|
||||
asynStatus status;
|
||||
char cmd[100];
|
||||
double target = double(targetCts) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator;
|
||||
sprintf(cmd,"MOV %s %f", pAxis->m_szAxisName, target);
|
||||
status = sendOnly(cmd);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
epicsThreadSleep( 0.2 ); // TODO test if we do need this
|
||||
asynMotorAxis* pAsynAxis = (asynMotorAxis*)pAxis;
|
||||
status = getGlobalState(&pAsynAxis, 1);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
// printf("PIHexapodController::moveCts(,%d) - getGlobalState() failed, status=%d\n", targetCts, status);
|
||||
return status;
|
||||
}
|
||||
if (!pAxis->m_bMoving)
|
||||
{
|
||||
int errorCode = getGCSError();
|
||||
// printf("PIHexapodController::moveCts(,%d) - not moving after MOV() gcserror=%d\n",targetCts, errorCode);
|
||||
if (errorCode != 0)
|
||||
{
|
||||
asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
|
||||
"PIHexapodController::moveCts() failed, GCS error %d\n", errorCode);
|
||||
return asynError;
|
||||
}
|
||||
}
|
||||
m_bAnyAxisMoving = true;
|
||||
pAxis->m_lastDirection = (targetCts > pAxis->m_positionCts) ? 1 : 0;
|
||||
printf("PIHexapodController::moveCts(,%d) - OK!\n",targetCts);
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIHexapodController::moveCts( PIasynAxis** pAxesArray, int* pTargetCtsArray, int numAxes)
|
||||
{
|
||||
asynStatus status;
|
||||
char cmd[1000] = "MOV";
|
||||
char subCmd[100];
|
||||
for (int axis = 0; axis <numAxes; axis++)
|
||||
{
|
||||
PIasynAxis* pAxis = pAxesArray[axis];
|
||||
double target = double(pTargetCtsArray[axis]) * pAxis->m_CPUdenominator / pAxis->m_CPUnumerator;
|
||||
sprintf(subCmd," %s %f", pAxis->m_szAxisName, target);
|
||||
strcat(cmd, subCmd);
|
||||
pAxis->m_lastDirection = (pTargetCtsArray[axis] > pAxis->m_positionCts) ? 1 : 0;
|
||||
}
|
||||
status = sendOnly(cmd);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
epicsThreadSleep(0.2);
|
||||
status = getGlobalState((asynMotorAxis**)pAxesArray, numAxes);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
if (!pAxesArray[0]->m_bMoving)
|
||||
{
|
||||
int errorCode = getGCSError();
|
||||
if (errorCode != 0)
|
||||
{
|
||||
asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
|
||||
"PIHexapodController::moveCts() failed, GCS error %d\n", errorCode);
|
||||
return asynError;
|
||||
}
|
||||
}
|
||||
m_bAnyAxisMoving = true;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
asynStatus PIHexapodController::getAxisPosition(PIasynAxis* pAxis, double& position)
|
||||
{
|
||||
if (!m_bAnyAxisMoving)
|
||||
{
|
||||
return PIGCSController::getAxisPosition(pAxis, position);
|
||||
}
|
||||
if (m_bCanReadPosWithChar3)
|
||||
{
|
||||
char buf[255];
|
||||
asynStatus status = sendAndReceive(char(3), buf, 99);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
char *pStart = buf;
|
||||
for(;;)
|
||||
{
|
||||
bool bEnd = false;
|
||||
while(*pStart == ' ') pStart++;
|
||||
char *pLF = strstr(pStart, "\n");
|
||||
if (pLF != NULL)
|
||||
{
|
||||
*pLF = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
bEnd = true;
|
||||
}
|
||||
// single line will look like "X = 1.0 \n"
|
||||
if (pStart[0] == pAxis->m_szAxisName[0] )
|
||||
{
|
||||
double value;
|
||||
if (!getValue(pStart, value))
|
||||
{
|
||||
return asynError;
|
||||
}
|
||||
position = value;
|
||||
return status;
|
||||
}
|
||||
if (bEnd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pStart = pLF + 1;
|
||||
if (*pStart == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
// should not come here!
|
||||
return asynError;
|
||||
}
|
||||
// return last position
|
||||
position = double(pAxis->m_positionCts) * double(pAxis->m_CPUdenominator) / double(pAxis->m_CPUnumerator);
|
||||
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
asynStatus PIHexapodController::SetPivotX(double value)
|
||||
{
|
||||
if (NULL != m_pCurrentLogSink)
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
|
||||
"PIHexapodController::SetPivotX() value %f", value);
|
||||
}
|
||||
asynStatus status = SetPivot('R', value);
|
||||
if (status== asynSuccess)
|
||||
{
|
||||
m_PivotX = value;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIHexapodController::SetPivotY(double value)
|
||||
{
|
||||
if (NULL != m_pCurrentLogSink)
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
|
||||
"PIHexapodController::SetPivotY() value %f", value);
|
||||
}
|
||||
asynStatus status = SetPivot('S', value);
|
||||
if (status== asynSuccess)
|
||||
{
|
||||
m_PivotY = value;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIHexapodController::SetPivotZ(double value)
|
||||
{
|
||||
if (NULL != m_pCurrentLogSink)
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
|
||||
"PIHexapodController::SetPivotZ() value %f", value);
|
||||
}
|
||||
asynStatus status = SetPivot('T', value);
|
||||
if (status== asynSuccess)
|
||||
{
|
||||
m_PivotZ = value;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIHexapodController::SetPivot(char cAxis, double value)
|
||||
{
|
||||
if (m_bAnyAxisMoving)
|
||||
{
|
||||
if (NULL != m_pCurrentLogSink)
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW,
|
||||
"PIHexapodController::SetPivot() cannot change pivot point while platform is moving");
|
||||
}
|
||||
return asynError;
|
||||
}
|
||||
|
||||
asynStatus status;
|
||||
char cmd[100];
|
||||
sprintf(cmd,"SPI %c %f", cAxis, value);
|
||||
status = sendOnly(cmd);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
int errorCode = getGCSError();
|
||||
if (errorCode != 0)
|
||||
{
|
||||
asynPrint(m_pInterface, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
|
||||
"PIHexapodController::SetPivot() failed, GCS error %d\n", errorCode);
|
||||
return asynError;
|
||||
}
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
asynStatus PIHexapodController::ReadPivotSettings()
|
||||
{
|
||||
char buf[100];
|
||||
char cmd[] = "SPI? RST";
|
||||
asynStatus status = sendAndReceive(cmd, buf, 99);
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
char* pStart = buf;
|
||||
bool bEnd = false;
|
||||
double px = 0.0;
|
||||
double py = 0.0;
|
||||
double pz = 0.0;
|
||||
for(;;)
|
||||
{
|
||||
while(*pStart == ' ') pStart++;
|
||||
char *pLF = strstr(pStart, "\n");
|
||||
if (pLF != NULL)
|
||||
{
|
||||
*pLF = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
bEnd = true;
|
||||
}
|
||||
// single line will look like "R = 1.0 \n"
|
||||
double value;
|
||||
if (!getValue(pStart, value))
|
||||
{
|
||||
return asynError;
|
||||
}
|
||||
switch(pStart[0])
|
||||
{
|
||||
case'R': px = value; break;
|
||||
case'S': py = value; break;
|
||||
case'T': pz = value; break;
|
||||
}
|
||||
if (bEnd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pStart = pLF + 1;
|
||||
if (*pStart == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_PivotX = px;
|
||||
m_PivotY = py;
|
||||
m_PivotZ = pz;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIHexapodController::referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards)
|
||||
{
|
||||
asynStatus status = sendOnly("INI X");
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
int errorCode = getGCSError();
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_ERROR,
|
||||
"PIHexapodController::referenceVelCts() failed\n");
|
||||
epicsSnprintf(pAxis->m_pasynUser->errorMessage,pAxis->m_pasynUser->errorMessageSize,
|
||||
"PIHexapodController::referenceVelCts() failed - GCS Error %d\n",errorCode);
|
||||
return status;
|
||||
}
|
||||
m_bHoming = true;
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
asynStatus PIHexapodController::haltAxis(PIasynAxis* pAxis)
|
||||
{
|
||||
asynStatus status = sendOnly(char(24));
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
//epicsThreadSleep(0.1); // TODO test value
|
||||
int err = getGCSError();
|
||||
// controller will set error code to PI_CNTR_STOP (10)
|
||||
if (err != PI_CNTR_STOP)
|
||||
{
|
||||
asynPrint(m_pCurrentLogSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
|
||||
"PIGCSController::haltAxis() failed, GCS error %d", err);
|
||||
return asynError;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* PIE755Controller.h
|
||||
*
|
||||
* Author: sra
|
||||
*/
|
||||
|
||||
#ifndef PIHEXAPODCONTROLLER_H_
|
||||
#define PIHEXAPODCONTROLLER_H_
|
||||
|
||||
#include "PIGCSController.h"
|
||||
|
||||
/**
|
||||
* class representing PI Hexapods.
|
||||
*/
|
||||
class PIHexapodController : public PIGCSController
|
||||
{
|
||||
public:
|
||||
PIHexapodController(asynUser* pCom, const char* szIDN)
|
||||
: PIGCSController(pCom, szIDN)
|
||||
{
|
||||
}
|
||||
~PIHexapodController() {}
|
||||
|
||||
virtual asynStatus init(void);
|
||||
virtual asynStatus initAxis(PIasynAxis* pAxis);
|
||||
|
||||
virtual asynStatus setAccelerationCts( PIasynAxis* pAxis, double acceleration) { return asynSuccess; }
|
||||
virtual asynStatus setAcceleration( PIasynAxis* pAxis, double acceleration) { return asynSuccess; }
|
||||
virtual asynStatus getStatus(PIasynAxis* pAxis, int& homing, int& moving, int& negLimit, int& posLimit, int& servoControl);
|
||||
virtual asynStatus getGlobalState(asynMotorAxis** Axes, int numAxes);
|
||||
virtual asynStatus getTravelLimits(PIasynAxis* pAxis, double& negLimit, double& posLimit)
|
||||
{
|
||||
negLimit = -100;
|
||||
posLimit = 100;
|
||||
return asynSuccess;
|
||||
}
|
||||
virtual asynStatus getReferencedState(PIasynAxis* pAxis);
|
||||
|
||||
virtual asynStatus haltAxis(PIasynAxis* pAxis);
|
||||
|
||||
virtual bool AcceptsNewTarget() { return !m_bAnyAxisMoving; }
|
||||
virtual bool CanCommunicateWhileHoming() { return false; }
|
||||
|
||||
virtual asynStatus moveCts( PIasynAxis* pAxis, int target);
|
||||
virtual asynStatus moveCts( PIasynAxis** pAxesArray, int* pTargetCtsArray, int numAxes);
|
||||
virtual asynStatus getAxisPosition(PIasynAxis* pAxis, double& position);
|
||||
|
||||
virtual asynStatus SetPivotX(double value);
|
||||
virtual asynStatus SetPivotY(double value);
|
||||
virtual asynStatus SetPivotZ(double value);
|
||||
|
||||
virtual double GetPivotX() { return m_PivotX; }
|
||||
virtual double GetPivotY() { return m_PivotY; }
|
||||
virtual double GetPivotZ() { return m_PivotZ; }
|
||||
|
||||
virtual asynStatus referenceVelCts( PIasynAxis* pAxis, double velocity, int forwards);
|
||||
|
||||
protected:
|
||||
virtual asynStatus findConnectedAxes();
|
||||
asynStatus ReadPivotSettings();
|
||||
asynStatus SetPivot(char cAxis, double value);
|
||||
|
||||
double m_PivotX;
|
||||
double m_PivotY;
|
||||
double m_PivotZ;
|
||||
|
||||
bool m_bHoming;
|
||||
|
||||
private:
|
||||
bool m_bCanReadStatusWithChar4;
|
||||
bool m_bCanReadPosWithChar3;
|
||||
};
|
||||
|
||||
#endif /* PIHEXAPODCONTROLLER_H_ */
|
||||
@@ -0,0 +1,6 @@
|
||||
include "asyn.dbd"
|
||||
include "motorRecord.dbd"
|
||||
##device(motor,VME_IO,devPIasyn,"PI Motor GCS2")
|
||||
##driver(PIasyn)
|
||||
registrar(PIasynDriverRegister)
|
||||
##registrar(PIasynRegister)
|
||||
+305
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
FILENAME... PIasynController.cpp
|
||||
USAGE... Simulated Motor Support.
|
||||
|
||||
Based on drvMotorSim.c
|
||||
|
||||
Mark Rivers
|
||||
December 13, 2009
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <epicsTime.h>
|
||||
#include <epicsThread.h>
|
||||
#include <epicsString.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <ellLib.h>
|
||||
#include <iocsh.h>
|
||||
#include <epicsExport.h>
|
||||
#include <motor_interface.h>
|
||||
|
||||
#include "PIasynAxis.h"
|
||||
#include "PIasynController.h"
|
||||
#include "PIGCSController.h"
|
||||
|
||||
//#undef asynPrint
|
||||
//#define asynPrint(user,reason,format...) 0
|
||||
|
||||
static const char *driverName = "PIasynAxis";
|
||||
|
||||
PIasynAxis::PIasynAxis(PIasynController *pController, PIGCSController* pGCSController, int axis, const char* szName )
|
||||
: asynMotorAxis((asynMotorController*)pController, axis)
|
||||
, pController_(pController)
|
||||
, m_szAxisName(NULL)
|
||||
, m_isHoming(0)
|
||||
, m_homed(0)
|
||||
, m_acceleration(0.0)
|
||||
, m_maxAcceleration(-1.0)
|
||||
, m_lastDirection(0)
|
||||
, m_CPUnumerator(1000)
|
||||
, m_CPUdenominator(1)
|
||||
, m_pasynUser(NULL)
|
||||
, m_bHasLimitSwitches(false)
|
||||
, m_bHasReference(false)
|
||||
, m_bProblem(false)
|
||||
, m_bServoControl(false)
|
||||
, m_bMoving(false)
|
||||
, m_pGCSController(pGCSController)
|
||||
{
|
||||
if (szName != NULL)
|
||||
{
|
||||
m_szAxisName = new char[strlen(szName)+1];
|
||||
strcpy(m_szAxisName, szName);
|
||||
}
|
||||
|
||||
printf("PIasynAxis::PIasynAxis() %d: %s\n",
|
||||
axis, m_szAxisName);
|
||||
}
|
||||
|
||||
|
||||
void PIasynAxis::Init(const char *portName)
|
||||
{
|
||||
asynUser* logSink = pasynManager->createAsynUser(0,0);
|
||||
asynStatus status = pasynManager->connectDevice(logSink, portName, getAxisNo());
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
asynPrint(logSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
|
||||
"PIasynController::configAxis() - connectDevice() failed\n");
|
||||
return;
|
||||
}
|
||||
m_pGCSController->m_pCurrentLogSink = logSink;
|
||||
|
||||
setIntegerParam(motorAxisHasClosedLoop, 1);
|
||||
|
||||
m_pGCSController->initAxis(this);
|
||||
double resolution;
|
||||
m_pGCSController->getResolution(this, resolution);
|
||||
m_pGCSController->getAxisVelocity(this);
|
||||
m_pGCSController->getAxisPositionCts(this);
|
||||
setDoubleParam(pController_->motorPosition_, m_positionCts);
|
||||
setDoubleParam(pController_->motorMoveAbs_, m_positionCts);
|
||||
m_pGCSController->getTravelLimits(this, negLimit_, posLimit_);
|
||||
setDoubleParam(pController_->motorLowLimit_, negLimit_);
|
||||
setDoubleParam(pController_->motorHighLimit_, posLimit_);
|
||||
m_pGCSController->getReferencedState(this);
|
||||
setIntegerParam( pController_->motorStatusHomed_, m_homed );
|
||||
callParamCallbacks();
|
||||
|
||||
pasynManager->freeAsynUser(logSink);
|
||||
|
||||
}
|
||||
|
||||
PIasynAxis::~PIasynAxis()
|
||||
{
|
||||
if (m_szAxisName != NULL)
|
||||
{
|
||||
delete [] m_szAxisName;
|
||||
}
|
||||
}
|
||||
|
||||
asynStatus PIasynAxis::poll(bool *returnMoving)
|
||||
{
|
||||
int done = 0;
|
||||
|
||||
int moving, negLimit, posLimit, servoControl;
|
||||
int oldHoming = m_isHoming;
|
||||
m_pGCSController->getStatus(this, m_isHoming, moving, negLimit, posLimit, servoControl);
|
||||
if (moving == 0 && m_isHoming == 0)
|
||||
done = 1;
|
||||
|
||||
m_bMoving = (done!=1);
|
||||
if (!m_isHoming || m_pGCSController->CanCommunicateWhileHoming())
|
||||
{
|
||||
if (oldHoming && oldHoming != m_isHoming)
|
||||
{
|
||||
m_pGCSController->getReferencedState(this);
|
||||
asynPrint(pasynUser_, ASYN_TRACE_ERROR, //FIXME: ASYN_TRACE_FLOW,
|
||||
"PIasynAxis::poll() axis %d referencing state changed, homed = %d\n",
|
||||
axisNo_, m_homed );
|
||||
}
|
||||
if (m_bServoControl && servoControl == 0) // servo changed without user interaction!
|
||||
{
|
||||
m_bProblem = true;
|
||||
}
|
||||
if (!m_isHoming || m_pGCSController->IsGCS2())
|
||||
{
|
||||
m_bServoControl = (servoControl == 1);
|
||||
m_pGCSController->getAxisPositionCts(this);
|
||||
double realPosition;
|
||||
m_pGCSController->getAxisPosition(this, realPosition);
|
||||
setDoubleParam(pController_->PI_SUP_POSITION, realPosition );
|
||||
}
|
||||
}
|
||||
if (m_isHoming)
|
||||
{
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
||||
"PIasynAxis::poll() axis %d referencing ...\n", axisNo_ );
|
||||
}
|
||||
setDoubleParam(pController_->motorPosition_, m_positionCts );
|
||||
setDoubleParam(pController_->motorEncoderPosition_, m_positionCts);
|
||||
setIntegerParam(pController_->motorStatusDirection_, m_lastDirection);
|
||||
setIntegerParam(pController_->motorStatusDone_, done );
|
||||
setIntegerParam(pController_->motorStatusHighLimit_, posLimit);
|
||||
setIntegerParam(pController_->motorStatusHomed_, m_homed );
|
||||
setIntegerParam(pController_->motorStatusMoving_, !done );
|
||||
setIntegerParam(pController_->motorStatusLowLimit_, negLimit);
|
||||
setIntegerParam(pController_->motorStatusGainSupport_, true);
|
||||
setIntegerParam(pController_->motorStatusProblem_, m_bProblem);
|
||||
setIntegerParam(pController_->motorStatusPowerOn_, m_bServoControl);
|
||||
setIntegerParam(pController_->PI_SUP_SERVO, m_bServoControl );
|
||||
|
||||
callParamCallbacks();
|
||||
|
||||
*returnMoving = m_bMoving;
|
||||
}
|
||||
|
||||
asynStatus PIasynAxis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration)
|
||||
{
|
||||
m_pGCSController->m_pCurrentLogSink = pasynUser_;
|
||||
asynStatus status = asynError;
|
||||
static const char *functionName = "moveAxis";
|
||||
|
||||
if (!m_pGCSController->AcceptsNewTarget())
|
||||
{
|
||||
asynPrint(pasynUser_, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"%s:%s: Set port %s, axis %d - controller does not accept new target (busy?)\n",
|
||||
driverName, functionName, pC_->portName, axisNo_ );
|
||||
printf("%s:%s: Set port %s, axis %d - controller does not accept new target (busy?)\n",
|
||||
driverName, functionName, pC_->portName, axisNo_ );
|
||||
return status;
|
||||
}
|
||||
|
||||
if (relative)
|
||||
{
|
||||
//TODO: MVR oder letztes target!
|
||||
//TODO: when is this used?
|
||||
}
|
||||
|
||||
if (pController_->movesDeferred != 0)
|
||||
{ /*Deferred moves.*/
|
||||
deferred_position = position;
|
||||
deferred_move = 1;
|
||||
deferred_relative = relative;
|
||||
setIntegerParam(pController_->motorStatusDone_, 0);
|
||||
callParamCallbacks();
|
||||
return asynSuccess;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (maxVelocity != 0)
|
||||
{
|
||||
status = m_pGCSController->setVelocityCts(this, maxVelocity);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
if (acceleration != 0)
|
||||
{
|
||||
status = m_pGCSController->setAccelerationCts(this, acceleration);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
setIntegerParam(pController_->motorStatusDone_, 0);
|
||||
callParamCallbacks();
|
||||
|
||||
status = m_pGCSController->moveCts(this, position);
|
||||
}
|
||||
epicsEventSignal(pController_->pollEventId_);
|
||||
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
||||
"%s:%s: Set driver %s, axis %d move to %f, min vel=%f, max_vel=%f, accel=%f, deffered=%d - status=%d\n",
|
||||
driverName, functionName, pC_->portName, axisNo_, position, minVelocity, maxVelocity, acceleration, pController_->movesDeferred, int(status) );
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIasynAxis::moveVelocity(double minVelocity, double maxVelocity, double acceleration)
|
||||
{
|
||||
m_pGCSController->m_pCurrentLogSink = pasynUser_;
|
||||
asynStatus status = asynError;
|
||||
static const char *functionName = "moveVelocityAxis";
|
||||
|
||||
if (!m_pGCSController->AcceptsNewTarget())
|
||||
{
|
||||
asynPrint(pasynUser_, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"%s:%s: Set port %s, axis %d - controller does not accept new target (busy?)",
|
||||
driverName, functionName, pController_->portName, axisNo_ );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
setIntegerParam(pController_->motorStatusDone_, 0);
|
||||
callParamCallbacks();
|
||||
|
||||
|
||||
double target = maxVelocity > 0 ? posLimit_ : negLimit_;
|
||||
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
||||
"%s:%s: Set port %s, axis %d move with velocity of %f, accel=%f / target %f - BEFORE MOV\n",
|
||||
driverName, functionName, pController_->portName, axisNo_, maxVelocity, acceleration, target );
|
||||
|
||||
m_pGCSController->setVelocityCts(this, maxVelocity);
|
||||
m_pGCSController->move(this, target);
|
||||
|
||||
epicsEventSignal(pController_->pollEventId_);
|
||||
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
||||
"%s:%s: Set port %s, axis %d move with velocity of %f, accel=%f / target %f - AFTER MOV\n",
|
||||
driverName, functionName, pController_->portName, axisNo_, maxVelocity, acceleration, target );
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIasynAxis::stop(double acceleration)
|
||||
{
|
||||
m_pGCSController->m_pCurrentLogSink = pasynUser_;
|
||||
static const char *functionName = "stopAxis";
|
||||
|
||||
deferred_move = 0;
|
||||
|
||||
m_pGCSController->haltAxis(this);
|
||||
|
||||
epicsEventSignal(pController_->pollEventId_);
|
||||
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
||||
"%s:%s: Set axis %d to stop with accel=%f",
|
||||
driverName, functionName, axisNo_, acceleration );
|
||||
return asynSuccess;
|
||||
}
|
||||
|
||||
|
||||
|
||||
asynStatus PIasynAxis::home(double minVelocity, double maxVelocity, double acceleration, int forwards)
|
||||
{
|
||||
m_pGCSController->m_pCurrentLogSink = pasynUser_;
|
||||
asynStatus status = asynError;
|
||||
static const char *functionName = "homeAxis";
|
||||
|
||||
m_isHoming = 1;
|
||||
setIntegerParam(pController_->motorStatusDone_, 0 );
|
||||
callParamCallbacks();
|
||||
|
||||
status = m_pGCSController->referenceVelCts(this, maxVelocity, forwards);
|
||||
if (asynSuccess != status)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
setIntegerParam(pController_->motorStatusHomed_, m_homed );
|
||||
epicsEventSignal(pController_->pollEventId_);
|
||||
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
||||
"%s:%s: Set driver %s, axis %d to home %s, min vel=%f, max_vel=%f, accel=%f",
|
||||
driverName, functionName, pController_->portName, axisNo_, (forwards?"FORWARDS":"REVERSE"), minVelocity, maxVelocity, acceleration );
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
FILENAME... PIasynController.cpp
|
||||
USAGE... PI GCS Motor Support.
|
||||
|
||||
Based on drvMotorSim.c
|
||||
|
||||
Mark Rivers
|
||||
December 13, 2009
|
||||
|
||||
Steffen Rau,
|
||||
January 2011
|
||||
*/
|
||||
|
||||
|
||||
#include <asynDriver.h> // for asynStatus
|
||||
#include <asynMotorAxis.h>
|
||||
|
||||
class PIasynController;
|
||||
class PIGCSController;
|
||||
|
||||
class PIasynAxis : public asynMotorAxis
|
||||
{
|
||||
public:
|
||||
PIasynAxis(class PIasynController *pController, PIGCSController* pGCSController, int axis, const char* szName);
|
||||
virtual~PIasynAxis();
|
||||
|
||||
void Init(const char *portName);
|
||||
|
||||
class PIasynController *pController_;
|
||||
int getAxisNo() { return axisNo_; }
|
||||
|
||||
virtual asynStatus poll(bool *moving);
|
||||
virtual asynStatus move(double position, int relative, double minVelocity, double maxVelocity, double acceleration);
|
||||
virtual asynStatus moveVelocity(double minVelocity, double maxVelocity, double acceleration);
|
||||
virtual asynStatus home(double minVelocity, double maxVelocity, double acceleration, int forwards);
|
||||
virtual asynStatus stop(double acceleration);
|
||||
|
||||
|
||||
char* m_szAxisName; ///< GCS name
|
||||
|
||||
int m_isHoming; ///< if \b TRUE indicating that axis is currently homing/referencing
|
||||
double deferred_position; ///< currently not used
|
||||
int deferred_move; ///< currently not used
|
||||
int deferred_relative; ///< currently not used
|
||||
int m_homed; ///< if \b TRUE axis was homed and absolute positions are correct
|
||||
|
||||
double m_velocity;
|
||||
double m_acceleration;
|
||||
double m_maxAcceleration;
|
||||
int m_positionCts;
|
||||
double m_position;
|
||||
int m_lastDirection;
|
||||
|
||||
int m_CPUnumerator;
|
||||
int m_CPUdenominator;
|
||||
|
||||
asynUser* m_pasynUser;
|
||||
|
||||
bool m_bHasLimitSwitches;
|
||||
bool m_bHasReference;
|
||||
bool m_bProblem;
|
||||
bool m_bServoControl;
|
||||
bool m_bMoving;
|
||||
int m_movingStateMask;
|
||||
|
||||
friend class PIasynController;
|
||||
private:
|
||||
|
||||
double negLimit_;
|
||||
double posLimit_;
|
||||
PIGCSController* m_pGCSController;
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,527 @@
|
||||
/*
|
||||
FILENAME... PIasynController.cpp
|
||||
USAGE... PI GCS2 Motor Support.
|
||||
|
||||
Based on drvMotorSim.c
|
||||
from Mark Rivers, December 13, 2009
|
||||
|
||||
Steffen Rau, Physik Instrumente (PI) GmbH & Co KG
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#include <epicsTime.h>
|
||||
#include <epicsThread.h>
|
||||
#include <epicsString.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <ellLib.h>
|
||||
#include <iocsh.h>
|
||||
#include <epicsExport.h>
|
||||
#include <asynOctetSyncIO.h>
|
||||
#include <motor_interface.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "PIasynController.h"
|
||||
#include "PIGCSController.h"
|
||||
#include "PIasynAxis.h"
|
||||
|
||||
|
||||
//#undef asynPrint
|
||||
//#define asynPrint(user,reason,format...) 0
|
||||
|
||||
|
||||
static const char *driverName = "PIasynDriver";
|
||||
|
||||
|
||||
static ELLLIST PIasynControllerList;
|
||||
static int PIasynControllerListInitialized = 0;
|
||||
|
||||
PIasynController::PIasynController(const char *portName, const char* asynPort, int numAxes, int priority, int stackSize, int movingPollPeriod, int idlePollPeriod)
|
||||
: asynMotorController(portName, numAxes, 10,
|
||||
asynInt32Mask | asynFloat64Mask,
|
||||
asynInt32Mask | asynFloat64Mask,
|
||||
ASYN_CANBLOCK | ASYN_MULTIDEVICE,
|
||||
1, // autoconnect
|
||||
priority, stackSize)
|
||||
, m_pGCSController( NULL )
|
||||
{
|
||||
createParam(PI_SUP_POSITION_String, asynParamFloat64, &PI_SUP_POSITION);
|
||||
createParam(PI_SUP_TARGET_String, asynParamFloat64, &PI_SUP_TARGET);
|
||||
createParam(PI_SUP_SERVO_String, asynParamInt32, &PI_SUP_SERVO);
|
||||
createParam(PI_SUP_LAST_ERR_String, asynParamInt32, &PI_SUP_LAST_ERR);
|
||||
createParam(PI_SUP_PIVOT_X_String, asynParamFloat64, &PI_SUP_PIVOT_X);
|
||||
createParam(PI_SUP_PIVOT_Y_String, asynParamFloat64, &PI_SUP_PIVOT_Y);
|
||||
createParam(PI_SUP_PIVOT_Z_String, asynParamFloat64, &PI_SUP_PIVOT_Z);
|
||||
createParam(PI_SUP_RBPIVOT_X_String, asynParamFloat64, &PI_SUP_RBPIVOT_X);
|
||||
createParam(PI_SUP_RBPIVOT_Y_String, asynParamFloat64, &PI_SUP_RBPIVOT_Y);
|
||||
createParam(PI_SUP_RBPIVOT_Z_String, asynParamFloat64, &PI_SUP_RBPIVOT_Z);
|
||||
|
||||
int axis;
|
||||
PIasynAxis *pAxis;
|
||||
PIasynControllerNode *pNode;
|
||||
|
||||
if (!PIasynControllerListInitialized)
|
||||
{
|
||||
PIasynControllerListInitialized = 1;
|
||||
ellInit(&PIasynControllerList);
|
||||
}
|
||||
|
||||
// We should make sure this portName is not already in the list */
|
||||
pNode = (PIasynControllerNode*) calloc(1, sizeof(PIasynControllerNode));
|
||||
pNode->portName = epicsStrDup(portName);
|
||||
pNode->pController = this;
|
||||
ellAdd(&PIasynControllerList, (ELLNODE *)pNode);
|
||||
|
||||
|
||||
asynStatus status;
|
||||
asynUser* pInterface;
|
||||
status = pasynOctetSyncIO->connect(asynPort, 0, &pInterface, NULL);
|
||||
if (status)
|
||||
{
|
||||
asynPrint(pInterface, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"echoHandler: unable to connect to port %s\n",
|
||||
asynPort);
|
||||
return;
|
||||
}
|
||||
status = pasynOctetSyncIO->setInputEos(pInterface, "\n", 1);
|
||||
if (status) {
|
||||
asynPrint(pInterface, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"echoHandler: unable to set input EOS on %s: %s\n",
|
||||
asynPort, pInterface->errorMessage);
|
||||
return;
|
||||
}
|
||||
status = pasynOctetSyncIO->setOutputEos(pInterface, "", 0);
|
||||
if (status) {
|
||||
asynPrint(pInterface, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"echoHandler: unable to set output EOS on %s: %s\n",
|
||||
asynPort, pInterface->errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
char inputBuff[256];
|
||||
inputBuff[0] = '\0';
|
||||
status = PIGCSController::sendAndReceive(pInterface, "*IDN?", inputBuff, 255, pInterface);
|
||||
asynPrint(pInterface, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"read from %s: %s\n",
|
||||
asynPort, inputBuff);
|
||||
|
||||
char* p = inputBuff;
|
||||
while (*p != '\0') { *p = toupper(*p); p++; }
|
||||
|
||||
m_pGCSController = PIGCSController::CreateGCSController(pInterface, inputBuff);
|
||||
if (NULL == m_pGCSController)
|
||||
{
|
||||
asynPrint(pInterface, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"PIasynController: unknown controller type %s: %s\n",
|
||||
asynPort, inputBuff);
|
||||
return;
|
||||
}
|
||||
|
||||
m_pGCSController->init();
|
||||
|
||||
if (numAxes < 1 ) numAxes = 1;
|
||||
this->numAxes_ = numAxes;
|
||||
|
||||
if (m_pGCSController->getNrFoundAxes()<size_t(numAxes))
|
||||
{
|
||||
// more axes configured than connected to controller
|
||||
asynPrint(pInterface, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"PIasynController: requested number of axes (%d) out of range, only %d axis/axes supported\n",
|
||||
numAxes, int(m_pGCSController->getNrFoundAxes()));
|
||||
delete m_pGCSController;
|
||||
m_pGCSController = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
for (axis=0; axis<numAxes; axis++)
|
||||
{
|
||||
pAxis = new PIasynAxis(this, m_pGCSController, axis, m_pGCSController->getAxesID(axis));
|
||||
pAxis->Init(portName);
|
||||
}
|
||||
|
||||
startPoller(double(movingPollPeriod)/1000, double(idlePollPeriod)/1000, 10);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void PIasynController::report(FILE *fp, int level)
|
||||
{
|
||||
int axis;
|
||||
PIasynAxis *pAxis;
|
||||
|
||||
fprintf(fp, "Simulation motor driver %s, numAxes=%d\n",
|
||||
this->portName, this->numAxes_);
|
||||
|
||||
for (axis=0; axis<this->numAxes_; axis++)
|
||||
{
|
||||
pAxis = getPIAxis(axis);
|
||||
fprintf(fp, " axis %d\n",
|
||||
pAxis->axisNo_);
|
||||
|
||||
if (level > 0)
|
||||
{
|
||||
if (pAxis->m_isHoming)
|
||||
{
|
||||
fprintf(fp, " Currently homing axis\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Call the base class method
|
||||
asynMotorController::report(fp, level);
|
||||
}
|
||||
|
||||
//PIasynAxis * PIasynController::getPIAxis(asynUser *pasynUser)
|
||||
//{
|
||||
// int axis;
|
||||
// PIasynAxis *pAxis;
|
||||
//
|
||||
// getAddress(pasynUser, &axis);
|
||||
// pAxis = this->m_pAxes[axis];
|
||||
// pAxis->m_pasynUser = pasynUser;
|
||||
// return(pAxis);
|
||||
//}
|
||||
|
||||
|
||||
|
||||
asynStatus PIasynController::processDeferredMoves()
|
||||
{
|
||||
asynStatus status = asynError;
|
||||
int axis;
|
||||
PIasynAxis *pAxesArray[PIGCSController::MAX_NR_AXES];
|
||||
int targetsCts[PIGCSController::MAX_NR_AXES];
|
||||
|
||||
int numDeferredAxes = 0;
|
||||
for (axis=0; axis<this->numAxes_; axis++)
|
||||
{
|
||||
PIasynAxis *pAxis = getPIAxis(axis);
|
||||
if (pAxis->deferred_move)
|
||||
{
|
||||
pAxesArray[numDeferredAxes] = pAxis;
|
||||
targetsCts[numDeferredAxes] = pAxis->deferred_position;
|
||||
pAxis->setIntegerParam(motorStatusDone_, 0);
|
||||
pAxis->callParamCallbacks();
|
||||
numDeferredAxes++;
|
||||
}
|
||||
}
|
||||
if (numDeferredAxes > 0)
|
||||
{
|
||||
status = m_pGCSController->moveCts(pAxesArray, targetsCts, numDeferredAxes);
|
||||
}
|
||||
|
||||
for (axis=0; axis<this->numAxes_; axis++)
|
||||
{
|
||||
if (getPIAxis(axis)->deferred_move)
|
||||
{
|
||||
getPIAxis(axis)->deferred_move = 0;
|
||||
}
|
||||
}
|
||||
epicsEventSignal(pollEventId_);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
asynStatus PIasynController::writeInt32(asynUser *pasynUser, epicsInt32 value)
|
||||
{
|
||||
if (NULL == m_pGCSController)
|
||||
{
|
||||
asynPrint(pasynUser, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"PIasynController::writeInt32() GCS controller not initialized!\n");
|
||||
|
||||
return asynError;
|
||||
}
|
||||
m_pGCSController->m_pCurrentLogSink = pasynUser;
|
||||
int function = pasynUser->reason;
|
||||
asynStatus status = asynSuccess;
|
||||
PIasynAxis *pAxis = (PIasynAxis *)this->getAxis(pasynUser);
|
||||
static const char *functionName = "writeInt32";
|
||||
|
||||
lock();
|
||||
/* Set the parameter and readback in the parameter library. This may be overwritten when we read back the
|
||||
* status at the end, but that's OK */
|
||||
status = pAxis->setIntegerParam(function, value);
|
||||
|
||||
if (function == motorSetClosedLoop_)
|
||||
{
|
||||
asynPrint(pasynUser, ASYN_TRACE_FLOW,
|
||||
"%s:%s: %sing Closed-Loop Control flag on driver %s\n",
|
||||
value != 0.0?"Enabl":"Disabl",
|
||||
driverName, functionName, this->portName);
|
||||
status = m_pGCSController->setServo(pAxis, (value!=0)?1:0);
|
||||
|
||||
}
|
||||
else if (function == motorDeferMoves_)
|
||||
{
|
||||
asynPrint(pasynUser, ASYN_TRACE_FLOW,
|
||||
"%s:%s: %sing Deferred Move flag on driver %s\n",
|
||||
value != 0.0?"Sett":"Clear",
|
||||
driverName, functionName, this->portName);
|
||||
if (value == 0.0 && this->movesDeferred != 0)
|
||||
{
|
||||
processDeferredMoves();
|
||||
}
|
||||
this->movesDeferred = value;
|
||||
} else {
|
||||
/* Call base class call its method (if we have our parameters check this here) */
|
||||
status = asynMotorController::writeInt32(pasynUser, value);
|
||||
}
|
||||
unlock();
|
||||
/* Do callbacks so higher layers see any changes */
|
||||
pAxis->callParamCallbacks();
|
||||
if (status)
|
||||
asynPrint(pasynUser, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"%s:%s: error, status=%d function=%d, value=%d\n",
|
||||
driverName, functionName, status, function, value);
|
||||
else
|
||||
asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
|
||||
"%s:%s: function=%d, value=%d\n",
|
||||
driverName, functionName, function, value);
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus PIasynController::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
|
||||
{
|
||||
if (NULL == m_pGCSController)
|
||||
{
|
||||
asynPrint(pasynUser, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"PIasynController::writeFloat64() GCS controller not initialized!\n");
|
||||
|
||||
return asynError;
|
||||
}
|
||||
m_pGCSController->m_pCurrentLogSink = pasynUser;
|
||||
int function = pasynUser->reason;
|
||||
asynStatus status = asynSuccess;
|
||||
PIasynAxis *pAxis = (PIasynAxis *)this->getAxis(pasynUser);
|
||||
static const char *functionName = "writeFloat64";
|
||||
|
||||
/* Set the parameter and readback in the parameter library. This may be overwritten when we read back the
|
||||
* status at the end, but that's OK */
|
||||
status = pAxis->setDoubleParam(function, value);
|
||||
|
||||
if (function == PI_SUP_TARGET)
|
||||
{
|
||||
printf("PI_SUP_TargetAO: %f for axis %d\n", value, pAxis->axisNo_);
|
||||
}
|
||||
else if (function == PI_SUP_PIVOT_X)
|
||||
{
|
||||
status = m_pGCSController->SetPivotX(value);
|
||||
}
|
||||
else if (function == PI_SUP_PIVOT_Y)
|
||||
{
|
||||
status = m_pGCSController->SetPivotY(value);
|
||||
}
|
||||
else if (function == PI_SUP_PIVOT_Z)
|
||||
{
|
||||
status = m_pGCSController->SetPivotZ(value);
|
||||
}
|
||||
else if (function == motorPosition_) // Entspricht das DFH ?
|
||||
{
|
||||
// pAxis->enc_offset = (double) value - pAxis->nextpoint.axis[0].p;
|
||||
asynPrint(pasynUser, ASYN_TRACE_FLOW,
|
||||
"%s:%s: Set axis %d to position %d",
|
||||
driverName, functionName, pAxis->axisNo_, value);
|
||||
}
|
||||
else if (function == motorResolution_ )
|
||||
{
|
||||
/* Call base class call its method (if we have our parameters check this here) */
|
||||
status = asynMotorController::writeFloat64(pasynUser, value);
|
||||
}
|
||||
else if (function == motorEncRatio_ )
|
||||
{
|
||||
/* Call base class call its method (if we have our parameters check this here) */
|
||||
status = asynMotorController::writeFloat64(pasynUser, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call base class call its method (if we have our parameters check this here) */
|
||||
status = asynMotorController::writeFloat64(pasynUser, value);
|
||||
}
|
||||
/* Do callbacks so higher layers see any changes */
|
||||
pAxis->callParamCallbacks();
|
||||
if (status)
|
||||
asynPrint(pasynUser, ASYN_TRACE_ERROR|ASYN_TRACE_FLOW,
|
||||
"%s:%s: error, status=%d function=%d, value=%f\n",
|
||||
driverName, functionName, status, function, value);
|
||||
else
|
||||
asynPrint(pasynUser, ASYN_TRACEIO_DRIVER,
|
||||
"%s:%s: function=%d, value=%f\n",
|
||||
driverName, functionName, function, value);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
asynStatus PIasynController::profileMove(asynUser *pasynUser, int npoints, double positions[], double times[], int relative, int trigger )
|
||||
{
|
||||
asynPrint(pasynUser, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
|
||||
"PIasynController::profileMove() - not implemented\n");
|
||||
return asynError;
|
||||
}
|
||||
|
||||
asynStatus PIasynController::triggerProfile(asynUser *pasynUser)
|
||||
{
|
||||
asynPrint(pasynUser, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
|
||||
"PIasynController::profileMove() - not implemented\n");
|
||||
return asynError;
|
||||
}
|
||||
|
||||
asynStatus PIasynController::configAxis(PIasynAxis *pAxis)
|
||||
{
|
||||
asynUser* logSink = pasynManager->createAsynUser(0,0);
|
||||
asynStatus status = pasynManager->connectDevice(logSink, portName, pAxis->getAxisNo());
|
||||
if (status != asynSuccess)
|
||||
{
|
||||
asynPrint(logSink, ASYN_TRACE_FLOW|ASYN_TRACE_ERROR,
|
||||
"PIasynController::configAxis() - connectDevice() failed\n");
|
||||
return status;
|
||||
}
|
||||
m_pGCSController->m_pCurrentLogSink = logSink;
|
||||
|
||||
pAxis->setIntegerParam(motorAxisHasClosedLoop, 1);
|
||||
pAxis->callParamCallbacks();
|
||||
|
||||
m_pGCSController->initAxis(pAxis);
|
||||
double resolution;
|
||||
m_pGCSController->getResolution(pAxis, resolution);
|
||||
m_pGCSController->getAxisVelocity(pAxis);
|
||||
m_pGCSController->getAxisPositionCts(pAxis);
|
||||
pAxis->setDoubleParam(this->motorPosition_, pAxis->m_positionCts);
|
||||
pAxis->setDoubleParam(this->motorMoveAbs_, pAxis->m_positionCts);
|
||||
double negLimit, posLimit;
|
||||
m_pGCSController->getTravelLimits(pAxis, negLimit, posLimit);
|
||||
pAxis->setDoubleParam(this->motorLowLimit_, negLimit);
|
||||
pAxis->setDoubleParam(this->motorHighLimit_, posLimit);
|
||||
m_pGCSController->getReferencedState(pAxis);
|
||||
pAxis->setIntegerParam( this->motorStatusHomed_, pAxis->m_homed );
|
||||
|
||||
pasynManager->freeAsynUser(logSink);
|
||||
|
||||
/* Send a signal to the poller task which will make it do a poll,
|
||||
* updating values for this axis to use the new resolution (stepSize) */
|
||||
epicsEventSignal(pollEventId_);
|
||||
|
||||
return(asynSuccess);
|
||||
}
|
||||
|
||||
/**\defgroup PIasynTask Routines to implement the motor axis simulation task
|
||||
@{
|
||||
*/
|
||||
|
||||
/** Process one iteration of an axis
|
||||
|
||||
This routine takes a single axis and propogates its motion forward a given amount
|
||||
of time.
|
||||
|
||||
\param pAxis [in] Pointer to axis information.
|
||||
\param delta [in] Time in seconds to propogate motion forwards.
|
||||
|
||||
\return Integer indicating 0 (asynSuccess) for success or non-zero for failure.
|
||||
*/
|
||||
|
||||
|
||||
//
|
||||
//static void PIasynTaskC(void *drvPvt)
|
||||
//{
|
||||
// PIasynController *pController = (PIasynController*)drvPvt;
|
||||
// pController->PIasynTask();
|
||||
//}
|
||||
//
|
||||
//
|
||||
//
|
||||
//void PIasynController::PIasynTask()
|
||||
//{
|
||||
// double timeout = m_idlePollingRate;
|
||||
// int axis;
|
||||
// PIasynAxis *pAxis;
|
||||
// epicsEventSignal(pollEventId_); /* Force on poll at startup */
|
||||
//
|
||||
// int status;
|
||||
// while ( 1 )
|
||||
// {
|
||||
// if (timeout != 0.) status = epicsEventWaitWithTimeout(pollEventId_, timeout);
|
||||
// else status = epicsEventWait(pollEventId_);
|
||||
//
|
||||
// lock();
|
||||
// m_pGCSController->getGlobalState(pAxes_, numAxes_);
|
||||
// unlock();
|
||||
//
|
||||
// bool bAnyAxisMoving = false;
|
||||
// for (axis=0; axis<this->numAxes_; axis++)
|
||||
// {
|
||||
// lock();
|
||||
// pAxis = getPIAxis(axis);
|
||||
// process(pAxis);
|
||||
// pAxis->callParamCallbacks();
|
||||
// unlock();
|
||||
// bAnyAxisMoving = (pAxis->m_bMoving != 0);
|
||||
// }
|
||||
// m_pGCSController->m_bAnyAxisMoving = bAnyAxisMoving;
|
||||
// if (m_pGCSController->m_bAnyAxisMoving)
|
||||
// timeout = m_movingPollingRate;
|
||||
// else
|
||||
// timeout = m_idlePollingRate;
|
||||
// }
|
||||
//}
|
||||
|
||||
asynStatus PIasynController::poll()
|
||||
{
|
||||
return m_pGCSController->getGlobalState(pAxes_, numAxes_);
|
||||
|
||||
setDoubleParam( 0, PI_SUP_RBPIVOT_X, m_pGCSController->GetPivotX());
|
||||
setDoubleParam( 0, PI_SUP_RBPIVOT_Y, m_pGCSController->GetPivotY());
|
||||
setDoubleParam( 0, PI_SUP_RBPIVOT_Z, m_pGCSController->GetPivotZ());
|
||||
|
||||
setIntegerParam( 0, PI_SUP_LAST_ERR, m_pGCSController->GetLastError() );
|
||||
|
||||
callParamCallbacks();
|
||||
}
|
||||
|
||||
|
||||
/** Configuration command, called directly or from iocsh */
|
||||
extern "C" int PI_GCS2_CreateController(const char *portName, const char* asynPort, int numAxes, int priority, int stackSize, int movingPollingRate, int idlePollingRate)
|
||||
{
|
||||
PIasynController *pasynController
|
||||
= new PIasynController(portName, asynPort, numAxes, priority, stackSize, movingPollingRate, idlePollingRate);
|
||||
pasynController = NULL;
|
||||
return(asynSuccess);
|
||||
}
|
||||
|
||||
/** Code for iocsh registration */
|
||||
static const iocshArg PI_GCS2_CreateControllerArg0 = {"Port name", iocshArgString};
|
||||
static const iocshArg PI_GCS2_CreateControllerArg1 = {"asyn Port name", iocshArgString};
|
||||
static const iocshArg PI_GCS2_CreateControllerArg2 = {"Number of axes", iocshArgInt};
|
||||
static const iocshArg PI_GCS2_CreateControllerArg3 = {"priority", iocshArgInt};
|
||||
static const iocshArg PI_GCS2_CreateControllerArg4 = {"stackSize", iocshArgInt};
|
||||
static const iocshArg PI_GCS2_CreateControllerArg5 = {"moving polling time [msec]", iocshArgInt};
|
||||
static const iocshArg PI_GCS2_CreateControllerArg6 = {"idle polling time [msec]", iocshArgInt};
|
||||
static const iocshArg * const PI_GCS2_CreateControllerArgs[] = {&PI_GCS2_CreateControllerArg0,
|
||||
&PI_GCS2_CreateControllerArg1,
|
||||
&PI_GCS2_CreateControllerArg2,
|
||||
&PI_GCS2_CreateControllerArg3,
|
||||
&PI_GCS2_CreateControllerArg4,
|
||||
&PI_GCS2_CreateControllerArg5,
|
||||
&PI_GCS2_CreateControllerArg6};
|
||||
static const iocshFuncDef PI_GCS2_CreateControllerDef = {"PI_GCS2_CreateController", 7, PI_GCS2_CreateControllerArgs};
|
||||
static void PI_GCS2_CreateControllerCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
PI_GCS2_CreateController(args[0].sval, args[1].sval, args[2].ival, args[3].ival, args[4].ival, args[5].ival, args[6].ival);
|
||||
}
|
||||
|
||||
|
||||
static void PIasynDriverRegister(void)
|
||||
{
|
||||
iocshRegister(&PI_GCS2_CreateControllerDef, PI_GCS2_CreateControllerCallFunc);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
epicsExportRegistrar(PIasynDriverRegister);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
FILENAME... PIasynController.cpp
|
||||
USAGE... Simulated Motor Support.
|
||||
|
||||
Based on drvMotorSim.c
|
||||
|
||||
Mark Rivers
|
||||
December 13, 2009
|
||||
|
||||
*/
|
||||
|
||||
#ifndef PI_ASYN_DRIVER_INCLUDED_
|
||||
#define PI_ASYN_DRIVER_INCLUDED_
|
||||
|
||||
#include "asynMotorController.h"
|
||||
#include "asynMotorAxis.h"
|
||||
|
||||
class PIasynAxis;
|
||||
class PIGCSController;
|
||||
|
||||
class PIasynController : asynMotorController {
|
||||
public:
|
||||
PIasynController(const char *portName, const char* asynPort, int numAxes, int priority, int stackSize, int movingPollPeriod, int idlePollPeriod);
|
||||
asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value);
|
||||
asynStatus writeFloat64(asynUser *pasynUser, epicsFloat64 value);
|
||||
void report(FILE *fp, int level);
|
||||
asynStatus profileMove(asynUser *pasynUser, int npoints, double positions[], double times[], int relative, int trigger);
|
||||
asynStatus triggerProfile(asynUser *pasynUser);
|
||||
asynStatus configAxis(PIasynAxis *pAxis);
|
||||
|
||||
PIasynAxis* getPIAxis(asynUser *pasynUser) { return (PIasynAxis*)asynMotorController::getAxis(pasynUser); }
|
||||
PIasynAxis* getPIAxis(int axisNo) { return (PIasynAxis*)asynMotorController::getAxis(axisNo); }
|
||||
|
||||
virtual asynStatus poll();
|
||||
|
||||
friend class PIasynAxis;
|
||||
|
||||
private:
|
||||
// void process(PIasynAxis *pAxis);
|
||||
epicsThreadId motorThread;
|
||||
int movesDeferred;
|
||||
//int numAxes;
|
||||
asynStatus processDeferredMoves();
|
||||
//PIasynAxis** m_pAxes;
|
||||
|
||||
PIGCSController* m_pGCSController;
|
||||
|
||||
int PI_SUP_POSITION;
|
||||
int PI_SUP_TARGET;
|
||||
int PI_SUP_SERVO;
|
||||
int PI_SUP_LAST_ERR;
|
||||
int PI_SUP_PIVOT_X;
|
||||
int PI_SUP_PIVOT_Y;
|
||||
int PI_SUP_PIVOT_Z;
|
||||
int PI_SUP_RBPIVOT_X;
|
||||
int PI_SUP_RBPIVOT_Y;
|
||||
int PI_SUP_RBPIVOT_Z;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#define PI_SUP_POSITION_String "PI_SUP_POSITION"
|
||||
#define PI_SUP_TARGET_String "PI_SUP_TARGET"
|
||||
#define PI_SUP_SERVO_String "PI_SUP_SERVO"
|
||||
#define PI_SUP_LAST_ERR_String "PI_SUP_LAST_ERR"
|
||||
#define PI_SUP_PIVOT_X_String "PI_SUP_PIVOT_X"
|
||||
#define PI_SUP_PIVOT_Y_String "PI_SUP_PIVOT_Y"
|
||||
#define PI_SUP_PIVOT_Z_String "PI_SUP_PIVOT_Z"
|
||||
#define PI_SUP_RBPIVOT_X_String "PI_SUP_RBPIVOT_X"
|
||||
#define PI_SUP_RBPIVOT_Y_String "PI_SUP_RBPIVOT_Y"
|
||||
#define PI_SUP_RBPIVOT_Z_String "PI_SUP_RBPIVOT_Z"
|
||||
|
||||
|
||||
typedef struct PIasynControllerNode {
|
||||
ELLNODE node;
|
||||
const char *portName;
|
||||
PIasynController *pController;
|
||||
} PIasynControllerNode;
|
||||
|
||||
#endif // PI_ASYN_DRIVER_INCLUDED_
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
Readme for PIasyn - EPICS support for PI GCS2 stages
|
||||
========================================================
|
||||
|
||||
The PIasyn driver is written to support PI motion controllers which
|
||||
support GCS2 (General Command Set) as commanding language.
|
||||
Currently this is implemented with different C++ classes where the
|
||||
differences and specialties are handled. This can be implemented
|
||||
by querying the controller what features are supported. So in future
|
||||
developments these classes may disappear.
|
||||
|
||||
Homing
|
||||
========
|
||||
|
||||
a) stages with absolute sensors
|
||||
Some PI stages, mostly piezo stages, use an absolute position sensor.
|
||||
The correct absolute position is known to the controller immediately after power up.
|
||||
For these stages homing is not necessary and thus not supported.
|
||||
These stages will ignore HOMF and HOMR.
|
||||
The HOME flag of the MSTA field is meaningless for these stages
|
||||
and HOMED is always true,
|
||||
|
||||
b) stages with incremental sensors
|
||||
Some PIStages needs to be referenced after controller power up. The state
|
||||
is reflected by the HOMED flag of MSTA. There are different ways to home
|
||||
a stage. The default is by using the reference switch. If a stage has
|
||||
a reference switch HOMF and HOMR will move to this switch. The direction is
|
||||
determined by the controller. The reference signal is edge based, so the controller
|
||||
can find out on which side of the reference the stage is and can move using
|
||||
the shortest path. HOMF and HOMR will trigger the same move. If the stage has
|
||||
no reference switch the built in limit switches can be used to determine the absolute
|
||||
position. In this case HOMF will send the stage to its positive limit switch and
|
||||
HOMR to its negative limit switch. As the reference is edge based or not present the
|
||||
HOME bit of the MSTA field is meaningless for these stages.
|
||||
|
||||
c) setting the homing velocity
|
||||
Reducing the velocity used for homing is usually done to improve the accuracy.
|
||||
PI controllers reach the reference every time from the same "side". So only this
|
||||
last approach is performed with the homing velocity set with HVEL. The coarse move
|
||||
to the proximity of the reference is done with the a velocity limited by the current
|
||||
velocity (set with VELO) and the maximum possible velocity to decelerate in case of
|
||||
hitting a limit switch.
|
||||
|
||||
"Motion Errors"
|
||||
=================
|
||||
|
||||
If the controller detects a "motion error", i.e. the difference between target and
|
||||
current position is greater than some given limit (also known as "following error"),
|
||||
the driver will set the PROBLEM bit in MSTA. Servo control is also switched off.
|
||||
The EA_POSITION bit of MSTA will reflect the "servo control" state. To re-enable
|
||||
servo control use CNEN.
|
||||
|
||||
|
||||
C-702
|
||||
=======
|
||||
|
||||
The C-702 controller uses an older "dialect" of GCS1.
|
||||
That's why at some points different parameter IDs are used and why there is no communication
|
||||
during homing. So the position cannot be updated during homing and will "jump" to the final
|
||||
position after homing is finished.
|
||||
|
||||
|
||||
+1075
File diff suppressed because it is too large
Load Diff
+3132
File diff suppressed because it is too large
Load Diff
Executable
+29
@@ -0,0 +1,29 @@
|
||||
# CONFIG - Load build configuration data
|
||||
#
|
||||
# Do not make changes to this file!
|
||||
|
||||
# Allow user to override where the build rules come from
|
||||
RULES = $(EPICS_BASE)
|
||||
|
||||
# RELEASE files point to other application tops
|
||||
include $(TOP)/configure/RELEASE
|
||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common
|
||||
ifdef T_A
|
||||
-include $(TOP)/configure/RELEASE.Common.$(T_A)
|
||||
-include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
endif
|
||||
|
||||
CONFIG = $(RULES)/configure
|
||||
include $(CONFIG)/CONFIG
|
||||
|
||||
# Override the Base definition:
|
||||
INSTALL_LOCATION = $(TOP)
|
||||
|
||||
# CONFIG_SITE files contain other build configuration settings
|
||||
include $(TOP)/configure/CONFIG_SITE
|
||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||
ifdef T_A
|
||||
-include $(TOP)/configure/CONFIG_SITE.Common.$(T_A)
|
||||
-include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
endif
|
||||
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
# CONFIG_SITE
|
||||
|
||||
# Make any application-specific changes to the EPICS build
|
||||
# configuration variables in this file.
|
||||
#
|
||||
# Host/target specific settings can be specified in files named
|
||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).Common
|
||||
# CONFIG_SITE.Common.$(T_A)
|
||||
# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
|
||||
# CHECK_RELEASE controls the consistency checking of the support
|
||||
# applications pointed to by the RELEASE* files.
|
||||
# Normally CHECK_RELEASE should be set to YES.
|
||||
# Set CHECK_RELEASE to NO to disable checking completely.
|
||||
# Set CHECK_RELEASE to WARN to perform consistency checking but
|
||||
# continue building anyway if conflicts are found.
|
||||
CHECK_RELEASE = YES
|
||||
|
||||
# Set this when you only want to compile this application
|
||||
# for a subset of the cross-compiled target architectures
|
||||
# that Base is built for.
|
||||
#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040
|
||||
|
||||
# To install files into a location other than $(TOP) define
|
||||
# INSTALL_LOCATION here.
|
||||
#INSTALL_LOCATION=</path/name/to/install/top>
|
||||
|
||||
# Set this when your IOC and the host use different paths
|
||||
# to access the application. This will be needed to boot
|
||||
# from a Microsoft FTP server or with some NFS mounts.
|
||||
# You must rebuild in the iocBoot directory for this to
|
||||
# take effect.
|
||||
#IOCS_APPL_TOP = </IOC/path/to/application/top>
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
TOP=..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
TARGETS = $(CONFIG_TARGETS)
|
||||
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
Executable
+36
@@ -0,0 +1,36 @@
|
||||
# RELEASE - Location of external support modules
|
||||
#
|
||||
# IF YOU MAKE ANY CHANGES to this file you must subsequently
|
||||
# do a "gnumake rebuild" in this application's top level
|
||||
# directory.
|
||||
#
|
||||
# The build process does not check dependencies against files
|
||||
# that are outside this application, thus you should do a
|
||||
# "gnumake rebuild" in the top level directory after EPICS_BASE
|
||||
# or any other external module pointed to below is rebuilt.
|
||||
#
|
||||
# Host- or target-specific settings can be given in files named
|
||||
# RELEASE.$(EPICS_HOST_ARCH).Common
|
||||
# RELEASE.Common.$(T_A)
|
||||
# RELEASE.$(EPICS_HOST_ARCH).$(T_A)
|
||||
#
|
||||
# This file should ONLY define paths to other support modules,
|
||||
# or include statements that pull in similar RELEASE files.
|
||||
# Build settings that are NOT module paths should appear in a
|
||||
# CONFIG_SITE file.
|
||||
|
||||
TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
|
||||
|
||||
# If using the sequencer, point SNCSEQ at its top directory:
|
||||
#SNCSEQ=$(EPICS_BASE)/../modules/soft/seq
|
||||
|
||||
# EPICS_BASE usually appears last so other apps can override stuff:
|
||||
EPICS_BASE=/home/sra/epics/base
|
||||
|
||||
# Set RULES here if you want to take build rules from somewhere
|
||||
# other than EPICS_BASE:
|
||||
#RULES=/path/to/epics/support/module/rules/x-y
|
||||
|
||||
ASYN=/home/sra/epics/synApps_5_6/support/asyn-4-18
|
||||
MOTOR=/home/sra/epics/synApps_5_6/support/motor-6-7
|
||||
|
||||
Executable
+6
@@ -0,0 +1,6 @@
|
||||
# RULES
|
||||
|
||||
include $(CONFIG)/RULES
|
||||
|
||||
# Library should be rebuilt because LIBOBJS may have changed.
|
||||
$(LIBNAME): ../Makefile
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#RULES.ioc
|
||||
include $(CONFIG)/RULES.ioc
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#RULES_DIRS
|
||||
include $(CONFIG)/RULES_DIRS
|
||||
Executable
+3
@@ -0,0 +1,3 @@
|
||||
#RULES_TOP
|
||||
include $(CONFIG)/RULES_TOP
|
||||
|
||||
Reference in New Issue
Block a user