mirror of
https://github.com/Binary-Coalescence/motorDSM.git
synced 2025-08-05 06:05:40 -05:00
Compare commits
91 Commits
R1-1-1
...
documentat
Author | SHA1 | Date | |
---|---|---|---|
75a1ff060d | |||
f85ae07d2b | |||
3ecb9676c0 | |||
03a93101c1 | |||
95c227a553 | |||
3614a806ea
|
|||
b25f608e98
|
|||
![]() |
841b6f5b41 | ||
2379c90d90 | |||
cf26f426df | |||
c1025d711b | |||
8fc33fa14d
|
|||
05a223bd17
|
|||
5d706d4879
|
|||
707850e879
|
|||
8ec61fb3dc
|
|||
90b0fa8836
|
|||
40cfb47f05
|
|||
1a4794a9b2
|
|||
a3d6a24a01
|
|||
c8dbd0916d
|
|||
e9ca810318
|
|||
bf7b557dd7
|
|||
0600cba84d
|
|||
51fceaf7d7
|
|||
66ef37cb10
|
|||
200b68857d
|
|||
d0532c2552
|
|||
45c8ff064e
|
|||
4351ab56e3
|
|||
a90eea829a
|
|||
7b9f2870ca
|
|||
f73608c596
|
|||
19731d2f37
|
|||
a4012dda64
|
|||
c812afbe4e
|
|||
7551465733
|
|||
bdec17808a
|
|||
29a78e1023
|
|||
c930a77811
|
|||
df98f6667a
|
|||
37d22e58dd
|
|||
8c053dfa62
|
|||
4ab244925d
|
|||
5d343b33d1
|
|||
0d84bb4a29
|
|||
448e26ac23
|
|||
19467e5b5b
|
|||
402584345f
|
|||
c5eebd9597
|
|||
341bbb5980
|
|||
71ae063b23
|
|||
b8b090a804
|
|||
273e545759
|
|||
ba71c79a92
|
|||
996439589a
|
|||
d412000373
|
|||
9fa37e8cd0
|
|||
9a3d3d773d
|
|||
6c841c9041
|
|||
9403c24df0
|
|||
7b3675fbdf
|
|||
a1827ca152
|
|||
c2cbaf6bfd
|
|||
1b366684d0
|
|||
8101fcae72
|
|||
629c55bba4
|
|||
b616133ace
|
|||
c1ffe8b805
|
|||
c11e11659b
|
|||
b56a1f9a35
|
|||
4837e8f597
|
|||
0c32dd28eb
|
|||
0841ff3e15
|
|||
1205814767
|
|||
67eee854c0
|
|||
a4d5388531
|
|||
07f07d16ad
|
|||
a43acb8537
|
|||
d24486dfb4
|
|||
a2d7256948
|
|||
4615467616
|
|||
417802a9b4
|
|||
a92fda6560
|
|||
7d7774072c
|
|||
b03cda55ac
|
|||
eec0a1d8f0
|
|||
2df164b697
|
|||
c9db06b418
|
|||
fd6b276fc9
|
|||
4a9b6a91e0
|
1
.ci
1
.ci
Submodule .ci deleted from 5764601630
@@ -1,3 +0,0 @@
|
||||
BASE=3.14
|
||||
|
||||
include modules
|
@@ -1,3 +0,0 @@
|
||||
BASE=3.15
|
||||
|
||||
include modules
|
@@ -1,3 +0,0 @@
|
||||
BASE=7.0
|
||||
|
||||
include modules
|
@@ -1,70 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import re
|
||||
|
||||
# Setup ANSI Colors (copied from cue.py)
|
||||
ANSI_RED = "\033[31;1m"
|
||||
ANSI_GREEN = "\033[32;1m"
|
||||
ANSI_YELLOW = "\033[33;1m"
|
||||
ANSI_BLUE = "\033[34;1m"
|
||||
ANSI_MAGENTA = "\033[35;1m"
|
||||
ANSI_CYAN = "\033[36;1m"
|
||||
ANSI_RESET = "\033[0m"
|
||||
ANSI_CLEAR = "\033[0K"
|
||||
|
||||
def cat(filename):
|
||||
'''
|
||||
Print the contents of a file
|
||||
'''
|
||||
with open(filename, 'r') as fh:
|
||||
for line in fh:
|
||||
print(line.strip())
|
||||
|
||||
def sanity_check(filename):
|
||||
'''
|
||||
Include the contents of a file in the github-actions log
|
||||
'''
|
||||
print("{}Contents of {}{}".format(ANSI_BLUE, filename, ANSI_RESET))
|
||||
cat(filename)
|
||||
print("{}End of {}{}".format(ANSI_BLUE, filename, ANSI_RESET))
|
||||
|
||||
if 'HOME' in os.environ:
|
||||
# Linux & OS X
|
||||
cache_dir = os.path.join(os.environ['HOME'], ".cache")
|
||||
else:
|
||||
# Windows
|
||||
cache_dir = os.path.join(os.environ['HOMEDRIVE'], os.environ['HOMEPATH'], ".cache")
|
||||
|
||||
module_dir = os.getenv('GITHUB_WORKSPACE')
|
||||
|
||||
# Copy the github-actions RELEASE.local to the configure dir
|
||||
filename = "configure/RELEASE.local"
|
||||
shutil.copy("{}/RELEASE.local".format(cache_dir), filename)
|
||||
|
||||
# Get the variable from the example release file
|
||||
example = "configure/EXAMPLE_RELEASE.local"
|
||||
fh = open(example, "r")
|
||||
lines = fh.readlines()
|
||||
fh.close()
|
||||
pObj = re.compile('(MOTOR_[^=]+)')
|
||||
module_var = None
|
||||
for line in lines:
|
||||
mObj = pObj.match(line)
|
||||
if mObj != None:
|
||||
module_var = mObj.group()
|
||||
break
|
||||
|
||||
# Add the path to the driver module to the RELEASE.local file, since it is needed by the example IOC
|
||||
fh = open(filename, "a")
|
||||
fh.write("{}={}\n".format(module_var, module_dir))
|
||||
fh.close()
|
||||
sanity_check(filename)
|
||||
|
||||
# Enable the building of example IOCs
|
||||
filename = "configure/CONFIG_SITE.local"
|
||||
fh = open(filename, 'w')
|
||||
fh.write("BUILD_IOCS = YES")
|
||||
fh.close()
|
||||
sanity_check(filename)
|
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import pprint
|
||||
|
||||
pprint.pprint(dict(os.environ), width = 1)
|
||||
|
||||
#!print("{}", breakmehere)
|
||||
|
@@ -1,9 +0,0 @@
|
||||
MODULES="sncseq ipac asyn autosave busy motor"
|
||||
|
||||
SNCSEQ=R2-2-9
|
||||
IPAC=master
|
||||
ASYN=R4-42
|
||||
AUTOSAVE=R5-10-2
|
||||
BUSY=R1-7-3
|
||||
MOTOR=master
|
||||
MOTOR_RECURSIVE=NO
|
@@ -1,43 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
# ugly hack: copy cue.py so that it can be imported
|
||||
shutil.copy('.ci/cue.py', '.ci-local/travis')
|
||||
from cue import *
|
||||
|
||||
def cat(filename):
|
||||
'''
|
||||
Print the contents of a file
|
||||
'''
|
||||
with open(filename, 'r') as fh:
|
||||
for line in fh:
|
||||
print(line.strip())
|
||||
|
||||
def sanity_check(filename):
|
||||
'''
|
||||
Include the contents of a file in the travis log
|
||||
'''
|
||||
print("{}Contents of {}{}".format(ANSI_BLUE, filename, ANSI_RESET))
|
||||
cat(filename)
|
||||
print("{}End of {}{}".format(ANSI_BLUE, filename, ANSI_RESET))
|
||||
|
||||
# Add the path to the driver module to the RELEASE.local file, since it is needed by the example IOC
|
||||
update_release_local('MOTOR_ACS', os.getenv('TRAVIS_BUILD_DIR'))
|
||||
|
||||
# Copy the travis RELEASE.local to the configure dir
|
||||
filename = "configure/RELEASE.local"
|
||||
shutil.copy("{}/RELEASE.local".format(cachedir), filename)
|
||||
sanity_check(filename)
|
||||
|
||||
# Enable the building of example IOCs
|
||||
filename = "configure/CONFIG_SITE.local"
|
||||
fh = open(filename, 'w')
|
||||
fh.write("BUILD_IOCS = YES")
|
||||
fh.close()
|
||||
sanity_check(filename)
|
||||
|
||||
# Remove cue.py
|
||||
os.remove('.ci-local/travis/cue.py')
|
||||
os.remove('.ci-local/travis/cue.pyc')
|
211
.github/workflows/ci-scripts-build-full.yml
vendored
211
.github/workflows/ci-scripts-build-full.yml
vendored
@@ -1,211 +0,0 @@
|
||||
# .github/workflows/ci-scripts-build.yml for use with EPICS Base ci-scripts
|
||||
# (see: https://github.com/epics-base/ci-scripts)
|
||||
|
||||
# This is YAML - indentation levels are crucial
|
||||
|
||||
# Set the 'name:' properties to values that work for you (MYMODULE)
|
||||
|
||||
name: "GHA full build"
|
||||
|
||||
# Only run manually
|
||||
on:
|
||||
workflow_dispatch
|
||||
|
||||
env:
|
||||
SETUP_PATH: .ci-local:.ci
|
||||
# For the sequencer on Linux/Windows/MacOS
|
||||
APT: re2c
|
||||
CHOCO: re2c
|
||||
BREW: re2c
|
||||
|
||||
jobs:
|
||||
build-base:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
# Set environment variables from matrix parameters
|
||||
env:
|
||||
CMP: ${{ matrix.cmp }}
|
||||
BCFG: ${{ matrix.configuration }}
|
||||
BASE: ${{ matrix.base }}
|
||||
WINE: ${{ matrix.wine }}
|
||||
RTEMS: ${{ matrix.rtems }}
|
||||
RTEMS_TARGET: ${{ matrix.rtems_target }}
|
||||
EXTRA: ${{ matrix.extra }}
|
||||
TEST: ${{ matrix.test }}
|
||||
SET: ${{ matrix.set }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Job names also name artifacts, character limitations apply
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
wine: "64"
|
||||
base: "7.0"
|
||||
set: modules
|
||||
name: "Ub-20 gcc-9 + MinGW"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: static
|
||||
wine: "64"
|
||||
base: "7.0"
|
||||
set: modules
|
||||
name: "Ub-20 gcc-9 + MinGW, static"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: static
|
||||
extra: "CMD_CXXFLAGS=-std=c++11"
|
||||
base: "7.0"
|
||||
set: modules
|
||||
name: "Ub-20 gcc-9 C++11, static"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
cmp: clang
|
||||
configuration: default
|
||||
extra: "CMD_CXXFLAGS=-std=c++11"
|
||||
base: "7.0"
|
||||
set: modules
|
||||
name: "Ub-20 clang-10 C++11"
|
||||
|
||||
### fails building autosave
|
||||
#!- os: ubuntu-20.04
|
||||
#! cmp: gcc
|
||||
#! configuration: default
|
||||
#! rtems: "4.10"
|
||||
#! base: "7.0"
|
||||
#! set: modules
|
||||
#! name: "Ub-20 gcc-9 + RT-4.10"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
rtems: "4.9"
|
||||
base: "7.0"
|
||||
set: modules
|
||||
name: "Ub-20 gcc-9 + RT-4.9"
|
||||
|
||||
### fails building asyn
|
||||
#!- os: ubuntu-20.04
|
||||
#! cmp: gcc
|
||||
#! configuration: default
|
||||
#! rtems: "5"
|
||||
#! rtems_target: RTEMS-pc686-qemu
|
||||
#! base: "7.0"
|
||||
#! set: modules
|
||||
#! name: "Ub-20 gcc-9 + RT-5.1 pc686"
|
||||
|
||||
### fails building autosave
|
||||
#!- os: ubuntu-20.04
|
||||
#! cmp: gcc
|
||||
#! configuration: default
|
||||
#! rtems: "5"
|
||||
#! rtems_target: RTEMS-beatnik
|
||||
#! test: NO
|
||||
#! base: "7.0"
|
||||
#! set: modules
|
||||
#! name: "Ub-20 gcc-9 + RT-5.1 beatnik"
|
||||
|
||||
- os: ubuntu-18.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
base: "7.0"
|
||||
set: modules
|
||||
name: "Ub-18 gcc-7"
|
||||
|
||||
### g++-8 not found
|
||||
#!- os: ubuntu-18.04
|
||||
#! cmp: gcc-8
|
||||
#! utoolchain: true
|
||||
#! configuration: default
|
||||
#! base: "7.0"
|
||||
#! set: modules
|
||||
#! name: "Ub-18 gcc-8"
|
||||
|
||||
#!- os: ubuntu-20.04
|
||||
#! cmp: gcc-8
|
||||
#! utoolchain: true
|
||||
#! configuration: default
|
||||
#! base: "7.0"
|
||||
#! set: modules
|
||||
#! name: "Ub-20 gcc-8"
|
||||
|
||||
- os: ubuntu-20.04
|
||||
cmp: clang
|
||||
configuration: default
|
||||
base: "7.0"
|
||||
set: modules
|
||||
name: "Ub-20 clang-10"
|
||||
|
||||
- os: macos-latest
|
||||
cmp: clang
|
||||
configuration: default
|
||||
base: "7.0"
|
||||
set: modules
|
||||
name: "MacOS clang-12"
|
||||
|
||||
- os: windows-2019
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
base: "7.0"
|
||||
set: modules
|
||||
name: "Win2019 MinGW"
|
||||
|
||||
- os: windows-2019
|
||||
cmp: gcc
|
||||
configuration: static
|
||||
base: "7.0"
|
||||
set: modules
|
||||
name: "Win2019 MinGW, static"
|
||||
|
||||
- os: windows-2019
|
||||
cmp: vs2019
|
||||
configuration: default
|
||||
base: "7.0"
|
||||
set: modules
|
||||
name: "Win2019 MSC-19"
|
||||
|
||||
- os: windows-2019
|
||||
cmp: vs2019
|
||||
configuration: static
|
||||
base: "7.0"
|
||||
set: modules
|
||||
name: "Win2019 MSC-19, static"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Automatic core dumper analysis
|
||||
uses: mdavidsaver/ci-core-dumper@master
|
||||
- name: "apt-get install"
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install qemu-system-x86 g++-mingw-w64-x86-64 gdb
|
||||
if: runner.os == 'Linux'
|
||||
- name: "apt-get install ${{ matrix.cmp }}"
|
||||
run: |
|
||||
sudo apt-get -y install software-properties-common
|
||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install ${{ matrix.cmp }}
|
||||
if: matrix.utoolchain
|
||||
- name: Sanity Check
|
||||
run: python .ci-local/github-actions/sanity-check.py
|
||||
- name: Prepare and compile dependencies
|
||||
run: python .ci/cue.py prepare
|
||||
- name: Patch main module
|
||||
run: python .ci-local/github-actions/post-prepare.py
|
||||
- name: Build main module
|
||||
run: python .ci/cue.py build
|
||||
- name: Run main module tests
|
||||
run: python .ci/cue.py test
|
||||
- name: Upload tapfiles Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: tapfiles ${{ matrix.name }}
|
||||
path: '**/O.*/*.tap'
|
||||
- name: Collect and show test results
|
||||
run: python .ci/cue.py test-results
|
109
.github/workflows/ci-scripts-build.yml
vendored
109
.github/workflows/ci-scripts-build.yml
vendored
@@ -1,109 +0,0 @@
|
||||
# .github/workflows/ci-scripts-build.yml for use with EPICS Base ci-scripts
|
||||
# (see: https://github.com/epics-base/ci-scripts)
|
||||
|
||||
# This is YAML - indentation levels are crucial
|
||||
|
||||
# Set the 'name:' properties to values that work for you (MYMODULE)
|
||||
|
||||
name: "GHA build"
|
||||
|
||||
# Trigger on pushes to the master branch and PRs
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'documentation/*'
|
||||
- '**/*.html'
|
||||
- '**/*.md'
|
||||
- '.github/workflows/ci-scripts-build-full.yml'
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'documentation/*'
|
||||
- '**/*.html'
|
||||
- '**/*.md'
|
||||
- '.github/workflows/ci-scripts-build-full.yml'
|
||||
|
||||
env:
|
||||
SETUP_PATH: .ci-local:.ci
|
||||
# For the sequencer on Linux/Windows/MacOS
|
||||
APT: re2c
|
||||
CHOCO: re2c
|
||||
BREW: re2c
|
||||
|
||||
jobs:
|
||||
build-base:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
# Set environment variables from matrix parameters
|
||||
env:
|
||||
CMP: ${{ matrix.cmp }}
|
||||
BCFG: ${{ matrix.configuration }}
|
||||
BASE: ${{ matrix.base }}
|
||||
WINE: ${{ matrix.wine }}
|
||||
RTEMS: ${{ matrix.rtems }}
|
||||
RTEMS_TARGET: ${{ matrix.rtems_target }}
|
||||
EXTRA: ${{ matrix.extra }}
|
||||
TEST: ${{ matrix.test }}
|
||||
SET: ${{ matrix.set }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
# Job names also name artifacts, character limitations apply
|
||||
include:
|
||||
- os: ubuntu-20.04
|
||||
cmp: gcc
|
||||
configuration: default
|
||||
base: "7.0"
|
||||
set: modules
|
||||
name: "7.0 Ub-20 gcc-9"
|
||||
|
||||
- os: macos-latest
|
||||
cmp: clang
|
||||
configuration: default
|
||||
base: "3.15"
|
||||
set: modules
|
||||
name: "3.15 MacOS clang-12"
|
||||
|
||||
- os: windows-2019
|
||||
cmp: vs2019
|
||||
configuration: static
|
||||
base: "3.15"
|
||||
set: modules
|
||||
name: "3.15 Win VS2019, static"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Automatic core dumper analysis
|
||||
uses: mdavidsaver/ci-core-dumper@master
|
||||
- name: "apt-get install"
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install qemu-system-x86 g++-mingw-w64-x86-64 gdb
|
||||
if: runner.os == 'Linux'
|
||||
- name: "apt-get install ${{ matrix.cmp }}"
|
||||
run: |
|
||||
sudo apt-get -y install software-properties-common
|
||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install ${{ matrix.cmp }}
|
||||
if: matrix.utoolchain
|
||||
- name: Sanity Check
|
||||
run: python .ci-local/github-actions/sanity-check.py
|
||||
- name: Prepare and compile dependencies
|
||||
run: python .ci/cue.py prepare
|
||||
- name: Patch main module
|
||||
run: python .ci-local/github-actions/post-prepare.py
|
||||
- name: Build main module
|
||||
run: python .ci/cue.py build
|
||||
- name: Run main module tests
|
||||
run: python .ci/cue.py test
|
||||
- name: Upload tapfiles Artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: tapfiles ${{ matrix.name }}
|
||||
path: '**/O.*/*.tap'
|
||||
- name: Collect and show test results
|
||||
run: python .ci/cue.py test-results
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
*~
|
||||
O.*
|
||||
*.swp
|
||||
*.bak
|
||||
*BAK.adl
|
||||
bin/
|
||||
db/
|
||||
@@ -16,3 +17,4 @@ auto_settings.sav*
|
||||
auto_positions.sav*
|
||||
.ccfxprepdir/
|
||||
*.local
|
||||
*_history
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule ".ci"]
|
||||
path = .ci
|
||||
url = https://github.com/epics-base/ci-scripts
|
143
.travis.yml
143
.travis.yml
@@ -1,143 +0,0 @@
|
||||
# .travis.xml for use with EPICS Base ci-scripts
|
||||
# (see: https://github.com/epics-base/ci-scripts)
|
||||
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
dist: xenial
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.cache
|
||||
|
||||
env:
|
||||
global:
|
||||
- SETUP_PATH=.ci-local:.ci
|
||||
# for the sequencer on Windows
|
||||
- CHOCO=re2c
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
# for all EPICS builds
|
||||
- libreadline6-dev
|
||||
- libncurses5-dev
|
||||
- perl
|
||||
# for clang compiler
|
||||
- clang
|
||||
# for mingw builds (32bit and 64bit)
|
||||
- g++-mingw-w64-i686
|
||||
- g++-mingw-w64-x86-64
|
||||
# for RTEMS cross builds
|
||||
- qemu-system-x86
|
||||
homebrew:
|
||||
packages:
|
||||
# for the sequencer
|
||||
- re2c
|
||||
update: true
|
||||
|
||||
install:
|
||||
- python .ci/cue.py prepare
|
||||
# ugly hacks go here:
|
||||
- python .ci-local/travis/post-prepare.py
|
||||
|
||||
script:
|
||||
- python .ci/cue.py build
|
||||
- python .ci/cue.py test
|
||||
- python .ci/cue.py test-results
|
||||
|
||||
# If you need to do more during install and build,
|
||||
# add a local directory to your module and do e.g.
|
||||
# - ./.ci-local/travis/install-extras.sh
|
||||
|
||||
# Define build jobs
|
||||
|
||||
# Well-known variables to use
|
||||
# SET source setup file
|
||||
# EXTRA content will be added to make command line
|
||||
# STATIC set to YES for static build (default: NO)
|
||||
# TEST set to NO to skip running the tests (default: YES)
|
||||
# VV set to make build scripts verbose (default: unset)
|
||||
|
||||
# Usually from setup files, but may be specified or overridden
|
||||
# on a job line
|
||||
# MODULES list of dependency modules
|
||||
# BASE branch or release tag name of the EPICS Base to use
|
||||
# <MODULE> branch or release tag for a specific module
|
||||
# ... see README for setup file syntax description
|
||||
|
||||
jobs:
|
||||
include:
|
||||
|
||||
# Older Base releases
|
||||
|
||||
- env: SET=base3-14
|
||||
|
||||
- env: SET=base3-14 BCFG=static
|
||||
|
||||
- env: SET=base3-15
|
||||
|
||||
- env: SET=base3-15 BCFG=static
|
||||
|
||||
# Default gcc, static build
|
||||
|
||||
- env: SET=base7-0
|
||||
|
||||
- env: SET=base7-0 BCFG=static
|
||||
|
||||
# Default clang build
|
||||
|
||||
- env: SET=base7-0
|
||||
compiler: clang
|
||||
|
||||
- env: SET=base7-0 EXTRA="CMD_CXXFLAGS=-std=c++11"
|
||||
compiler: clang
|
||||
|
||||
# Trusty: compiler versions very close to RHEL 7
|
||||
|
||||
- env: SET=base7-0
|
||||
dist: trusty
|
||||
|
||||
- env: SET=base7-0 BCFG=debug
|
||||
dist: trusty
|
||||
|
||||
# Other gcc versions (added as an extra package)
|
||||
|
||||
- env: SET=base7-0
|
||||
compiler: gcc-6
|
||||
addons: { apt: { packages: ["g++-6"], sources: ["ubuntu-toolchain-r-test"] } }
|
||||
|
||||
- env: SET=base7-0
|
||||
compiler: gcc-7
|
||||
addons: { apt: { packages: ["g++-7"], sources: ["ubuntu-toolchain-r-test"] } }
|
||||
|
||||
# Cross-compilations to Windows using MinGW and WINE
|
||||
|
||||
- env: SET=base7-0 WINE=32 TEST=NO BCFG=static
|
||||
|
||||
- env: SET=base7-0 WINE=64 TEST=NO
|
||||
|
||||
# Windows builds
|
||||
|
||||
- env: SET=base7-0
|
||||
os: windows
|
||||
compiler: vs2017
|
||||
|
||||
- env: SET=base7-0 BCFG=static
|
||||
os: windows
|
||||
compiler: vs2017
|
||||
|
||||
- env: SET=base7-0 BCFG=debug
|
||||
os: windows
|
||||
compiler: vs2017
|
||||
|
||||
# MacOS build
|
||||
|
||||
- env: SET=base7-0
|
||||
os: osx
|
||||
compiler: clang
|
||||
|
||||
# Cross-compilation to RTEMS
|
||||
|
||||
- env: SET=base7-0 RTEMS=4.9
|
||||
|
||||
- env: SET=base7-0 RTEMS=4.10
|
232
README.md
232
README.md
@@ -1,11 +1,229 @@
|
||||
# motorAcs
|
||||
EPICS motor drivers for the following [Advanced Control Systems Corporation](http://www.acsmotion.com) controllers: MCB-4B
|
||||
motorDSM
|
||||
==========
|
||||
|
||||
[](https://github.com/epics-motor/motorAcs/actions/workflows/ci-scripts-build.yml)
|
||||
<!--[](https://travis-ci.org/epics-motor/motorAcs)-->
|
||||
EPICS motor drivers for the following [Dynamic Structures and Materials](https://www.dynamic-structures.com/) motor controllers: MD-90
|
||||
|
||||
motorAcs is a submodule of [motor](https://github.com/epics-modules/motor). When motorAcs is built in the ``motor/modules`` directory, no manual configuration is needed.
|
||||
motorDSM is a submodule of [motor](https://github.com/epics-modules/motor). When motorDSM is built in the ``motor/modules`` directory, no manual configuration is needed.
|
||||
|
||||
motorAcs can also be built outside of motor by copying it's ``EXAMPLE_RELEASE.local`` file to ``RELEASE.local`` and defining the paths to ``MOTOR`` and itself.
|
||||
motorDSM can also be built outside of motor by copying it's ``configure/EXAMPLE_RELEASE.local`` file to ``RELEASE.local`` and defining the paths to ``EPICS_BASE``, ``MOTOR``, and itself.
|
||||
|
||||
motorDSM contains an example IOC that is built if ``configure/CONFIG_SITE.local`` sets ``BUILD_IOCS = YES``. The example IOC can be built outside of the driver module. Copy ``iocs/dsmIOC/configure/EXAMPLE_RELEASE.local`` to ``RELEASE.local`` and uncomment and set the paths for the appropriate lines depending on whether motorDSM was built inside the motor module or independently.
|
||||
|
||||
# Running an example IOC
|
||||
|
||||
To run the example IOC, build the packages listed below, then:
|
||||
|
||||
1. Follow the steps in "Configuring the system for attached controllers" below.
|
||||
2. Set the "EPICS_CA_ADDR_LIST" environment variable to include the IP address of the server.
|
||||
If it's running on the same computer, you can use the loopback IP address.
|
||||
`export EPICS_CA_ADDR_LIST='127.0.0.1'`
|
||||
3. In the ``iocs/dsmIOC/iocBoot/iocDsm`` directory, run
|
||||
```
|
||||
$ ../../bin/linux-x86_64/dsm st.cmd.md90
|
||||
```
|
||||
|
||||
for one attached MD-90 controller, or
|
||||
```
|
||||
$ ../../bin/linux-x86_64/dsm st.cmd.md90.multi
|
||||
```
|
||||
for eight attached MD-90 controllers. Edit this file to use more than one unit; simply comment out the ones you don't need.
|
||||
|
||||
4. Test using the `caget` and `caput` arguments as described in the "Example usage" section below.
|
||||
|
||||
# Configuring the system for attached controllers
|
||||
-------------------------------------------------
|
||||
|
||||
The following steps must be used in either st.cmd.md90 (for a single unit) or in st.cmd.md90.multiple (for multiple units).
|
||||
st.cmd.md90.multiple includes 8 motors predefined on /dev/ttyUSB0 through /dev/ttyUSB7. Comment out all motors you don't need.
|
||||
|
||||
**1. Define a new serial port named "serial0" and set the location of the physical port**
|
||||
`drvAsynSerialPortConfigure([serial name], [device location], 0, 0, 0)`
|
||||
*e.g., `drvAsynSerialPortConfigure("serial0", "/dev/ttyUSB0", 0, 0, 0)`*
|
||||
|
||||
**2. Configure the port**
|
||||
- Baud = 115200
|
||||
- Bits = 8
|
||||
- Parity = none
|
||||
- Stop bits = 1
|
||||
- Input end of message: "\r"
|
||||
- Output end of message: "\r"
|
||||
- Trace IO mask: 2
|
||||
```
|
||||
asynSetOption([serial name], 0, "baud", "115200")
|
||||
asynSetOption([serial name], 0, "bits", "8")
|
||||
asynSetOption([serial name], 0, "parity", "none")
|
||||
asynSetOption([serial name], 0, "stop", "1")
|
||||
asynOctetSetInputEos("serial0", 0, "\r")
|
||||
asynOctetSetOutputEos("serial0", 0, "\r")
|
||||
asynSetTraceIOMask("serial0", 0, 2)
|
||||
```
|
||||
where `[serial name]` is the name you assigned in step 1, surrounded by double quotes.
|
||||
|
||||
**3. Set initial parameters**
|
||||
- Power supply enabled (`EPS` command)
|
||||
- Deadband = 10 nm (`SDB 10` command)
|
||||
```
|
||||
asynOctetConnect("initConnection", [serial name], 0)
|
||||
asynOctetWrite("initConnection", "EPS")
|
||||
asynOctetWrite("initConnection", "SDB 10")
|
||||
asynOctetDisconnect('initConnection')
|
||||
```
|
||||
|
||||
**4. Create MD90 Controller object**
|
||||
`MD90CreateController([controller name], [serial name], 1, 100, 5000)`
|
||||
where `[controller name]` is the name of the motor to assign. Convention is to use "MD90n", starting with n=0.
|
||||
|
||||
**5. Intialize the IOC**
|
||||
After the call to `iocInit` (still in the st.cmd.md90[.multiple] file), issue the following commands for each motor. The example below uses `DSM:m0` but it should be run for each line described in motor.substitutions.md90 (or motor.substitutions.md90.multiple).
|
||||
````
|
||||
dbpf("DSM:m0.RTRY", "0") #sets retries to 0; this is automatic on the MD90
|
||||
dbpf("DSM:m0.TWV", "0.1") #Tweak distance
|
||||
dbpf("DSM:m0.VMAX", "1.0") #Sets max velocity to 1 mm/s
|
||||
dbpf("DSM:m0.HVEL", "1.0") #Sets max velocity to 1 mm/s
|
||||
````
|
||||
|
||||
**6. Update the substitutions file**
|
||||
Save and close the st.cmd file you've been configuring, then open the motor substitutions file (motor.substitutions.md90[.multiple]).
|
||||
Ensure the values in the `pattern` block's `PORT` field match the names used in the std.cmd file.
|
||||
Note that, despite this field being called "Port", they use the names of the MD90 Controller object defined above (by default, MD900, MD901, etc.
|
||||
Do __not__ use the direct serial port names (by default, serial0, serial1, etc.).
|
||||
|
||||
|
||||
# Compiling motorDSM
|
||||
|
||||
------------------------
|
||||
|
||||
To set up a full EPICS stack for development and testing, install and configure all of the following dependencies:
|
||||
|
||||
------------------------
|
||||
epics-base
|
||||
------------------------
|
||||
|
||||
Install make, gcc, and perl packages if not already installed, then clone and build epics-base:
|
||||
|
||||
$ export SUPPORT=/path/to/install/directory
|
||||
$ cd $SUPPORT
|
||||
$ git clone git@github.com:epics-base/epics-base.git
|
||||
$ cd epics-base
|
||||
$ make distclean
|
||||
$ make
|
||||
|
||||
|
||||
------------------------
|
||||
asyn
|
||||
------------------------
|
||||
|
||||
$ cd $SUPPORT
|
||||
$ git clone git@github.com:epics-modules/asyn.git
|
||||
|
||||
You may need to install (on Arch Linux) ``rpcsvc-proto`` package to get ``rpcgen`` binary needed to make asyn.
|
||||
|
||||
In ``asyn/configure``, create the file ``RELEASE.local`` with contents:
|
||||
SUPPORT=/path/to/install/directory
|
||||
EPICS_BASE=/path/to/epics-base
|
||||
|
||||
In ``asyn/configure``, create ``CONFIG_SITE.local`` file with the line:
|
||||
TIRPC=YES
|
||||
if appropriate header files are in ``/usr/include/tirpc/rpc`` instead of ``/usr/include/rpc``.
|
||||
|
||||
$ cd $SUPPORT/asyn
|
||||
$ make clean
|
||||
$ make
|
||||
|
||||
|
||||
------------------------
|
||||
seq
|
||||
------------------------
|
||||
|
||||
$ cd $SUPPORT
|
||||
$ git clone git@github.com:ISISComputingGroup/EPICS-seq.git seq
|
||||
|
||||
Install the ``re2c`` package (Arch) if needed.
|
||||
|
||||
Create ``seq/configure/RELEASE.local`` and set path for ``EPICS_BASE``. (Note this package seems to forget to git-ignore the .local file.)
|
||||
|
||||
Edit ``seq/configure/RELEASE`` to add the missing '-' before the ``include`` for ``ISIS_CONFIG`` on the next to last line. This seems to be a typo.
|
||||
|
||||
$ cd $SUPPORT/seq
|
||||
$ make clean
|
||||
$ make
|
||||
|
||||
|
||||
------------------------
|
||||
motor
|
||||
------------------------
|
||||
|
||||
$ cd $SUPPORT
|
||||
$ git clone git@github.com:epics-modules/motor.git
|
||||
|
||||
Create ``motor/configure/RELEASE.local`` and set ``SUPPORT``, ``ASYN``, ``SNCSEQ``, and ``EPICS_BASE`` to the appropriate paths.
|
||||
|
||||
$ cd $SUPPORT/motor
|
||||
$ make distclean
|
||||
$ make
|
||||
|
||||
|
||||
------------------------
|
||||
motorDSM (this package)
|
||||
------------------------
|
||||
|
||||
$ cd $SUPPORT
|
||||
$ git clone git@github.com:Binary-Coalescence/motorDSM.git
|
||||
|
||||
In ``motorDSM/configure``, copy ``EXAMPLE_RELEASE.local`` to ``RELEASE.local`` and set paths for ``EPICS_BASE``, ``MOTOR``, and ``MOTOR_DSM``.
|
||||
|
||||
In ``motorDSM/configure``, copy ``EXAMPLE_CONFIG_SITE.local`` to ``CONFIG_SITE.local`` and uncomment to set:
|
||||
BUILD_IOCS = YES
|
||||
|
||||
In ``motorDSM/iocs/dsmIOC/configure``, copy ``EXAMPLE_RELEASE.local`` to ``RELEASE.local``. Comment out the "if built inside motor" lines, uncomment the "if built outside motor" lines, and set the path for ``MOTOR_DSM``.
|
||||
|
||||
$ cd $SUPPORT/motorDSM
|
||||
$ make distclean
|
||||
$ make
|
||||
|
||||
------------------------
|
||||
# Example usage
|
||||
|
||||
After building, run the example IOC described at the top of this section in one terminal window.
|
||||
Open another terminal window and navigate to [EPICS install directory]/epics-base/bin/linux-x86_64/ (or wherever you built EPICS base.
|
||||
Use the commands `caput` and `caget` to set and read process variables.
|
||||
|
||||
For example, to get the current position, use `./caget DSM:m0.REP`. This reads the REP variable, which is the "Raw Encoder Position". Set m0 to m1, m2, etc. for multiple motors.
|
||||
|
||||
Other examples
|
||||
-------------------------
|
||||
|
||||
Homing the motor (must be done before you can issue position commands):
|
||||
`./caput DSM:m0.HOMF 1 #Begins homing sequence in the forward direction`
|
||||
`./caput DSM:m0.HOMR 1 #Begins homing sequence in the reverse direction`
|
||||
|
||||
Moving to a position target:
|
||||
`./caput DSM:m0.VAL 2.345 #Moves to 2.345 mm`
|
||||
|
||||
Setting a velocity target:
|
||||
`./caput DSM:m0.VELO 0.5 #Sets velocity target to 0.5 mm/s`
|
||||
(Note that velocity targets are appropriate only. They adjust the step rate of the motor and are not guaranteed to be exact.)
|
||||
|
||||
A note aboue velocity targets
|
||||
-----------------------------
|
||||
The I-20 motor driven by the MD-90 is a closed loop "step and repeat" motor that takes full steps towards its position target until it is
|
||||
close, then will perform linear extensions to close the loop on the target position. This is handled internally on the MD-90, not by
|
||||
EPICS.
|
||||
|
||||
The Velocity target parameter sets the step frequency
|
||||
at which the motor operates on its way to the target position. The speed is not closed loop, and will depend on external loads, environmental
|
||||
conditions, etc. A speed target of 1 mm/s will generate a roughly 1 mm/s motion, but it is not guaranteed.
|
||||
|
||||
Additionally, due to the way EPICS operates, setting VELO will not immediately send a command to the MD90. Instead, EPICS remembers the last value you set, and will set this new
|
||||
velocity target when it sends the next move command. **However, the motor must not be in servo mode to accept a new velocity target.**
|
||||
|
||||
The motor enters servo mode when you send a new position target, and stays in servo mode until you issue a Stop command
|
||||
(by setting the `DSM:m0.STOP` parameter to 1).
|
||||
|
||||
If you do not disable servo prior to issuing a Move command at the new velocity, then VELO will become out of sync with the actual motor
|
||||
velocity, and EPICS will return error 3 "Cannot execute while moving" in its console each time you issue a Move command.
|
||||
This is because each Move command internally sends a "Set step frequenc" command, which will error if you do not Stop the motor first.
|
||||
Reading the VELO parameter at this point will return the wrong value- it returns the value you requested, not the actual speed setting
|
||||
on the motor.
|
||||
To fix this, you must Stop the motor, then send a new Move command. At
|
||||
|
||||
motorAcs contains an example IOC that is built if ``CONFIG_SITE.local`` sets ``BUILD_IOCS = YES``. The example IOC can be built outside of driver module.
|
||||
|
@@ -1,336 +0,0 @@
|
||||
/*
|
||||
FILENAME... MCB4BDriver.cpp
|
||||
USAGE... Motor driver support for the ACS MCB-4B controller.
|
||||
|
||||
Mark Rivers
|
||||
March 1, 2012
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <iocsh.h>
|
||||
#include <epicsThread.h>
|
||||
|
||||
#include <asynOctetSyncIO.h>
|
||||
|
||||
#include <epicsExport.h>
|
||||
#include "MCB4BDriver.h"
|
||||
|
||||
#define NINT(f) (int)((f)>0 ? (f)+0.5 : (f)-0.5)
|
||||
|
||||
/** Creates a new MCB4BController object.
|
||||
* \param[in] portName The name of the asyn port that will be created for this driver
|
||||
* \param[in] MCB4BPortName The name of the drvAsynSerialPort that was created previously to connect to the MCB4B controller
|
||||
* \param[in] numAxes The number of axes that this controller supports
|
||||
* \param[in] movingPollPeriod The time between polls when any axis is moving
|
||||
* \param[in] idlePollPeriod The time between polls when no axis is moving
|
||||
*/
|
||||
MCB4BController::MCB4BController(const char *portName, const char *MCB4BPortName, int numAxes,
|
||||
double movingPollPeriod, double idlePollPeriod)
|
||||
: asynMotorController(portName, numAxes, NUM_MCB4B_PARAMS,
|
||||
0, // No additional interfaces beyond those in base class
|
||||
0, // No additional callback interfaces beyond those in base class
|
||||
ASYN_CANBLOCK | ASYN_MULTIDEVICE,
|
||||
1, // autoconnect
|
||||
0, 0) // Default priority and stack size
|
||||
{
|
||||
int axis;
|
||||
asynStatus status;
|
||||
MCB4BAxis *pAxis;
|
||||
static const char *functionName = "MCB4BController::MCB4BController";
|
||||
|
||||
/* Connect to MCB4B controller */
|
||||
status = pasynOctetSyncIO->connect(MCB4BPortName, 0, &pasynUserController_, NULL);
|
||||
if (status) {
|
||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||
"%s: cannot connect to MCB-4B controller\n",
|
||||
functionName);
|
||||
}
|
||||
for (axis=0; axis<numAxes; axis++) {
|
||||
pAxis = new MCB4BAxis(this, axis);
|
||||
}
|
||||
|
||||
startPoller(movingPollPeriod, idlePollPeriod, 2);
|
||||
}
|
||||
|
||||
|
||||
/** Creates a new MCB4BController object.
|
||||
* Configuration command, called directly or from iocsh
|
||||
* \param[in] portName The name of the asyn port that will be created for this driver
|
||||
* \param[in] MCB4BPortName The name of the drvAsynIPPPort that was created previously to connect to the MCB4B controller
|
||||
* \param[in] numAxes The number of axes that this controller supports
|
||||
* \param[in] movingPollPeriod The time in ms between polls when any axis is moving
|
||||
* \param[in] idlePollPeriod The time in ms between polls when no axis is moving
|
||||
*/
|
||||
extern "C" int MCB4BCreateController(const char *portName, const char *MCB4BPortName, int numAxes,
|
||||
int movingPollPeriod, int idlePollPeriod)
|
||||
{
|
||||
MCB4BController *pMCB4BController
|
||||
= new MCB4BController(portName, MCB4BPortName, numAxes, movingPollPeriod/1000., idlePollPeriod/1000.);
|
||||
pMCB4BController = NULL;
|
||||
return(asynSuccess);
|
||||
}
|
||||
|
||||
/** Reports on status of the driver
|
||||
* \param[in] fp The file pointer on which report information will be written
|
||||
* \param[in] level The level of report detail desired
|
||||
*
|
||||
* If details > 0 then information is printed about each axis.
|
||||
* After printing controller-specific information it calls asynMotorController::report()
|
||||
*/
|
||||
void MCB4BController::report(FILE *fp, int level)
|
||||
{
|
||||
fprintf(fp, "MCB-4B motor driver %s, numAxes=%d, moving poll period=%f, idle poll period=%f\n",
|
||||
this->portName, numAxes_, movingPollPeriod_, idlePollPeriod_);
|
||||
|
||||
// Call the base class method
|
||||
asynMotorController::report(fp, level);
|
||||
}
|
||||
|
||||
/** Returns a pointer to an MCB4BAxis object.
|
||||
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
||||
* \param[in] pasynUser asynUser structure that encodes the axis index number. */
|
||||
MCB4BAxis* MCB4BController::getAxis(asynUser *pasynUser)
|
||||
{
|
||||
return static_cast<MCB4BAxis*>(asynMotorController::getAxis(pasynUser));
|
||||
}
|
||||
|
||||
/** Returns a pointer to an MCB4BAxis object.
|
||||
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
||||
* \param[in] axisNo Axis index number. */
|
||||
MCB4BAxis* MCB4BController::getAxis(int axisNo)
|
||||
{
|
||||
return static_cast<MCB4BAxis*>(asynMotorController::getAxis(axisNo));
|
||||
}
|
||||
|
||||
|
||||
// These are the MCB4BAxis methods
|
||||
|
||||
/** Creates a new MCB4BAxis object.
|
||||
* \param[in] pC Pointer to the MCB4BController to which this axis belongs.
|
||||
* \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1.
|
||||
*
|
||||
* Initializes register numbers, etc.
|
||||
*/
|
||||
MCB4BAxis::MCB4BAxis(MCB4BController *pC, int axisNo)
|
||||
: asynMotorAxis(pC, axisNo),
|
||||
pC_(pC)
|
||||
{
|
||||
}
|
||||
|
||||
/** Reports on status of the axis
|
||||
* \param[in] fp The file pointer on which report information will be written
|
||||
* \param[in] level The level of report detail desired
|
||||
*
|
||||
* After printing device-specific information calls asynMotorAxis::report()
|
||||
*/
|
||||
void MCB4BAxis::report(FILE *fp, int level)
|
||||
{
|
||||
if (level > 0) {
|
||||
fprintf(fp, " axis %d\n",
|
||||
axisNo_);
|
||||
}
|
||||
|
||||
// Call the base class method
|
||||
asynMotorAxis::report(fp, level);
|
||||
}
|
||||
|
||||
asynStatus MCB4BAxis::sendAccelAndVelocity(double acceleration, double velocity)
|
||||
{
|
||||
asynStatus status;
|
||||
int ival;
|
||||
// static const char *functionName = "MCB4B::sendAccelAndVelocity";
|
||||
|
||||
// Send the velocity
|
||||
ival = NINT(fabs(115200./velocity));
|
||||
if (ival < 2) ival=2;
|
||||
if (ival > 255) ival = 255;
|
||||
sprintf(pC_->outString_, "#%02dV=%d", axisNo_, ival);
|
||||
status = pC_->writeReadController();
|
||||
|
||||
// Send the acceleration
|
||||
// acceleration is in steps/sec/sec
|
||||
// MCB is programmed with Ramp Index (R) where:
|
||||
// dval (steps/sec/sec) = 720,000/(256-R) */
|
||||
// or R=256-(720,000/dval) */
|
||||
ival = NINT(256-(720000./acceleration));
|
||||
if (ival < 1) ival=1;
|
||||
if (ival > 255) ival=255;
|
||||
sprintf(pC_->outString_, "#%02dR=%d", axisNo_, ival);
|
||||
status = pC_->writeReadController();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
asynStatus MCB4BAxis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration)
|
||||
{
|
||||
asynStatus status;
|
||||
// static const char *functionName = "MCB4BAxis::move";
|
||||
|
||||
status = sendAccelAndVelocity(acceleration, maxVelocity);
|
||||
|
||||
if (relative) {
|
||||
sprintf(pC_->outString_, "#%02dI%+d", axisNo_, NINT(position));
|
||||
} else {
|
||||
sprintf(pC_->outString_, "#%02dG%+d", axisNo_, NINT(position));
|
||||
}
|
||||
status = pC_->writeReadController();
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus MCB4BAxis::home(double minVelocity, double maxVelocity, double acceleration, int forwards)
|
||||
{
|
||||
asynStatus status;
|
||||
// static const char *functionName = "MCB4BAxis::home";
|
||||
|
||||
status = sendAccelAndVelocity(acceleration, maxVelocity);
|
||||
|
||||
if (forwards) {
|
||||
sprintf(pC_->outString_, "#%02dH+", axisNo_);
|
||||
} else {
|
||||
sprintf(pC_->outString_, "#%02dH-", axisNo_);
|
||||
}
|
||||
status = pC_->writeReadController();
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus MCB4BAxis::moveVelocity(double minVelocity, double maxVelocity, double acceleration)
|
||||
{
|
||||
asynStatus status;
|
||||
static const char *functionName = "MCB4BAxis::moveVelocity";
|
||||
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
||||
"%s: minVelocity=%f, maxVelocity=%f, acceleration=%f\n",
|
||||
functionName, minVelocity, maxVelocity, acceleration);
|
||||
|
||||
status = sendAccelAndVelocity(acceleration, maxVelocity);
|
||||
|
||||
/* MCB-4B does not have jog command. Move 1 million steps */
|
||||
if (maxVelocity > 0.) {
|
||||
/* This is a positive move in MCB4B coordinates */
|
||||
sprintf(pC_->outString_, "#%02dI+1000000", axisNo_);
|
||||
} else {
|
||||
/* This is a negative move in MCB4B coordinates */
|
||||
sprintf(pC_->outString_, "#%02dI-1000000", axisNo_);
|
||||
}
|
||||
status = pC_->writeReadController();
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus MCB4BAxis::stop(double acceleration )
|
||||
{
|
||||
asynStatus status;
|
||||
//static const char *functionName = "MCB4BAxis::stop";
|
||||
|
||||
sprintf(pC_->outString_, "#%02dQ", axisNo_);
|
||||
status = pC_->writeReadController();
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus MCB4BAxis::setPosition(double position)
|
||||
{
|
||||
asynStatus status;
|
||||
//static const char *functionName = "MCB4BAxis::setPosition";
|
||||
|
||||
sprintf(pC_->outString_, "#%02dP=%+d", axisNo_, NINT(position));
|
||||
status = pC_->writeReadController();
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus MCB4BAxis::setClosedLoop(bool closedLoop)
|
||||
{
|
||||
asynStatus status;
|
||||
//static const char *functionName = "MCB4BAxis::setClosedLoop";
|
||||
|
||||
sprintf(pC_->outString_, "#%02dW=%d", axisNo_, closedLoop ? 1:0);
|
||||
status = pC_->writeReadController();
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Polls the axis.
|
||||
* This function reads the motor position, the limit status, the home status, the moving status,
|
||||
* and the drive power-on status.
|
||||
* It calls setIntegerParam() and setDoubleParam() for each item that it polls,
|
||||
* and then calls callParamCallbacks() at the end.
|
||||
* \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false). */
|
||||
asynStatus MCB4BAxis::poll(bool *moving)
|
||||
{
|
||||
int done;
|
||||
int driveOn;
|
||||
int limit;
|
||||
double position;
|
||||
asynStatus comStatus;
|
||||
|
||||
// Read the current motor position
|
||||
sprintf(pC_->outString_, "#%02dP", axisNo_);
|
||||
comStatus = pC_->writeReadController();
|
||||
if (comStatus) goto skip;
|
||||
// The response string is of the form "#01P=+1000"
|
||||
position = atof(&pC_->inString_[5]);
|
||||
setDoubleParam(pC_->motorPosition_, position);
|
||||
|
||||
// Read the moving status of this motor
|
||||
sprintf(pC_->outString_, "#%02dX", axisNo_);
|
||||
comStatus = pC_->writeReadController();
|
||||
if (comStatus) goto skip;
|
||||
// The response string is of the form "#01X=1"
|
||||
done = (pC_->inString_[5] == '0') ? 1:0;
|
||||
setIntegerParam(pC_->motorStatusDone_, done);
|
||||
*moving = done ? false:true;
|
||||
|
||||
// Read the limit status
|
||||
sprintf(pC_->outString_, "#%02dE", axisNo_);
|
||||
comStatus = pC_->writeReadController();
|
||||
if (comStatus) goto skip;
|
||||
// The response string is of the form "#01E=1"
|
||||
limit = (pC_->inString_[5] == '1') ? 1:0;
|
||||
setIntegerParam(pC_->motorStatusHighLimit_, limit);
|
||||
limit = (pC_->inString_[6] == '1') ? 1:0;
|
||||
setIntegerParam(pC_->motorStatusLowLimit_, limit);
|
||||
limit = (pC_->inString_[7] == '1') ? 1:0;
|
||||
setIntegerParam(pC_->motorStatusAtHome_, limit);
|
||||
|
||||
// Read the drive power on status
|
||||
sprintf(pC_->outString_, "#%02dW", axisNo_);
|
||||
comStatus = pC_->writeReadController();
|
||||
if (comStatus) goto skip;
|
||||
driveOn = (pC_->inString_[5] == '1') ? 1:0;
|
||||
setIntegerParam(pC_->motorStatusPowerOn_, driveOn);
|
||||
setIntegerParam(pC_->motorStatusProblem_, 0);
|
||||
|
||||
skip:
|
||||
setIntegerParam(pC_->motorStatusProblem_, comStatus ? 1:0);
|
||||
callParamCallbacks();
|
||||
return comStatus ? asynError : asynSuccess;
|
||||
}
|
||||
|
||||
/** Code for iocsh registration */
|
||||
static const iocshArg MCB4BCreateControllerArg0 = {"Port name", iocshArgString};
|
||||
static const iocshArg MCB4BCreateControllerArg1 = {"MCB-4B port name", iocshArgString};
|
||||
static const iocshArg MCB4BCreateControllerArg2 = {"Number of axes", iocshArgInt};
|
||||
static const iocshArg MCB4BCreateControllerArg3 = {"Moving poll period (ms)", iocshArgInt};
|
||||
static const iocshArg MCB4BCreateControllerArg4 = {"Idle poll period (ms)", iocshArgInt};
|
||||
static const iocshArg * const MCB4BCreateControllerArgs[] = {&MCB4BCreateControllerArg0,
|
||||
&MCB4BCreateControllerArg1,
|
||||
&MCB4BCreateControllerArg2,
|
||||
&MCB4BCreateControllerArg3,
|
||||
&MCB4BCreateControllerArg4};
|
||||
static const iocshFuncDef MCB4BCreateControllerDef = {"MCB4BCreateController", 5, MCB4BCreateControllerArgs};
|
||||
static void MCB4BCreateContollerCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
MCB4BCreateController(args[0].sval, args[1].sval, args[2].ival, args[3].ival, args[4].ival);
|
||||
}
|
||||
|
||||
static void MCB4BRegister(void)
|
||||
{
|
||||
iocshRegister(&MCB4BCreateControllerDef, MCB4BCreateContollerCallFunc);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
epicsExportRegistrar(MCB4BRegister);
|
||||
}
|
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
FILENAME... MCB4BDriver.h
|
||||
USAGE... Motor driver support for the ACS MCB-4B controller.
|
||||
|
||||
Mark Rivers
|
||||
March 1, 2012
|
||||
|
||||
*/
|
||||
|
||||
#include "asynMotorController.h"
|
||||
#include "asynMotorAxis.h"
|
||||
|
||||
#define MAX_MCB4B_AXES 4
|
||||
|
||||
// No controller-specific parameters yet
|
||||
#define NUM_MCB4B_PARAMS 0
|
||||
|
||||
class epicsShareClass MCB4BAxis : public asynMotorAxis
|
||||
{
|
||||
public:
|
||||
/* These are the methods we override from the base class */
|
||||
MCB4BAxis(class MCB4BController *pC, int axis);
|
||||
void report(FILE *fp, int level);
|
||||
asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration);
|
||||
asynStatus moveVelocity(double min_velocity, double max_velocity, double acceleration);
|
||||
asynStatus home(double min_velocity, double max_velocity, double acceleration, int forwards);
|
||||
asynStatus stop(double acceleration);
|
||||
asynStatus poll(bool *moving);
|
||||
asynStatus setPosition(double position);
|
||||
asynStatus setClosedLoop(bool closedLoop);
|
||||
|
||||
private:
|
||||
MCB4BController *pC_; /**< Pointer to the asynMotorController to which this axis belongs.
|
||||
* Abbreviated because it is used very frequently */
|
||||
asynStatus sendAccelAndVelocity(double accel, double velocity);
|
||||
|
||||
friend class MCB4BController;
|
||||
};
|
||||
|
||||
class epicsShareClass MCB4BController : public asynMotorController {
|
||||
public:
|
||||
MCB4BController(const char *portName, const char *MCB4BPortName, int numAxes, double movingPollPeriod, double idlePollPeriod);
|
||||
|
||||
void report(FILE *fp, int level);
|
||||
MCB4BAxis* getAxis(asynUser *pasynUser);
|
||||
MCB4BAxis* getAxis(int axisNo);
|
||||
|
||||
friend class MCB4BAxis;
|
||||
};
|
@@ -1,11 +0,0 @@
|
||||
# Advanced Control Systems driver support.
|
||||
|
||||
# Model 1 (non-asyn) driver
|
||||
device(motor,VME_IO,devMCB4B,"ACS MCB-4B")
|
||||
driver(drvMCB4B)
|
||||
registrar(AcsRegister)
|
||||
|
||||
# Model 3 driver
|
||||
registrar(MCB4BRegister)
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
EPICS_BASE=
|
||||
MOTOR=
|
||||
-include $(MOTOR)/modules/RELEASE.$(EPICS_HOST_ARCH).local
|
||||
# path to motorAcs is needed to build the IOC inside motorAcs, but outside motor
|
||||
MOTOR_ACS=
|
||||
# path to motorDsm is needed to build the IOC inside motorDsm, but outside motor
|
||||
MOTOR_DSM=
|
||||
|
@@ -2,6 +2,6 @@
|
||||
|
||||
# Use motor/module's generated release file when buidling inside motor
|
||||
-include $(TOP)/../RELEASE.$(EPICS_HOST_ARCH).local
|
||||
# Use motorAcs's RELEASE.local when building outside motor
|
||||
# Use motorDsm's RELEASE.local when building outside motor
|
||||
-include $(TOP)/configure/RELEASE.local
|
||||
|
||||
|
@@ -1,3 +1,22 @@
|
||||
# motorDSM Releases
|
||||
|
||||
## __v0.9.0-alpha__
|
||||
|
||||
### Changes since motorAcs R1-1-1
|
||||
|
||||
#### New features
|
||||
* Global rename Acs -> DSM and MCB-4B -> MD-90
|
||||
* Updated motor controller and axis methods to work with the DSM MD-90 controller
|
||||
* Updated example IOC startup scripts for the MD-90
|
||||
|
||||
#### Modifications to existing features
|
||||
* Removed Acs controller interface
|
||||
|
||||
#### Bug fixes
|
||||
* None
|
||||
|
||||
|
||||
|
||||
# motorAcs Releases
|
||||
|
||||
## __R1-1-1 (2023-04-11)__
|
||||
|
@@ -1,4 +1,4 @@
|
||||
# ### ACS_MCB4B.iocsh ###
|
||||
# ### DSM_MD90.iocsh ###
|
||||
|
||||
#- ###################################################
|
||||
#- PORT - Serial port for communications
|
||||
@@ -17,9 +17,9 @@
|
||||
#- Default: 100
|
||||
#- ###################################################
|
||||
|
||||
# ACS MCB-4B serial connection settings
|
||||
iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=19200, BITS=8, STOP=1, PARITY=none")
|
||||
# DSM MD-90 serial connection settings
|
||||
iocshLoad("$(IP)/iocsh/setSerialParams.iocsh", "PORT=$(PORT), BAUD=115200, BITS=8, STOP=1, PARITY=none")
|
||||
asynOctetSetInputEos( "$(PORT)", -1, "\r")
|
||||
asynOctetSetOutputEos("$(PORT)", -1, "\r")
|
||||
|
||||
MCB4BCreateController("$(INSTANCE)", "$(PORT)", $(NUM_AXES=1), $(MOVING_POLL=$(POLL_RATE=100)), $(IDLE_POLL=$(POLL_RATE=100)))
|
||||
MD90CreateController("$(INSTANCE)", "$(PORT)", $(NUM_AXES=1), $(MOVING_POLL=$(POLL_RATE=100)), $(IDLE_POLL=$(POLL_RATE=1000)))
|
@@ -1,6 +1,6 @@
|
||||
TOP = ../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
IOCSH += ACS_MCB4B.iocsh
|
||||
IOCSH += DSM_MD90.iocsh
|
||||
|
||||
include $(TOP)/configure/RULES
|
502
dsmApp/src/MD90Driver.cpp
Normal file
502
dsmApp/src/MD90Driver.cpp
Normal file
@@ -0,0 +1,502 @@
|
||||
/*
|
||||
FILENAME... MD90Driver.cpp
|
||||
USAGE... Motor driver support for the DSM MD-90 controller.
|
||||
|
||||
Mark Rivers
|
||||
March 1, 2012
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <iocsh.h>
|
||||
#include <epicsThread.h>
|
||||
|
||||
#include <asynOctetSyncIO.h>
|
||||
|
||||
#include <epicsExport.h>
|
||||
#include "MD90Driver.h"
|
||||
|
||||
#define NINT(f) (int)((f)>0 ? (f)+0.5 : (f)-0.5)
|
||||
|
||||
/** Creates a new MD90Controller object.
|
||||
* \param[in] portName The name of the asyn port that will be created for this driver
|
||||
* \param[in] MD90PortName The name of the drvAsynSerialPort that was created previously to connect to the MD90 controller
|
||||
* \param[in] numAxes The number of axes that this controller supports
|
||||
* \param[in] movingPollPeriod The time between polls when any axis is moving
|
||||
* \param[in] idlePollPeriod The time between polls when no axis is moving
|
||||
*/
|
||||
MD90Controller::MD90Controller(const char *portName, const char *MD90PortName, int numAxes,
|
||||
double movingPollPeriod, double idlePollPeriod)
|
||||
: asynMotorController(portName, numAxes, NUM_MD90_PARAMS,
|
||||
0, // No additional interfaces beyond those in base class
|
||||
0, // No additional callback interfaces beyond those in base class
|
||||
ASYN_CANBLOCK | ASYN_MULTIDEVICE,
|
||||
1, // autoconnect
|
||||
0, 0) // Default priority and stack size
|
||||
{
|
||||
int axis;
|
||||
asynStatus status;
|
||||
MD90Axis *pAxis;
|
||||
static const char *functionName = "MD90Controller::MD90Controller";
|
||||
|
||||
/* Connect to MD90 controller */
|
||||
status = pasynOctetSyncIO->connect(MD90PortName, 0, &pasynUserController_, NULL);
|
||||
if (status) {
|
||||
asynPrint(this->pasynUserSelf, ASYN_TRACE_ERROR,
|
||||
"%s: cannot connect to MD-90 controller\n",
|
||||
functionName);
|
||||
}
|
||||
for (axis=0; axis<numAxes; axis++) {
|
||||
pAxis = new MD90Axis(this, axis);
|
||||
}
|
||||
|
||||
startPoller(movingPollPeriod, idlePollPeriod, 2);
|
||||
}
|
||||
|
||||
|
||||
/** Creates a new MD90Controller object.
|
||||
* Configuration command, called directly or from iocsh
|
||||
* \param[in] portName The name of the asyn port that will be created for this driver
|
||||
* \param[in] MD90PortName The name of the drvAsynIPPPort that was created previously to connect to the MD90 controller
|
||||
* \param[in] numAxes The number of axes that this controller supports
|
||||
* \param[in] movingPollPeriod The time in ms between polls when any axis is moving
|
||||
* \param[in] idlePollPeriod The time in ms between polls when no axis is moving
|
||||
*/
|
||||
extern "C" int MD90CreateController(const char *portName, const char *MD90PortName, int numAxes,
|
||||
int movingPollPeriod, int idlePollPeriod)
|
||||
{
|
||||
MD90Controller *pMD90Controller
|
||||
= new MD90Controller(portName, MD90PortName, numAxes, movingPollPeriod/1000., idlePollPeriod/1000.);
|
||||
pMD90Controller = NULL;
|
||||
return(asynSuccess);
|
||||
}
|
||||
|
||||
/** Reports on status of the driver
|
||||
* \param[in] fp The file pointer on which report information will be written
|
||||
* \param[in] level The level of report detail desired
|
||||
*
|
||||
* If details > 0 then information is printed about each axis.
|
||||
* After printing controller-specific information it calls asynMotorController::report()
|
||||
*/
|
||||
void MD90Controller::report(FILE *fp, int level)
|
||||
{
|
||||
fprintf(fp, "MD-90 motor driver %s, numAxes=%d, moving poll period=%f, idle poll period=%f\n",
|
||||
this->portName, numAxes_, movingPollPeriod_, idlePollPeriod_);
|
||||
|
||||
// Call the base class method
|
||||
asynMotorController::report(fp, level);
|
||||
}
|
||||
|
||||
/** Returns a pointer to an MD90Axis object.
|
||||
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
||||
* \param[in] pasynUser asynUser structure that encodes the axis index number. */
|
||||
MD90Axis* MD90Controller::getAxis(asynUser *pasynUser)
|
||||
{
|
||||
return static_cast<MD90Axis*>(asynMotorController::getAxis(pasynUser));
|
||||
}
|
||||
|
||||
/** Returns a pointer to an MD90Axis object.
|
||||
* Returns NULL if the axis number encoded in pasynUser is invalid.
|
||||
* \param[in] axisNo Axis index number. */
|
||||
MD90Axis* MD90Controller::getAxis(int axisNo)
|
||||
{
|
||||
return static_cast<MD90Axis*>(asynMotorController::getAxis(axisNo));
|
||||
}
|
||||
|
||||
|
||||
// These are the MD90Axis methods
|
||||
|
||||
/** Creates a new MD90Axis object.
|
||||
* \param[in] pC Pointer to the MD90Controller to which this axis belongs.
|
||||
* \param[in] axisNo Index number of this axis, range 0 to pC->numAxes_-1.
|
||||
*
|
||||
* Initializes register numbers, etc.
|
||||
*/
|
||||
MD90Axis::MD90Axis(MD90Controller *pC, int axisNo)
|
||||
: asynMotorAxis(pC, axisNo),
|
||||
pC_(pC)
|
||||
{
|
||||
}
|
||||
|
||||
/** Reports on status of the axis
|
||||
* \param[in] fp The file pointer on which report information will be written
|
||||
* \param[in] level The level of report detail desired
|
||||
*
|
||||
* After printing device-specific information calls asynMotorAxis::report()
|
||||
*/
|
||||
void MD90Axis::report(FILE *fp, int level)
|
||||
{
|
||||
if (level > 0) {
|
||||
fprintf(fp, " axis %d\n",
|
||||
axisNo_);
|
||||
}
|
||||
|
||||
// Call the base class method
|
||||
asynMotorAxis::report(fp, level);
|
||||
}
|
||||
|
||||
/** Print out message if the motor controller returns a non-zero error code
|
||||
* \param[in] functionName The function originating the call
|
||||
* \param[in] reply Reply message returned from motor controller
|
||||
*/
|
||||
asynStatus MD90Axis::parseReply(const char *functionName, const char *reply)
|
||||
{
|
||||
int replyStatus;
|
||||
char replyString[256];
|
||||
int replyValue;
|
||||
asynStatus comStatus;
|
||||
|
||||
comStatus = asynSuccess;
|
||||
|
||||
if (reply[0] == '\0') {
|
||||
comStatus = asynError;
|
||||
replyStatus = -1;
|
||||
} else if ( strcmp(reply, "Unrecognized command.") == 0 ) {
|
||||
replyStatus = 6;
|
||||
} else {
|
||||
sscanf(reply, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||
}
|
||||
|
||||
if (replyStatus != 0) {
|
||||
asynPrint(pasynUser_, ASYN_TRACE_ERROR,
|
||||
"%s: %s\n",
|
||||
functionName, reply);
|
||||
}
|
||||
|
||||
return comStatus;
|
||||
}
|
||||
|
||||
/** Acceleration currently unsupported with MD-90 controller
|
||||
* \param[in] acceleration The accelerations to ramp up to max velocity
|
||||
* \param[in] velocity Motor velocity in steps / sec
|
||||
*/
|
||||
asynStatus MD90Axis::sendAccelAndVelocity(double acceleration, double velocity)
|
||||
{
|
||||
asynStatus status;
|
||||
int freq;
|
||||
static const char *functionName = "MD90::sendAccelAndVelocity";
|
||||
|
||||
// Send the velocity
|
||||
// Velocity provided in steps/sec
|
||||
// Our unit step size of the encoder is 10 nm, but the motor moves in steps approx. 5 micrometers.
|
||||
// Motor controller accepts step frequency in Hz.
|
||||
freq = NINT(fabs(velocity / COUNTS_PER_STEP));
|
||||
sprintf(pC_->outString_, "SSF %d", freq);
|
||||
status = pC_->writeReadController();
|
||||
if (!status) {
|
||||
status = parseReply(functionName, pC_->inString_);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
asynStatus MD90Axis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration)
|
||||
{
|
||||
asynStatus status;
|
||||
static const char *functionName = "MD90Axis::move";
|
||||
|
||||
status = sendAccelAndVelocity(acceleration, maxVelocity);
|
||||
|
||||
// Position specified in encoder steps (10 nm), but motor move commands are in nanometers
|
||||
position = position * 10;
|
||||
if (relative) {
|
||||
sprintf(pC_->outString_, "CRM %d", NINT(position));
|
||||
} else {
|
||||
sprintf(pC_->outString_, "CLM %d", NINT(position));
|
||||
}
|
||||
status = pC_->writeReadController();
|
||||
if (!status) {
|
||||
status = parseReply(functionName, pC_->inString_);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus MD90Axis::home(double minVelocity, double maxVelocity, double acceleration, int forwards)
|
||||
{
|
||||
asynStatus status;
|
||||
static const char *functionName = "MD90Axis::home";
|
||||
|
||||
status = sendAccelAndVelocity(acceleration, maxVelocity);
|
||||
|
||||
sprintf(pC_->outString_, "HOM");
|
||||
status = pC_->writeReadController();
|
||||
if (!status) {
|
||||
status = parseReply(functionName, pC_->inString_);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus MD90Axis::moveVelocity(double minVelocity, double maxVelocity, double acceleration)
|
||||
{
|
||||
asynStatus status;
|
||||
static const char *functionName = "MD90Axis::moveVelocity";
|
||||
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW,
|
||||
"%s: minVelocity=%f, maxVelocity=%f, acceleration=%f\n",
|
||||
functionName, minVelocity, maxVelocity, acceleration);
|
||||
|
||||
status = sendAccelAndVelocity(acceleration, maxVelocity);
|
||||
|
||||
/* MD-90 does not have jog command. Move max 6000 steps */
|
||||
sprintf(pC_->outString_, "SNS 6000");
|
||||
status = pC_->writeReadController();
|
||||
if (maxVelocity > 0.) {
|
||||
/* This is a positive move in MD90 coordinates */
|
||||
sprintf(pC_->outString_, "ESF");
|
||||
} else {
|
||||
/* This is a negative move in MD90 coordinates */
|
||||
sprintf(pC_->outString_, "ESB");
|
||||
}
|
||||
status = pC_->writeReadController();
|
||||
if (!status) {
|
||||
status = parseReply(functionName, pC_->inString_);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus MD90Axis::stop(double acceleration )
|
||||
{
|
||||
asynStatus status;
|
||||
static const char *functionName = "MD90Axis::stop";
|
||||
|
||||
sprintf(pC_->outString_, "STP");
|
||||
status = pC_->writeReadController();
|
||||
if (!status) {
|
||||
status = parseReply(functionName, pC_->inString_);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/** The ACS driver used this to turn on/off the motor winding current, so
|
||||
* we'll use this for enabling/disabling the persistent move state.
|
||||
*/
|
||||
asynStatus MD90Axis::setClosedLoop(bool closedLoop)
|
||||
{
|
||||
asynStatus status;
|
||||
static const char *functionName = "MD90Axis::setClosedLoop";
|
||||
|
||||
if (closedLoop == 1) {
|
||||
sprintf(pC_->outString_, "EPM");
|
||||
} else {
|
||||
sprintf(pC_->outString_, "DPM");
|
||||
}
|
||||
status = pC_->writeReadController();
|
||||
if (!status) {
|
||||
status = parseReply(functionName, pC_->inString_);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Set the I Gain of the motor control loop. The motor is an I- controller
|
||||
* and has no P or D terms.
|
||||
* \param[in] iGain The current I gain in the control loop
|
||||
*/
|
||||
asynStatus MD90Axis::setIGain(double iGain)
|
||||
{
|
||||
asynStatus status;
|
||||
static const char *functionName = "MD90Axis::setIGain";
|
||||
|
||||
iGain = iGain * 1000;
|
||||
if (iGain < 1) iGain = 1.0;
|
||||
if (iGain > 1000) iGain = 1000.0;
|
||||
sprintf(pC_->outString_, "SGN %d", NINT(iGain));
|
||||
status = pC_->writeReadController();
|
||||
if (!status) {
|
||||
status = parseReply(functionName, pC_->inString_);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
asynStatus MD90Axis::doMoveToHome()
|
||||
{
|
||||
asynStatus status;
|
||||
static const char *functionName = "MD90Axis::doMoveToHome";
|
||||
|
||||
sprintf(pC_->outString_, "CLM 0");
|
||||
status = pC_->writeReadController();
|
||||
if (!status) {
|
||||
status = parseReply(functionName, pC_->inString_);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Polls the axis.
|
||||
* This function reads the motor position, the limit status, the home status, the moving status,
|
||||
* and the drive power-on status.
|
||||
* It calls setIntegerParam() and setDoubleParam() for each item that it polls,
|
||||
* and then calls callParamCallbacks() at the end.
|
||||
* \param[out] moving A flag that is set indicating that the axis is moving (true) or done (false).
|
||||
*/
|
||||
asynStatus MD90Axis::poll(bool *moving)
|
||||
{
|
||||
int replyStatus;
|
||||
char replyString[256];
|
||||
int replyValue;
|
||||
int done;
|
||||
int driveOn;
|
||||
int homed;
|
||||
double position;
|
||||
double velocity;
|
||||
asynStatus comStatus;
|
||||
static const char *functionName = "MD90Axis::poll";
|
||||
|
||||
// TODO: Will need to add some more error handling for the motor return codes.
|
||||
|
||||
setIntegerParam(pC_->motorStatusProblem_, 0);
|
||||
|
||||
// Read the drive power on status
|
||||
sprintf(pC_->outString_, "GPS");
|
||||
comStatus = pC_->writeReadController();
|
||||
if (comStatus) goto skip;
|
||||
// The response string is of the form "0: Power supply enabled state: 1"
|
||||
sscanf(pC_->inString_, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||
driveOn = (replyValue == '1') ? 1:0;
|
||||
setIntegerParam(pC_->motorStatusPowerOn_, driveOn);
|
||||
|
||||
// Read the home status
|
||||
sprintf(pC_->outString_, "GHS");
|
||||
comStatus = pC_->writeReadController();
|
||||
if (comStatus) goto skip;
|
||||
// The response string is of the form "0: Home status: 1"
|
||||
sscanf(pC_->inString_, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||
homed = (replyValue == '1') ? 1:0;
|
||||
setIntegerParam(pC_->motorStatusHomed_, homed);
|
||||
|
||||
// Read the moving status of this motor
|
||||
sprintf(pC_->outString_, "STA");
|
||||
comStatus = pC_->writeReadController();
|
||||
if (comStatus) goto skip;
|
||||
// The response string is of the form "0: Current status value: 0"
|
||||
sscanf(pC_->inString_, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||
done = (replyValue == '2') ? 0:1;
|
||||
setIntegerParam(pC_->motorStatusDone_, done);
|
||||
*moving = done ? false:true;
|
||||
switch(replyValue) {
|
||||
case 0: // Idle
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s: Idle\n", functionName);
|
||||
break;
|
||||
case 1: // Open loop move complete
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s: Open loop move complete\n", functionName);
|
||||
break;
|
||||
case 2: // Move in progress
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s: Move in progress\n", functionName);
|
||||
break;
|
||||
case 3: // Move stopped
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s: Move stopped\n", functionName);
|
||||
break;
|
||||
case 4: // Homing error
|
||||
setIntegerParam(pC_->motorStatusProblem_, 1);
|
||||
asynPrint(pasynUser_, ASYN_TRACE_ERROR, "%s: Homing error\n", functionName);
|
||||
break;
|
||||
case 5: // Stance error
|
||||
setIntegerParam(pC_->motorStatusProblem_, 1);
|
||||
asynPrint(pasynUser_, ASYN_TRACE_ERROR, "%s: Stance error (Error resetting pose during closed loop move)\n", functionName);
|
||||
break;
|
||||
case 6: // Stance complete
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s: Stance complete (Finished resetting pose, starting extension move)\n", functionName);
|
||||
break;
|
||||
case 7: // Open loop move error
|
||||
setIntegerParam(pC_->motorStatusProblem_, 1);
|
||||
asynPrint(pasynUser_, ASYN_TRACE_ERROR, "%s: Open loop move error\n", functionName);
|
||||
break;
|
||||
case 8: // Closed loop move error
|
||||
setIntegerParam(pC_->motorStatusProblem_, 1);
|
||||
asynPrint(pasynUser_, ASYN_TRACE_ERROR, "%s: Closed loop move error\n", functionName);
|
||||
break;
|
||||
case 9: // Closed loop move complete
|
||||
asynPrint(pasynUser_, ASYN_TRACE_FLOW, "%s: Closed loop move complete\n", functionName);
|
||||
break;
|
||||
case 10: // End of travel error
|
||||
setIntegerParam(pC_->motorStatusProblem_, 1);
|
||||
asynPrint(pasynUser_, ASYN_TRACE_ERROR, "%s: End of travel error\n", functionName);
|
||||
if (position > 0) {
|
||||
setIntegerParam(pC_->motorStatusHighLimit_, 1);
|
||||
} else {
|
||||
setIntegerParam(pC_->motorStatusLowLimit_, 1);
|
||||
}
|
||||
break;
|
||||
case 11: // Ramp move error
|
||||
setIntegerParam(pC_->motorStatusProblem_, 1);
|
||||
asynPrint(pasynUser_, ASYN_TRACE_ERROR, "%s: Ramp move error\n", functionName);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Read the current motor position in encoder steps (10 nm)
|
||||
sprintf(pC_->outString_, "GEC");
|
||||
comStatus = pC_->writeReadController();
|
||||
if (comStatus) goto skip;
|
||||
// The response string is of the form "0: Current position in encoder counts: 1000"
|
||||
sscanf(pC_->inString_, "%d: %[^:]: %lf", &replyStatus, replyString, &position);
|
||||
setDoubleParam(pC_->motorPosition_, position);
|
||||
setDoubleParam(pC_->motorEncoderPosition_, position);
|
||||
setIntegerParam(pC_->motorStatusAtHome_, (position == 0) ? 1:0); // home limit switch
|
||||
setIntegerParam(pC_->motorStatusHome_, (position == 0) ? 1:0); // at home position
|
||||
|
||||
// Read the current motor step frequency to calculate approx. set velocity in (encoder step lengths / s)
|
||||
sprintf(pC_->outString_, "GSF");
|
||||
comStatus = pC_->writeReadController();
|
||||
if (comStatus) goto skip;
|
||||
// The response string is of the form "0: Current step frequency: 100"
|
||||
sscanf(pC_->inString_, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||
velocity = replyValue * COUNTS_PER_STEP;
|
||||
setDoubleParam(pC_->motorVelocity_, velocity);
|
||||
|
||||
// Read the current motor integral gain (range 1-1000)
|
||||
sprintf(pC_->outString_, "GGN");
|
||||
comStatus = pC_->writeReadController();
|
||||
if (comStatus) goto skip;
|
||||
// The response string is of the form "0: Gain: 1000"
|
||||
sscanf(pC_->inString_, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||
setDoubleParam(pC_->motorIGain_, replyValue);
|
||||
|
||||
// Read the current motor persistent move state (using EPICS motorClosedLoop to report this)
|
||||
sprintf(pC_->outString_, "GPM");
|
||||
comStatus = pC_->writeReadController();
|
||||
if (comStatus) goto skip;
|
||||
// The response string is of the form "0: Current persistent move state: 1"
|
||||
sscanf(pC_->inString_, "%d: %[^:]: %d", &replyStatus, replyString, &replyValue);
|
||||
setIntegerParam(pC_->motorClosedLoop_, (replyValue == 0) ? 0:1);
|
||||
|
||||
// set some default params
|
||||
setIntegerParam(pC_->motorStatusHasEncoder_, 1);
|
||||
setIntegerParam(pC_->motorStatusGainSupport_, 1);
|
||||
|
||||
skip:
|
||||
setIntegerParam(pC_->motorStatusProblem_, comStatus ? 1:0);
|
||||
callParamCallbacks();
|
||||
return comStatus ? asynError : asynSuccess;
|
||||
}
|
||||
|
||||
/** Code for iocsh registration */
|
||||
static const iocshArg MD90CreateControllerArg0 = {"Port name", iocshArgString};
|
||||
static const iocshArg MD90CreateControllerArg1 = {"MD-90 port name", iocshArgString};
|
||||
static const iocshArg MD90CreateControllerArg2 = {"Number of axes", iocshArgInt};
|
||||
static const iocshArg MD90CreateControllerArg3 = {"Moving poll period (ms)", iocshArgInt};
|
||||
static const iocshArg MD90CreateControllerArg4 = {"Idle poll period (ms)", iocshArgInt};
|
||||
static const iocshArg * const MD90CreateControllerArgs[] = {&MD90CreateControllerArg0,
|
||||
&MD90CreateControllerArg1,
|
||||
&MD90CreateControllerArg2,
|
||||
&MD90CreateControllerArg3,
|
||||
&MD90CreateControllerArg4};
|
||||
static const iocshFuncDef MD90CreateControllerDef = {"MD90CreateController", 5, MD90CreateControllerArgs};
|
||||
static void MD90CreateContollerCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
MD90CreateController(args[0].sval, args[1].sval, args[2].ival, args[3].ival, args[4].ival);
|
||||
}
|
||||
|
||||
static void MD90Register(void)
|
||||
{
|
||||
iocshRegister(&MD90CreateControllerDef, MD90CreateContollerCallFunc);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
epicsExportRegistrar(MD90Register);
|
||||
}
|
50
dsmApp/src/MD90Driver.h
Normal file
50
dsmApp/src/MD90Driver.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
FILENAME... MD90Driver.h
|
||||
USAGE... Motor driver support for the DSM MD-90 controller.
|
||||
|
||||
*/
|
||||
|
||||
#include "asynMotorController.h"
|
||||
#include "asynMotorAxis.h"
|
||||
|
||||
#define MAX_MD90_AXES 1
|
||||
|
||||
// No controller-specific parameters yet
|
||||
#define NUM_MD90_PARAMS 0
|
||||
|
||||
#define COUNTS_PER_STEP 1000.0 //Number of encoder counts per motor step (measured by testing)
|
||||
|
||||
class epicsShareClass MD90Axis : public asynMotorAxis
|
||||
{
|
||||
public:
|
||||
/* These are the methods we override from the base class */
|
||||
MD90Axis(class MD90Controller *pC, int axis);
|
||||
void report(FILE *fp, int level);
|
||||
asynStatus move(double position, int relative, double min_velocity, double max_velocity, double acceleration);
|
||||
asynStatus moveVelocity(double min_velocity, double max_velocity, double acceleration);
|
||||
asynStatus home(double min_velocity, double max_velocity, double acceleration, int forwards);
|
||||
asynStatus stop(double acceleration);
|
||||
asynStatus poll(bool *moving);
|
||||
asynStatus setClosedLoop(bool closedLoop);
|
||||
asynStatus setIGain(double iGain);
|
||||
asynStatus doMoveToHome();
|
||||
|
||||
private:
|
||||
MD90Controller *pC_; /**< Pointer to the asynMotorController to which this axis belongs.
|
||||
* Abbreviated because it is used very frequently */
|
||||
asynStatus sendAccelAndVelocity(double accel, double velocity);
|
||||
asynStatus parseReply(const char *functionName, const char *reply);
|
||||
|
||||
friend class MD90Controller;
|
||||
};
|
||||
|
||||
class epicsShareClass MD90Controller : public asynMotorController {
|
||||
public:
|
||||
MD90Controller(const char *portName, const char *MD90PortName, int numAxes, double movingPollPeriod, double idlePollPeriod);
|
||||
|
||||
void report(FILE *fp, int level);
|
||||
MD90Axis* getAxis(asynUser *pasynUser);
|
||||
MD90Axis* getAxis(int axisNo);
|
||||
|
||||
friend class MD90Axis;
|
||||
};
|
@@ -5,18 +5,18 @@ include $(TOP)/configure/CONFIG
|
||||
# The following are used for debugging messages.
|
||||
USR_CXXFLAGS += -DDEBUG
|
||||
|
||||
DBD += devAcsMotor.dbd
|
||||
DBD += devDsmMotor.dbd
|
||||
|
||||
LIBRARY_IOC = Acs
|
||||
LIBRARY_IOC = dsm
|
||||
|
||||
SRCS += AcsRegister.cc
|
||||
SRCS += dsmRegister.cc
|
||||
|
||||
# Advanced Control Systems driver support.
|
||||
SRCS += devMCB4B.c drvMCB4B.c
|
||||
SRCS += MCB4BDriver.cpp
|
||||
SRCS += devMD90.c drvMD90.c
|
||||
SRCS += MD90Driver.cpp
|
||||
|
||||
Acs_LIBS += motor asyn
|
||||
Acs_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
dsm_LIBS += motor asyn
|
||||
dsm_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
11
dsmApp/src/devDsmMotor.dbd
Normal file
11
dsmApp/src/devDsmMotor.dbd
Normal file
@@ -0,0 +1,11 @@
|
||||
# Advanced Control Systems driver support.
|
||||
|
||||
# Model 1 (non-asyn) driver
|
||||
device(motor,VME_IO,devMD90,"DSM MD-90")
|
||||
driver(drvMD90)
|
||||
registrar(dsmRegister)
|
||||
|
||||
# Model 3 driver
|
||||
registrar(MD90Register)
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* File: devMCB4B.cc */
|
||||
/* File: devMD90.cc */
|
||||
|
||||
/* Device Support Routines for motor */
|
||||
/*
|
||||
@@ -20,21 +20,21 @@
|
||||
#include "motorRecord.h"
|
||||
#include "motor.h"
|
||||
#include "motordevCom.h"
|
||||
#include "drvMCB4B.h"
|
||||
#include "drvMD90.h"
|
||||
#include "epicsExport.h"
|
||||
|
||||
#define STATIC static
|
||||
|
||||
extern struct driver_table MCB4B_access;
|
||||
extern struct driver_table MD90_access;
|
||||
|
||||
#define NINT(f) (long)((f)>0 ? (f)+0.5 : (f)-0.5)
|
||||
|
||||
volatile int devMCB4BDebug = 0;
|
||||
extern "C" {epicsExportAddress(int, devMCB4BDebug);}
|
||||
volatile int devMD90Debug = 0;
|
||||
extern "C" {epicsExportAddress(int, devMD90Debug);}
|
||||
|
||||
static inline void Debug(int level, const char *format, ...) {
|
||||
#ifdef DEBUG
|
||||
if (level < devMCB4BDebug)
|
||||
if (level < devMD90Debug)
|
||||
{
|
||||
va_list pVar;
|
||||
va_start(pVar, format);
|
||||
@@ -45,35 +45,35 @@ static inline void Debug(int level, const char *format, ...) {
|
||||
}
|
||||
|
||||
/* Debugging levels:
|
||||
* devMCB4BDebug >= 3 Print new part of command and command string so far
|
||||
* at the end of MCB4B_build_trans
|
||||
* devMD90Debug >= 3 Print new part of command and command string so far
|
||||
* at the end of MD90_build_trans
|
||||
*/
|
||||
|
||||
|
||||
/* ----------------Create the dsets for devMCB4B----------------- */
|
||||
/* ----------------Create the dsets for devMD90----------------- */
|
||||
STATIC struct driver_table *drvtabptr;
|
||||
STATIC long MCB4B_init(int);
|
||||
STATIC long MCB4B_init_record(void *);
|
||||
STATIC long MCB4B_start_trans(struct motorRecord *);
|
||||
STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd, double *, struct motorRecord *);
|
||||
STATIC RTN_STATUS MCB4B_end_trans(struct motorRecord *);
|
||||
STATIC long MD90_init(int);
|
||||
STATIC long MD90_init_record(void *);
|
||||
STATIC long MD90_start_trans(struct motorRecord *);
|
||||
STATIC RTN_STATUS MD90_build_trans(motor_cmnd, double *, struct motorRecord *);
|
||||
STATIC RTN_STATUS MD90_end_trans(struct motorRecord *);
|
||||
|
||||
struct motor_dset devMCB4B =
|
||||
struct motor_dset devMD90 =
|
||||
{
|
||||
{8, NULL, (DEVSUPFUN) MCB4B_init, (DEVSUPFUN) MCB4B_init_record, NULL},
|
||||
{8, NULL, (DEVSUPFUN) MD90_init, (DEVSUPFUN) MD90_init_record, NULL},
|
||||
motor_update_values,
|
||||
MCB4B_start_trans,
|
||||
MCB4B_build_trans,
|
||||
MCB4B_end_trans
|
||||
MD90_start_trans,
|
||||
MD90_build_trans,
|
||||
MD90_end_trans
|
||||
};
|
||||
|
||||
extern "C" {epicsExportAddress(dset,devMCB4B);}
|
||||
extern "C" {epicsExportAddress(dset,devMD90);}
|
||||
|
||||
|
||||
/* --------------------------- program data --------------------- */
|
||||
/* This table is used to define the command types */
|
||||
|
||||
static msg_types MCB4B_table[] = {
|
||||
static msg_types MD90_table[] = {
|
||||
MOTION, /* MOVE_ABS */
|
||||
MOTION, /* MOVE_REL */
|
||||
MOTION, /* HOME_FOR */
|
||||
@@ -99,63 +99,63 @@ static msg_types MCB4B_table[] = {
|
||||
};
|
||||
|
||||
|
||||
static struct board_stat **MCB4B_cards;
|
||||
static struct board_stat **MD90_cards;
|
||||
|
||||
/* --------------------------- program data --------------------- */
|
||||
|
||||
|
||||
/* initialize device support for MCB4B stepper motor */
|
||||
STATIC long MCB4B_init(int after)
|
||||
/* initialize device support for MD90 stepper motor */
|
||||
STATIC long MD90_init(int after)
|
||||
{
|
||||
long rtnval;
|
||||
|
||||
Debug(5, "MCB4B_init: entry\n");
|
||||
Debug(5, "MD90_init: entry\n");
|
||||
if (!after)
|
||||
{
|
||||
drvtabptr = &MCB4B_access;
|
||||
drvtabptr = &MD90_access;
|
||||
(drvtabptr->init)();
|
||||
}
|
||||
|
||||
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &MCB4B_cards);
|
||||
Debug(5, "MCB4B_init: exit\n");
|
||||
rtnval = motor_init_com(after, *drvtabptr->cardcnt_ptr, drvtabptr, &MD90_cards);
|
||||
Debug(5, "MD90_init: exit\n");
|
||||
return(rtnval);
|
||||
}
|
||||
|
||||
|
||||
/* initialize a record instance */
|
||||
STATIC long MCB4B_init_record(void *arg)
|
||||
STATIC long MD90_init_record(void *arg)
|
||||
{
|
||||
struct motorRecord *mr = (struct motorRecord *) arg;
|
||||
long rtnval;
|
||||
|
||||
Debug(5, "MCB4B_init_record: entry\n");
|
||||
Debug(5, "MD90_init_record: entry\n");
|
||||
rtnval = motor_init_record_com(mr, *drvtabptr->cardcnt_ptr,
|
||||
drvtabptr, MCB4B_cards);
|
||||
drvtabptr, MD90_cards);
|
||||
return(rtnval);
|
||||
Debug(5, "MCB4B_init_record: exit\n");
|
||||
Debug(5, "MD90_init_record: exit\n");
|
||||
}
|
||||
|
||||
|
||||
/* start building a transaction */
|
||||
STATIC long MCB4B_start_trans(struct motorRecord *mr)
|
||||
STATIC long MD90_start_trans(struct motorRecord *mr)
|
||||
{
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
/* end building a transaction */
|
||||
STATIC RTN_STATUS MCB4B_end_trans(struct motorRecord *mr)
|
||||
STATIC RTN_STATUS MD90_end_trans(struct motorRecord *mr)
|
||||
{
|
||||
return(OK);
|
||||
}
|
||||
|
||||
/* add a part to the transaction */
|
||||
STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct motorRecord *mr)
|
||||
STATIC RTN_STATUS MD90_build_trans(motor_cmnd command, double *parms, struct motorRecord *mr)
|
||||
{
|
||||
struct motor_trans *trans = (struct motor_trans *) mr->dpvt;
|
||||
struct mess_node *motor_call;
|
||||
struct controller *brdptr;
|
||||
struct MCB4Bcontroller *cntrl;
|
||||
struct MD90controller *cntrl;
|
||||
char buff[30];
|
||||
int axis, card;
|
||||
RTN_STATUS rtnval;
|
||||
@@ -170,19 +170,19 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
||||
dval = (parms == NULL) ? 0.0 : *parms;
|
||||
ival = NINT(dval);
|
||||
|
||||
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MCB4B_cards);
|
||||
Debug(5, "MCB4B_build_trans: entry, motor_start_trans_com=%d\n", rtnval);
|
||||
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MD90_cards);
|
||||
Debug(5, "MD90_build_trans: entry, motor_start_trans_com=%d\n", rtnval);
|
||||
|
||||
motor_call = &(trans->motor_call);
|
||||
motor_call->type = MCB4B_table[command];
|
||||
motor_call->type = MD90_table[command];
|
||||
card = motor_call->card;
|
||||
axis = motor_call->signal;
|
||||
brdptr = (*trans->tabptr->card_array)[card];
|
||||
Debug(5, "MCB4B_build_trans: axis=%d, command=%d\n", axis, command);
|
||||
Debug(5, "MD90_build_trans: axis=%d, command=%d\n", axis, command);
|
||||
if (brdptr == NULL)
|
||||
return(rtnval = ERROR);
|
||||
|
||||
cntrl = (struct MCB4Bcontroller *) brdptr->DevicePrivate;
|
||||
cntrl = (struct MD90controller *) brdptr->DevicePrivate;
|
||||
|
||||
|
||||
if (trans->state != BUILD_STATE)
|
||||
@@ -192,8 +192,8 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
||||
{
|
||||
strcpy(motor_call->message, mr->init);
|
||||
rtnval = motor_end_trans_com(mr, drvtabptr);
|
||||
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MCB4B_cards);
|
||||
motor_call->type = MCB4B_table[command];
|
||||
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MD90_cards);
|
||||
motor_call->type = MD90_table[command];
|
||||
}
|
||||
|
||||
switch (command)
|
||||
@@ -207,8 +207,8 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
||||
{
|
||||
strcpy(motor_call->message, mr->prem);
|
||||
rtnval = motor_end_trans_com(mr, drvtabptr);
|
||||
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MCB4B_cards);
|
||||
motor_call->type = MCB4B_table[command];
|
||||
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MD90_cards);
|
||||
motor_call->type = MD90_table[command];
|
||||
}
|
||||
if (strlen(mr->post) != 0)
|
||||
motor_call->postmsgptr = (char *) &mr->post;
|
||||
@@ -238,7 +238,7 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
||||
case SET_VEL_BASE:
|
||||
send=false;
|
||||
trans->state = IDLE_STATE;
|
||||
break; /* MCB4B does not use base velocity */
|
||||
break; /* MD90 does not use base velocity */
|
||||
case SET_VELOCITY:
|
||||
ival = (int) (fabs(115200./dval) + 0.5);
|
||||
if (ival < 2) ival=2;
|
||||
@@ -247,7 +247,7 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
||||
break;
|
||||
case SET_ACCEL:
|
||||
/* dval is acceleration in steps/sec/sec */
|
||||
/* MCB is programmed with Ramp Index (R) where: */
|
||||
/* MD-90 is programmed with Ramp Index (R) where: */
|
||||
/* dval (steps/sec/sec) = 720,000/(256-R) */
|
||||
/* or R=256-(720,000/dval) */
|
||||
ival = (int) (256-(720000./dval)+0.5);
|
||||
@@ -257,7 +257,7 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
||||
break;
|
||||
case GO:
|
||||
/*
|
||||
* The MCB4B starts moving immediately on move commands, GO command
|
||||
* The MD90 starts moving immediately on move commands, GO command
|
||||
* does nothing
|
||||
*/
|
||||
send=false;
|
||||
@@ -265,7 +265,7 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
||||
break;
|
||||
case SET_ENC_RATIO:
|
||||
/*
|
||||
* The MCB4B does not have the concept of encoder ratio, ignore this
|
||||
* The MD90 does not have the concept of encoder ratio, ignore this
|
||||
* command
|
||||
*/
|
||||
send=false;
|
||||
@@ -280,19 +280,19 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
||||
sprintf(motor_call->message, "#%02dQ", axis);
|
||||
break;
|
||||
case JOG:
|
||||
/* MCB-4B does not have jog command. Move 1 million steps */
|
||||
/* MD-90 does not have jog command. Move 1 million steps */
|
||||
ival = (int) (fabs(115200./dval) + 0.5);
|
||||
if (ival < 2) ival=2;
|
||||
if (ival > 65535) ival = 65535;
|
||||
sprintf(motor_call->message, "#%02dC=%ld", axis, ival);
|
||||
rtnval = motor_end_trans_com(mr, drvtabptr);
|
||||
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MCB4B_cards);
|
||||
motor_call->type = MCB4B_table[command];
|
||||
rtnval = (RTN_STATUS) motor_start_trans_com(mr, MD90_cards);
|
||||
motor_call->type = MD90_table[command];
|
||||
if (dval > 0.) {
|
||||
/* This is a positive move in MCB4B coordinates */
|
||||
/* This is a positive move in MD90 coordinates */
|
||||
sprintf(motor_call->message, "#%02dM+1000000", axis);
|
||||
} else {
|
||||
/* This is a negative move in MCB4B coordinates */
|
||||
/* This is a negative move in MD90 coordinates */
|
||||
sprintf(motor_call->message, "#%02dM-1000000", axis);
|
||||
}
|
||||
break;
|
||||
@@ -325,7 +325,7 @@ STATIC RTN_STATUS MCB4B_build_trans(motor_cmnd command, double *parms, struct mo
|
||||
return(rtnval);
|
||||
else {
|
||||
rtnval = motor_end_trans_com(mr, drvtabptr);
|
||||
Debug(5, "MCB4B_send_msg: motor_end_trans_com status=%d, exit\n", rtnval);
|
||||
Debug(5, "MD90_send_msg: motor_end_trans_com status=%d, exit\n", rtnval);
|
||||
return (rtnval);
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
/* File: drvMCB4B.cc */
|
||||
/* File: drvMD90.cc */
|
||||
|
||||
/* Device Driver Support routines for motor */
|
||||
/*
|
||||
@@ -24,8 +24,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <errlog.h>
|
||||
#include "motor.h"
|
||||
#include "AcsRegister.h"
|
||||
#include "drvMCB4B.h"
|
||||
#include "dsmRegister.h"
|
||||
#include "drvMD90.h"
|
||||
#include "asynOctetSyncIO.h"
|
||||
#include "epicsExport.h"
|
||||
|
||||
@@ -35,14 +35,14 @@
|
||||
|
||||
#define TIMEOUT 2.0 /* Command timeout in sec */
|
||||
|
||||
#define BUFF_SIZE 100 /* Maximum length of string to/from MCB4B */
|
||||
#define BUFF_SIZE 100 /* Maximum length of string to/from MD90 */
|
||||
|
||||
volatile int drvMCB4BDebug = 0;
|
||||
extern "C" {epicsExportAddress(int, drvMCB4BDebug);}
|
||||
volatile int drvMD90Debug = 0;
|
||||
extern "C" {epicsExportAddress(int, drvMD90Debug);}
|
||||
|
||||
static inline void Debug(int level, const char *format, ...) {
|
||||
#ifdef DEBUG
|
||||
if (level < drvMCB4BDebug)
|
||||
if (level < drvMD90Debug)
|
||||
{
|
||||
va_list pVar;
|
||||
va_start(pVar, format);
|
||||
@@ -53,14 +53,14 @@ static inline void Debug(int level, const char *format, ...) {
|
||||
}
|
||||
|
||||
/* Debugging notes:
|
||||
* drvMCB4BDebug == 0 No debugging information is printed
|
||||
* drvMCB4BDebug >= 1 Warning information is printed
|
||||
* drvMCB4BDebug >= 2 Time-stamped messages are printed for each string
|
||||
* drvMD90Debug == 0 No debugging information is printed
|
||||
* drvMD90Debug >= 1 Warning information is printed
|
||||
* drvMD90Debug >= 2 Time-stamped messages are printed for each string
|
||||
* sent to and received from the controller
|
||||
* drvMCB4BDebug >= 3 Additional debugging messages
|
||||
* drvMD90Debug >= 3 Additional debugging messages
|
||||
*/
|
||||
|
||||
int MCB4B_num_cards = 0;
|
||||
int MD90_num_cards = 0;
|
||||
|
||||
/* Local data required for every driver; see "motordrvComCode.h" */
|
||||
#include "motordrvComCode.h"
|
||||
@@ -78,7 +78,7 @@ STATIC void query_done(int, int, struct mess_node *);
|
||||
|
||||
/*----------------functions-----------------*/
|
||||
|
||||
struct driver_table MCB4B_access =
|
||||
struct driver_table MD90_access =
|
||||
{
|
||||
motor_init,
|
||||
motor_send,
|
||||
@@ -102,16 +102,16 @@ struct driver_table MCB4B_access =
|
||||
NULL
|
||||
};
|
||||
|
||||
struct drvMCB4B_drvet
|
||||
struct drvMD90_drvet
|
||||
{
|
||||
long number;
|
||||
long (*report) (int);
|
||||
long (*init) (void);
|
||||
} drvMCB4B = {2, report, init};
|
||||
} drvMD90 = {2, report, init};
|
||||
|
||||
extern "C" {epicsExportAddress(drvet, drvMCB4B);}
|
||||
extern "C" {epicsExportAddress(drvet, drvMD90);}
|
||||
|
||||
STATIC struct thread_args targs = {SCAN_RATE, &MCB4B_access, 0.0};
|
||||
STATIC struct thread_args targs = {SCAN_RATE, &MD90_access, 0.0};
|
||||
|
||||
|
||||
/*********************************************************
|
||||
@@ -120,16 +120,16 @@ STATIC struct thread_args targs = {SCAN_RATE, &MCB4B_access, 0.0};
|
||||
static long report(int level)
|
||||
{
|
||||
int card;
|
||||
struct MCB4Bcontroller *cntrl;
|
||||
struct MD90controller *cntrl;
|
||||
|
||||
if (MCB4B_num_cards <=0)
|
||||
printf(" NO MCB4B controllers found\n");
|
||||
if (MD90_num_cards <=0)
|
||||
printf(" NO MD90 controllers found\n");
|
||||
else
|
||||
{
|
||||
for (card = 0; card < MCB4B_num_cards; card++) {
|
||||
for (card = 0; card < MD90_num_cards; card++) {
|
||||
if (motor_state[card]) {
|
||||
cntrl = (struct MCB4Bcontroller *) motor_state[card]->DevicePrivate;
|
||||
printf(" MCB4B controller %d, port=%s, id: %s \n",
|
||||
cntrl = (struct MD90controller *) motor_state[card]->DevicePrivate;
|
||||
printf(" MD90 controller %d, port=%s, id: %s \n",
|
||||
card, cntrl->port,
|
||||
motor_state[card]->ident);
|
||||
}
|
||||
@@ -148,10 +148,10 @@ static long init()
|
||||
* support
|
||||
*/
|
||||
/* Check for setup */
|
||||
if (MCB4B_num_cards <= 0)
|
||||
if (MD90_num_cards <= 0)
|
||||
{
|
||||
Debug(1, "init: *MCB4B driver disabled*\n");
|
||||
Debug(1, "MCB4BSetup() is missing from startup script.\n");
|
||||
Debug(1, "init: *MD90 driver disabled*\n");
|
||||
Debug(1, "MD90Setup() is missing from startup script.\n");
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ STATIC void query_done(int card, int axis, struct mess_node *nodeptr)
|
||||
*********************************************************/
|
||||
STATIC void start_status(int card)
|
||||
{
|
||||
/* The MCB4B cannot query status or positions of all axes with a
|
||||
/* The MD90 cannot query status or positions of all axes with a
|
||||
* single command. This needs to be done on an axis-by-axis basis,
|
||||
* so this function does nothing
|
||||
*/
|
||||
@@ -265,7 +265,7 @@ STATIC int set_status(int card, int signal)
|
||||
if ((status.Bits.RA_DONE || ls_active == true) && nodeptr != 0 && nodeptr->postmsgptr != 0)
|
||||
{
|
||||
send_mess(card, nodeptr->postmsgptr, NULL);
|
||||
/* The MCB4B always sends back a response, read it and discard */
|
||||
/* The MD90 always sends back a response, read it and discard */
|
||||
recv_mess(card, buff, WAIT);
|
||||
nodeptr->postmsgptr = NULL;
|
||||
}
|
||||
@@ -276,12 +276,12 @@ STATIC int set_status(int card, int signal)
|
||||
|
||||
|
||||
/*****************************************************/
|
||||
/* send a message to the MCB4B board */
|
||||
/* send a message to the MD90 board */
|
||||
/* send_mess() */
|
||||
/*****************************************************/
|
||||
STATIC RTN_STATUS send_mess(int card, const char *com, const char *name)
|
||||
{
|
||||
struct MCB4Bcontroller *cntrl;
|
||||
struct MD90controller *cntrl;
|
||||
size_t nwrite;
|
||||
|
||||
/* Check that card exists */
|
||||
@@ -293,7 +293,7 @@ STATIC RTN_STATUS send_mess(int card, const char *com, const char *name)
|
||||
|
||||
/* If the string is NULL just return */
|
||||
if (strlen(com) == 0) return(OK);
|
||||
cntrl = (struct MCB4Bcontroller *) motor_state[card]->DevicePrivate;
|
||||
cntrl = (struct MD90controller *) motor_state[card]->DevicePrivate;
|
||||
|
||||
Debug(2, "send_mess: sending message to card %d, message=%s\n",\
|
||||
card, com);
|
||||
@@ -305,7 +305,7 @@ STATIC RTN_STATUS send_mess(int card, const char *com, const char *name)
|
||||
|
||||
|
||||
/*****************************************************/
|
||||
/* Read a response string from the MCB4B board */
|
||||
/* Read a response string from the MD90 board */
|
||||
/* recv_mess() */
|
||||
/*****************************************************/
|
||||
STATIC int recv_mess(int card, char *com, int flag)
|
||||
@@ -313,7 +313,7 @@ STATIC int recv_mess(int card, char *com, int flag)
|
||||
double timeout;
|
||||
size_t nread=0;
|
||||
asynStatus status;
|
||||
struct MCB4Bcontroller *cntrl;
|
||||
struct MD90controller *cntrl;
|
||||
int flush;
|
||||
int eomReason;
|
||||
|
||||
@@ -324,7 +324,7 @@ STATIC int recv_mess(int card, char *com, int flag)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
cntrl = (struct MCB4Bcontroller *) motor_state[card]->DevicePrivate;
|
||||
cntrl = (struct MD90controller *) motor_state[card]->DevicePrivate;
|
||||
|
||||
Debug(3, "recv_mess entry: card %d, flag=%d\n",\
|
||||
card, flag);
|
||||
@@ -363,18 +363,18 @@ STATIC int recv_mess(int card, char *com, int flag)
|
||||
|
||||
/*****************************************************/
|
||||
/* Setup system configuration */
|
||||
/* MCB4BSetup() */
|
||||
/* MD90Setup() */
|
||||
/*****************************************************/
|
||||
RTN_STATUS
|
||||
MCB4BSetup(int num_cards, /* maximum number of controllers in system */
|
||||
MD90Setup(int num_cards, /* maximum number of controllers in system */
|
||||
int scan_rate) /* polling rate - 1/60 sec units */
|
||||
{
|
||||
int itera;
|
||||
|
||||
if (num_cards < 1 || num_cards > MCB4B_NUM_CARDS)
|
||||
MCB4B_num_cards = MCB4B_NUM_CARDS;
|
||||
if (num_cards < 1 || num_cards > MD90_NUM_CARDS)
|
||||
MD90_num_cards = MD90_NUM_CARDS;
|
||||
else
|
||||
MCB4B_num_cards = num_cards;
|
||||
MD90_num_cards = num_cards;
|
||||
|
||||
/* Set motor polling task rate */
|
||||
if (scan_rate >= 1 && scan_rate <= 60)
|
||||
@@ -384,15 +384,15 @@ MCB4BSetup(int num_cards, /* maximum number of controllers in system */
|
||||
|
||||
/*
|
||||
* Allocate space for motor_state structure pointers. Note this must be done
|
||||
* before MCB4BConfig is called, so it cannot be done in motor_init()
|
||||
* before MD90Config is called, so it cannot be done in motor_init()
|
||||
* This means that we must allocate space for a card without knowing
|
||||
* if it really exists, which is not a serious problem since this is just
|
||||
* an array of pointers.
|
||||
*/
|
||||
motor_state = (struct controller **) malloc(MCB4B_num_cards *
|
||||
motor_state = (struct controller **) malloc(MD90_num_cards *
|
||||
sizeof(struct controller *));
|
||||
|
||||
for (itera = 0; itera < MCB4B_num_cards; itera++)
|
||||
for (itera = 0; itera < MD90_num_cards; itera++)
|
||||
motor_state[itera] = (struct controller *) NULL;
|
||||
return (OK);
|
||||
}
|
||||
@@ -400,20 +400,20 @@ MCB4BSetup(int num_cards, /* maximum number of controllers in system */
|
||||
|
||||
/*****************************************************/
|
||||
/* Configure a controller */
|
||||
/* MCB4BConfig() */
|
||||
/* MD90Config() */
|
||||
/*****************************************************/
|
||||
RTN_STATUS
|
||||
MCB4BConfig(int card, /* card being configured */
|
||||
MD90Config(int card, /* card being configured */
|
||||
const char *name) /* port name for asyn */
|
||||
{
|
||||
struct MCB4Bcontroller *cntrl;
|
||||
struct MD90controller *cntrl;
|
||||
|
||||
if (card < 0 || card >= MCB4B_num_cards)
|
||||
if (card < 0 || card >= MD90_num_cards)
|
||||
return (ERROR);
|
||||
|
||||
motor_state[card] = (struct controller *) malloc(sizeof(struct controller));
|
||||
motor_state[card]->DevicePrivate = malloc(sizeof(struct MCB4Bcontroller));
|
||||
cntrl = (struct MCB4Bcontroller *) motor_state[card]->DevicePrivate;
|
||||
motor_state[card]->DevicePrivate = malloc(sizeof(struct MD90controller));
|
||||
cntrl = (struct MD90controller *) motor_state[card]->DevicePrivate;
|
||||
strcpy(cntrl->port, name);
|
||||
return (OK);
|
||||
}
|
||||
@@ -429,7 +429,7 @@ MCB4BConfig(int card, /* card being configured */
|
||||
STATIC int motor_init()
|
||||
{
|
||||
struct controller *brdptr;
|
||||
struct MCB4Bcontroller *cntrl;
|
||||
struct MD90controller *cntrl;
|
||||
int card_index, motor_index;
|
||||
char buff[BUFF_SIZE];
|
||||
int total_axis = 0;
|
||||
@@ -439,21 +439,21 @@ STATIC int motor_init()
|
||||
initialized = true; /* Indicate that driver is initialized. */
|
||||
|
||||
/* Check for setup */
|
||||
if (MCB4B_num_cards <= 0)
|
||||
if (MD90_num_cards <= 0)
|
||||
{
|
||||
Debug(1, "motor_init: *MCB4B driver disabled*\n");
|
||||
Debug(1, "MCB4BSetup() is missing from startup script.\n");
|
||||
Debug(1, "motor_init: *MD90 driver disabled*\n");
|
||||
Debug(1, "MD90Setup() is missing from startup script.\n");
|
||||
return (ERROR);
|
||||
}
|
||||
|
||||
for (card_index = 0; card_index < MCB4B_num_cards; card_index++)
|
||||
for (card_index = 0; card_index < MD90_num_cards; card_index++)
|
||||
{
|
||||
if (!motor_state[card_index])
|
||||
continue;
|
||||
|
||||
brdptr = motor_state[card_index];
|
||||
total_cards = card_index + 1;
|
||||
cntrl = (struct MCB4Bcontroller *) brdptr->DevicePrivate;
|
||||
cntrl = (struct MD90controller *) brdptr->DevicePrivate;
|
||||
|
||||
/* Initialize communications channel */
|
||||
success_rtn = pasynOctetSyncIO->connect(cntrl->port, 0, &cntrl->pasynUser, NULL);
|
||||
@@ -498,7 +498,7 @@ STATIC int motor_init()
|
||||
sprintf(buff,"#%02dQ", motor_index);
|
||||
send_mess(card_index, buff, 0);
|
||||
recv_mess(card_index, buff, WAIT); /* Throw away response */
|
||||
strcpy(brdptr->ident, "MCB-4B");
|
||||
strcpy(brdptr->ident, "MD-90");
|
||||
motor_info->status.All = 0;
|
||||
motor_info->no_motion_count = 0;
|
||||
motor_info->encoder_position = 0;
|
||||
@@ -521,7 +521,7 @@ STATIC int motor_init()
|
||||
|
||||
Debug(3, "motor_init: spawning motor task\n");
|
||||
|
||||
epicsThreadCreate((char *) "tMCB4B", epicsThreadPriorityMedium,
|
||||
epicsThreadCreate((char *) "tMD90", epicsThreadPriorityMedium,
|
||||
epicsThreadGetStackSize(epicsThreadStackMedium),
|
||||
(EPICSTHREADFUNC) motor_task, (void *) &targs);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* File: drvMCB4B.h */
|
||||
/* File: drvMD90.h */
|
||||
|
||||
|
||||
/* Device Driver Support definitions for motor */
|
||||
@@ -12,23 +12,23 @@
|
||||
* .01 02/24/2002 mlr initialized from drvPM304.h
|
||||
*/
|
||||
|
||||
#ifndef INCdrvMCB4Bh
|
||||
#define INCdrvMCB4Bh 1
|
||||
#ifndef INCdrvMD90h
|
||||
#define INCdrvMD90h 1
|
||||
|
||||
#include "motordrvCom.h"
|
||||
#include "asynDriver.h"
|
||||
|
||||
/* MCB4B default profile. */
|
||||
/* MD90 default profile. */
|
||||
|
||||
#define MCB4B_NUM_CARDS 4
|
||||
#define MCB4B_NUM_CHANNELS 4
|
||||
#define MD90_NUM_CARDS 4
|
||||
#define MD90_NUM_CHANNELS 4
|
||||
|
||||
#define OUTPUT_TERMINATOR "\r"
|
||||
|
||||
struct MCB4Bcontroller
|
||||
struct MD90controller
|
||||
{
|
||||
asynUser *pasynUser; /* asynUser structure */
|
||||
char port[80]; /* asyn port name */
|
||||
};
|
||||
|
||||
#endif /* INCdrvMCB4Bh */
|
||||
#endif /* INCdrvMD90h */
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
FILENAME... AcsRegister.cc
|
||||
USAGE... Register ACS motor device driver shell commands.
|
||||
FILENAME... dsmRegister.cc
|
||||
USAGE... Register DSM motor device driver shell commands.
|
||||
|
||||
*/
|
||||
|
||||
@@ -16,40 +16,40 @@ of this distribution.
|
||||
**********************************************************************/
|
||||
|
||||
#include <iocsh.h>
|
||||
#include "AcsRegister.h"
|
||||
#include "dsmRegister.h"
|
||||
#include "epicsExport.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
// ACS Setup arguments
|
||||
// DSM Setup arguments
|
||||
static const iocshArg setupArg0 = {"Max. controller count", iocshArgInt};
|
||||
static const iocshArg setupArg1 = {"Polling rate", iocshArgInt};
|
||||
// ACS Config arguments
|
||||
// DSM Config arguments
|
||||
static const iocshArg configArg0 = {"Card being configured", iocshArgInt};
|
||||
static const iocshArg configArg1 = {"asyn port name", iocshArgString};
|
||||
|
||||
static const iocshArg * const MCB4BSetupArgs[2] = {&setupArg0, &setupArg1};
|
||||
static const iocshArg * const MCB4BConfigArgs[2] = {&configArg0, &configArg1};
|
||||
static const iocshArg * const MD90SetupArgs[2] = {&setupArg0, &setupArg1};
|
||||
static const iocshArg * const MD90ConfigArgs[2] = {&configArg0, &configArg1};
|
||||
|
||||
static const iocshFuncDef setupMCB4B = {"MCB4BSetup", 2, MCB4BSetupArgs};
|
||||
static const iocshFuncDef configMCB4B = {"MCB4BConfig", 2, MCB4BConfigArgs};
|
||||
static const iocshFuncDef setupMD90 = {"MD90Setup", 2, MD90SetupArgs};
|
||||
static const iocshFuncDef configMD90 = {"MD90Config", 2, MD90ConfigArgs};
|
||||
|
||||
static void setupMCB4BCallFunc(const iocshArgBuf *args)
|
||||
static void setupMD90CallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
MCB4BSetup(args[0].ival, args[1].ival);
|
||||
MD90Setup(args[0].ival, args[1].ival);
|
||||
}
|
||||
static void configMCB4BCallFunc(const iocshArgBuf *args)
|
||||
static void configMD90CallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
MCB4BConfig(args[0].ival, args[1].sval);
|
||||
MD90Config(args[0].ival, args[1].sval);
|
||||
}
|
||||
|
||||
static void AcsRegister(void)
|
||||
static void dsmRegister(void)
|
||||
{
|
||||
iocshRegister(&setupMCB4B, setupMCB4BCallFunc);
|
||||
iocshRegister(&configMCB4B, configMCB4BCallFunc);
|
||||
iocshRegister(&setupMD90, setupMD90CallFunc);
|
||||
iocshRegister(&configMD90, configMD90CallFunc);
|
||||
}
|
||||
|
||||
epicsExportRegistrar(AcsRegister);
|
||||
epicsExportRegistrar(dsmRegister);
|
||||
|
||||
} // extern "C"
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
FILENAME... AcsRegister.h
|
||||
USAGE... This file contains function prototypes for ACS IOC shell commands.
|
||||
FILENAME... dsmRegister.h
|
||||
USAGE... This file contains function prototypes for DSM IOC shell commands.
|
||||
|
||||
*/
|
||||
|
||||
@@ -37,6 +37,6 @@ USAGE... This file contains function prototypes for ACS IOC shell commands.
|
||||
#include "motordrvCom.h"
|
||||
|
||||
/* Function prototypes. */
|
||||
extern RTN_STATUS MCB4BSetup(int, int);
|
||||
extern RTN_STATUS MCB4BConfig(int, const char *);
|
||||
extern RTN_STATUS MD90Setup(int, int);
|
||||
extern RTN_STATUS MD90Config(int, const char *);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
DIRS += acsIOC
|
||||
DIRS += dsmIOC
|
||||
|
||||
include $(TOP)/configure/RULES_TOP
|
||||
|
||||
|
@@ -1,6 +0,0 @@
|
||||
# Use the following lines if motorAcs was built inside motor
|
||||
MOTOR=
|
||||
-include $(MOTOR)/configure/RELEASE
|
||||
# Use the following lines if motorAcs was built outside motor
|
||||
#!MOTOR_ACS=
|
||||
#!-include $(MOTOR_ACS)/configure/RELEASE.local
|
@@ -1,9 +0,0 @@
|
||||
file "$(MOTOR)/db/basic_asyn_motor.db"
|
||||
{
|
||||
pattern
|
||||
{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT}
|
||||
{IOC:, 1, "m$(N)", "asynMotor", MCB4B1, 0, "Bottom", mm, Pos, 2.0, 0.1, .2, 0, 1, .2, -.001, 3, 16, 0, ""}
|
||||
{IOC:, 2, "m$(N)", "asynMotor", MCB4B1, 1, "Top", mm, Pos, 2.0, 0.1, .2, 0, 1, .2, -.001, 3, 16, 0, ""}
|
||||
{IOC:, 3, "m$(N)", "asynMotor", MCB4B1, 2, "Inboard", mm, Pos, 2.0, 0.1, .2, 0, 1, .2, -.001, 3, 16, 0, ""}
|
||||
{IOC:, 4, "m$(N)", "asynMotor", MCB4B1, 3, "Outboard", mm, Pos, 2.0, 0.1, .2, 0, 1, .2, -.001, 3, 16, 0, ""}
|
||||
}
|
@@ -1,34 +0,0 @@
|
||||
#errlogInit(5000)
|
||||
< envPaths
|
||||
|
||||
# Tell EPICS all about the record types, device-support modules, drivers, etc.
|
||||
dbLoadDatabase("../../dbd/acs.dbd")
|
||||
acs_registerRecordDeviceDriver(pdbbase)
|
||||
|
||||
# Port 2 on a Moxa
|
||||
drvAsynIPPortConfigure("serial1", "192.168.1.16:4002",0,0,0)
|
||||
# Local serial port
|
||||
#!drvAsynSerialPortConfigure("serial1", "/dev/ttyS0", 0, 0, 0)
|
||||
asynOctetSetInputEos("serial1",0,"\r")
|
||||
asynOctetSetOutputEos("serial1",0,"\r")
|
||||
asynSetTraceIOMask("serial1", 0, 2)
|
||||
#asynSetTraceMask("serial1", 0, 255)
|
||||
|
||||
MCB4BCreateController("MCB4B1", "serial1", 4, 100, 5000)
|
||||
|
||||
### Motors
|
||||
dbLoadTemplate "motor.substitutions.mcb4b"
|
||||
|
||||
dbLoadRecords("$(ASYN)/db/asynRecord.db","P=IOC:,R=serial1,PORT=serial1,ADDR=0,OMAX=80,IMAX=80")
|
||||
|
||||
iocInit
|
||||
|
||||
# This IOC does not use save/restore, so set values of some PVs
|
||||
dbpf("IOC:m1.RTRY", "0")
|
||||
dbpf("IOC:m1.TWV", "0.1")
|
||||
dbpf("IOC:m2.RTRY", "0")
|
||||
dbpf("IOC:m2.TWV", "0.1")
|
||||
dbpf("IOC:m3.RTRY", "0")
|
||||
dbpf("IOC:m3.TWV", "0.1")
|
||||
dbpf("IOC:m4.RTRY", "0")
|
||||
dbpf("IOC:m4.TWV", "0.1")
|
@@ -37,8 +37,8 @@ CHECK_RELEASE = YES
|
||||
|
||||
# Include motor's CONFIG_SITE.local when building inside motor
|
||||
-include $(TOP)/../../../../configure/CONFIG_SITE.local
|
||||
# Include motorAcs's CONFIG_SITE.local when building inside motorAcs
|
||||
# Include motorDsm's CONFIG_SITE.local when building inside motorDsm
|
||||
-include $(TOP)/../../configure/CONFIG_SITE.local
|
||||
# Use acsIOC's CONFIG_SITE.local
|
||||
# Use dsmIOC's CONFIG_SITE.local
|
||||
-include $(TOP)/configure/CONFIG_SITE.local
|
||||
|
6
iocs/dsmIOC/configure/EXAMPLE_RELEASE.local
Normal file
6
iocs/dsmIOC/configure/EXAMPLE_RELEASE.local
Normal file
@@ -0,0 +1,6 @@
|
||||
# Use the following lines if motorDsm was built inside motor
|
||||
MOTOR=
|
||||
-include $(MOTOR)/configure/RELEASE
|
||||
# Use the following lines if motorDsm was built outside motor
|
||||
#!MOTOR_DSM=
|
||||
#!-include $(MOTOR_DSM)/configure/RELEASE.local
|
@@ -2,7 +2,7 @@
|
||||
|
||||
# Use motor/module's generated release file when buidling inside motor
|
||||
-include $(TOP)/../../../RELEASE.$(EPICS_HOST_ARCH).local
|
||||
# Use motorAcs's release file when building inside motorAcs, but outside motor
|
||||
# Use motorDsm's release file when building inside motorDsm, but outside motor
|
||||
-include $(TOP)/../../configure/RELEASE.local
|
||||
# Use acsIOC's RELEASE.local when building outside motorAcs
|
||||
# Use dsmIOC's RELEASE.local when building outside motorDsm
|
||||
-include $(TOP)/configure/RELEASE.local
|
@@ -11,44 +11,44 @@ include $(TOP)/configure/CONFIG
|
||||
#=============================
|
||||
# Build the IOC application
|
||||
|
||||
PROD_IOC = acs
|
||||
# acs.dbd will be created and installed
|
||||
DBD += acs.dbd
|
||||
PROD_IOC = dsm
|
||||
# dsm.dbd will be created and installed
|
||||
DBD += dsm.dbd
|
||||
|
||||
# acs.dbd will be made up from these files:
|
||||
acs_DBD += base.dbd
|
||||
# dsm.dbd will be made up from these files:
|
||||
dsm_DBD += base.dbd
|
||||
|
||||
# Include dbd files from all support applications:
|
||||
#ifdef ASYN
|
||||
acs_DBD += asyn.dbd
|
||||
acs_DBD += drvAsynSerialPort.dbd
|
||||
acs_DBD += drvAsynIPPort.dbd
|
||||
dsm_DBD += asyn.dbd
|
||||
dsm_DBD += drvAsynSerialPort.dbd
|
||||
dsm_DBD += drvAsynIPPort.dbd
|
||||
#endif
|
||||
acs_DBD += motorSupport.dbd
|
||||
acs_DBD += devAcsMotor.dbd
|
||||
dsm_DBD += motorSupport.dbd
|
||||
dsm_DBD += devDsmMotor.dbd
|
||||
|
||||
# Add all the support libraries needed by this IOC
|
||||
acs_LIBS += Acs
|
||||
acs_LIBS += motor
|
||||
dsm_LIBS += dsm
|
||||
dsm_LIBS += motor
|
||||
#ifdef ASYN
|
||||
acs_LIBS += asyn
|
||||
dsm_LIBS += asyn
|
||||
#endif
|
||||
#ifdef SNCSEQ
|
||||
acs_LIBS += seq pv
|
||||
dsm_LIBS += seq pv
|
||||
#endif
|
||||
|
||||
# acs_registerRecordDeviceDriver.cpp derives from acs.dbd
|
||||
acs_SRCS += acs_registerRecordDeviceDriver.cpp
|
||||
# dsm_registerRecordDeviceDriver.cpp derives from dsm.dbd
|
||||
dsm_SRCS += dsm_registerRecordDeviceDriver.cpp
|
||||
|
||||
# Build the main IOC entry point on workstation OSs.
|
||||
acs_SRCS_DEFAULT += acsMain.cpp
|
||||
acs_SRCS_vxWorks += -nil-
|
||||
dsm_SRCS_DEFAULT += dsmMain.cpp
|
||||
dsm_SRCS_vxWorks += -nil-
|
||||
|
||||
# Add support from base/src/vxWorks if needed
|
||||
#acs_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary
|
||||
#dsm_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary
|
||||
|
||||
# Finally link to the EPICS Base libraries
|
||||
acs_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
dsm_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
|
||||
#===========================
|
||||
|
@@ -1,4 +1,4 @@
|
||||
/* acsMain.cpp */
|
||||
/* dsmMain.cpp */
|
||||
/* Author: Marty Kraimer Date: 17MAR2000 */
|
||||
|
||||
#include <stddef.h>
|
26
iocs/dsmIOC/iocBoot/iocDsm/motor.substitutions.md90
Normal file
26
iocs/dsmIOC/iocBoot/iocDsm/motor.substitutions.md90
Normal file
@@ -0,0 +1,26 @@
|
||||
file "$(MOTOR)/db/basic_asyn_motor.db"
|
||||
{
|
||||
pattern
|
||||
{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, VMAX, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT}
|
||||
{DSM:, 0, "m$(N)", "asynMotor", MD900, 0, "MD-90", mm, Pos, 0.5, 0.025, 0.625, 0, 0, 0.03, 0, .00001, 2, 20, -20, ""}
|
||||
}
|
||||
|
||||
# P IOC prefix
|
||||
# N Port number
|
||||
# M Record name pattern
|
||||
# DTYP Datatype
|
||||
# PORT Port
|
||||
# ADDR Address
|
||||
# DESC Description
|
||||
# EGU Engineering units
|
||||
# DIR Direction
|
||||
# VELO Velocity (EGU / s) (note: jog velocity set separately by JVEL)
|
||||
# VBAS Minimum velocity (EGU / s)
|
||||
# VMAX Maximum velocity (EGU / s) (note: not getting set here with basic_asyn_motor.db)
|
||||
# ACCL Acceleration (time in seconds until VELO)
|
||||
# BDST Backlash distance
|
||||
# MRES Motor step size (EGU)
|
||||
# PREC Display precision number of decimal places
|
||||
# DHLM Dial high travel limit (EGU)
|
||||
# DLLM Dial low travel limit (EGU)
|
||||
# INIT Initialization string (seems to be unused/broken)
|
33
iocs/dsmIOC/iocBoot/iocDsm/motor.substitutions.md90.multi
Normal file
33
iocs/dsmIOC/iocBoot/iocDsm/motor.substitutions.md90.multi
Normal file
@@ -0,0 +1,33 @@
|
||||
file "$(MOTOR)/db/basic_asyn_motor.db"
|
||||
{
|
||||
pattern
|
||||
{P, N, M, DTYP, PORT, ADDR, DESC, EGU, DIR, VELO, VBAS, VMAX, ACCL, BDST, BVEL, BACC, MRES, PREC, DHLM, DLLM, INIT}
|
||||
{DSM:, 0, "m$(N)", "asynMotor", MD900, 0, "MD-90", mm, Pos, 0.5, 0.025, 0.625, 0, 0, 0.03, 0, .00001, 2, 20, -20, ""}
|
||||
{DSM:, 1, "m$(N)", "asynMotor", MD901, 0, "MD-90", mm, Pos, 0.5, 0.025, 0.625, 0, 0, 0.03, 0, .00001, 2, 20, -20, ""}
|
||||
{DSM:, 2, "m$(N)", "asynMotor", MD902, 0, "MD-90", mm, Pos, 0.5, 0.025, 0.625, 0, 0, 0.03, 0, .00001, 2, 20, -20, ""}
|
||||
{DSM:, 3, "m$(N)", "asynMotor", MD903, 0, "MD-90", mm, Pos, 0.5, 0.025, 0.625, 0, 0, 0.03, 0, .00001, 2, 20, -20, ""}
|
||||
{DSM:, 4, "m$(N)", "asynMotor", MD904, 0, "MD-90", mm, Pos, 0.5, 0.025, 0.625, 0, 0, 0.03, 0, .00001, 2, 20, -20, ""}
|
||||
{DSM:, 5, "m$(N)", "asynMotor", MD905, 0, "MD-90", mm, Pos, 0.5, 0.025, 0.625, 0, 0, 0.03, 0, .00001, 2, 20, -20, ""}
|
||||
{DSM:, 6, "m$(N)", "asynMotor", MD906, 0, "MD-90", mm, Pos, 0.5, 0.025, 0.625, 0, 0, 0.03, 0, .00001, 2, 20, -20, ""}
|
||||
{DSM:, 7, "m$(N)", "asynMotor", MD907, 0, "MD-90", mm, Pos, 0.5, 0.025, 0.625, 0, 0, 0.03, 0, .00001, 2, 20, -20, ""}
|
||||
}
|
||||
|
||||
# P IOC prefix
|
||||
# N Port number
|
||||
# M Record name pattern
|
||||
# DTYP Datatype
|
||||
# PORT Port
|
||||
# ADDR Address
|
||||
# DESC Description
|
||||
# EGU Engineering units
|
||||
# DIR Direction
|
||||
# VELO Velocity (EGU / s) (note: jog velocity set separately by JVEL)
|
||||
# VBAS Minimum velocity (EGU / s)
|
||||
# VMAX Maximum velocity (EGU / s) (note: not getting set here with basic_asyn_motor.db)
|
||||
# ACCL Acceleration (time in seconds until VELO)
|
||||
# BDST Backlash distance
|
||||
# MRES Motor step size (EGU)
|
||||
# PREC Display precision number of decimal places
|
||||
# DHLM Dial high travel limit (EGU)
|
||||
# DLLM Dial low travel limit (EGU)
|
||||
# INIT Initialization string (seems to be unused/broken)
|
@@ -1,24 +1,24 @@
|
||||
#!../../bin/linux-x86_64/acs
|
||||
#!../../bin/linux-x86_64/dsm
|
||||
|
||||
< envPaths
|
||||
|
||||
cd "${TOP}"
|
||||
|
||||
## Register all support components
|
||||
dbLoadDatabase "dbd/acs.dbd"
|
||||
acs_registerRecordDeviceDriver pdbbase
|
||||
dbLoadDatabase "dbd/dsm.dbd"
|
||||
dsm_registerRecordDeviceDriver pdbbase
|
||||
|
||||
cd "${TOP}/iocBoot/${IOC}"
|
||||
|
||||
|
||||
## motorUtil (allstop & alldone)
|
||||
dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=acs:")
|
||||
dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=dsm:")
|
||||
|
||||
##
|
||||
|
||||
iocInit
|
||||
|
||||
## motorUtil (allstop & alldone)
|
||||
motorUtilInit("acs:")
|
||||
motorUtilInit("dsm:")
|
||||
|
||||
# Boot complete
|
38
iocs/dsmIOC/iocBoot/iocDsm/st.cmd.md90
Normal file
38
iocs/dsmIOC/iocBoot/iocDsm/st.cmd.md90
Normal file
@@ -0,0 +1,38 @@
|
||||
#errlogInit(5000)
|
||||
< envPaths
|
||||
|
||||
# Tell EPICS all about the record types, device-support modules, drivers, etc.
|
||||
dbLoadDatabase("../../dbd/dsm.dbd")
|
||||
dsm_registerRecordDeviceDriver(pdbbase)
|
||||
|
||||
# Network device
|
||||
#!drvAsynIPPortConfigure("serial0", "192.168.1.16:4002",0,0,0)
|
||||
# Local serial port
|
||||
drvAsynSerialPortConfigure("serial0", "/dev/ttyUSB0", 0, 0, 0)
|
||||
asynSetOption("serial0", 0, "baud", "115200")
|
||||
asynSetOption("serial0", 0, "bits", "8")
|
||||
asynSetOption("serial0", 0, "parity", "none")
|
||||
asynSetOption("serial0", 0, "stop", "1")
|
||||
|
||||
asynOctetSetInputEos("serial0", 0, "\r")
|
||||
asynOctetSetOutputEos("serial0", 0, "\r")
|
||||
asynSetTraceIOMask("serial0", 0, 2)
|
||||
|
||||
# Turn on the power supply and set the deadband
|
||||
asynOctetConnect("initConnection", "serial0", 0)
|
||||
asynOctetWrite("initConnection", "EPS")
|
||||
asynOctetWrite("initConnection", "SDB 10")
|
||||
asynOctetDisconnect('initConnection')
|
||||
|
||||
MD90CreateController("MD900", "serial0", 1, 100, 5000)
|
||||
|
||||
### Motors
|
||||
dbLoadTemplate "motor.substitutions.md90"
|
||||
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial0,PORT=serial0,ADDR=0,OMAX=80,IMAX=80")
|
||||
|
||||
iocInit
|
||||
|
||||
# This IOC does not use save/restore, so set values of some PVs
|
||||
dbpf("DSM:m0.RTRY", "0")
|
||||
dbpf("DSM:m0.TWV", "0.1")
|
||||
dbpf("DSM:m0.VMAX", "0.625")
|
178
iocs/dsmIOC/iocBoot/iocDsm/st.cmd.md90.multi
Normal file
178
iocs/dsmIOC/iocBoot/iocDsm/st.cmd.md90.multi
Normal file
@@ -0,0 +1,178 @@
|
||||
#errlogInit(5000)
|
||||
< envPaths
|
||||
|
||||
# Tell EPICS all about the record types, device-support modules, drivers, etc.
|
||||
dbLoadDatabase("../../dbd/dsm.dbd")
|
||||
dsm_registerRecordDeviceDriver(pdbbase)
|
||||
|
||||
# Unfortunately, iocsh doesn't support looping...
|
||||
|
||||
# Local serial port
|
||||
drvAsynSerialPortConfigure("serial0", "/dev/ttyUSB0", 0, 0, 0)
|
||||
drvAsynSerialPortConfigure("serial1", "/dev/ttyUSB1", 0, 0, 0)
|
||||
drvAsynSerialPortConfigure("serial2", "/dev/ttyUSB2", 0, 0, 0)
|
||||
drvAsynSerialPortConfigure("serial3", "/dev/ttyUSB3", 0, 0, 0)
|
||||
drvAsynSerialPortConfigure("serial4", "/dev/ttyUSB4", 0, 0, 0)
|
||||
drvAsynSerialPortConfigure("serial5", "/dev/ttyUSB5", 0, 0, 0)
|
||||
drvAsynSerialPortConfigure("serial6", "/dev/ttyUSB6", 0, 0, 0)
|
||||
drvAsynSerialPortConfigure("serial7", "/dev/ttyUSB7", 0, 0, 0)
|
||||
|
||||
asynSetOption("serial0", 0, "baud", "115200")
|
||||
asynSetOption("serial1", 0, "baud", "115200")
|
||||
asynSetOption("serial2", 0, "baud", "115200")
|
||||
asynSetOption("serial3", 0, "baud", "115200")
|
||||
asynSetOption("serial4", 0, "baud", "115200")
|
||||
asynSetOption("serial5", 0, "baud", "115200")
|
||||
asynSetOption("serial6", 0, "baud", "115200")
|
||||
asynSetOption("serial7", 0, "baud", "115200")
|
||||
|
||||
asynSetOption("serial0", 0, "bits", "8")
|
||||
asynSetOption("serial1", 0, "bits", "8")
|
||||
asynSetOption("serial2", 0, "bits", "8")
|
||||
asynSetOption("serial3", 0, "bits", "8")
|
||||
asynSetOption("serial4", 0, "bits", "8")
|
||||
asynSetOption("serial5", 0, "bits", "8")
|
||||
asynSetOption("serial6", 0, "bits", "8")
|
||||
asynSetOption("serial7", 0, "bits", "8")
|
||||
|
||||
asynSetOption("serial0", 0, "parity", "none")
|
||||
asynSetOption("serial1", 0, "parity", "none")
|
||||
asynSetOption("serial2", 0, "parity", "none")
|
||||
asynSetOption("serial3", 0, "parity", "none")
|
||||
asynSetOption("serial4", 0, "parity", "none")
|
||||
asynSetOption("serial5", 0, "parity", "none")
|
||||
asynSetOption("serial6", 0, "parity", "none")
|
||||
asynSetOption("serial7", 0, "parity", "none")
|
||||
|
||||
asynSetOption("serial0", 0, "stop", "1")
|
||||
asynSetOption("serial1", 0, "stop", "1")
|
||||
asynSetOption("serial2", 0, "stop", "1")
|
||||
asynSetOption("serial3", 0, "stop", "1")
|
||||
asynSetOption("serial4", 0, "stop", "1")
|
||||
asynSetOption("serial5", 0, "stop", "1")
|
||||
asynSetOption("serial6", 0, "stop", "1")
|
||||
asynSetOption("serial7", 0, "stop", "1")
|
||||
|
||||
asynOctetSetInputEos("serial0", 0, "\r")
|
||||
asynOctetSetInputEos("serial1", 0, "\r")
|
||||
asynOctetSetInputEos("serial2", 0, "\r")
|
||||
asynOctetSetInputEos("serial3", 0, "\r")
|
||||
asynOctetSetInputEos("serial4", 0, "\r")
|
||||
asynOctetSetInputEos("serial5", 0, "\r")
|
||||
asynOctetSetInputEos("serial6", 0, "\r")
|
||||
asynOctetSetInputEos("serial7", 0, "\r")
|
||||
|
||||
asynOctetSetOutputEos("serial0", 0, "\r")
|
||||
asynOctetSetOutputEos("serial1", 0, "\r")
|
||||
asynOctetSetOutputEos("serial2", 0, "\r")
|
||||
asynOctetSetOutputEos("serial3", 0, "\r")
|
||||
asynOctetSetOutputEos("serial4", 0, "\r")
|
||||
asynOctetSetOutputEos("serial5", 0, "\r")
|
||||
asynOctetSetOutputEos("serial6", 0, "\r")
|
||||
asynOctetSetOutputEos("serial7", 0, "\r")
|
||||
|
||||
asynSetTraceIOMask("serial0", 0, 2)
|
||||
asynSetTraceIOMask("serial1", 0, 2)
|
||||
asynSetTraceIOMask("serial2", 0, 2)
|
||||
asynSetTraceIOMask("serial3", 0, 2)
|
||||
asynSetTraceIOMask("serial4", 0, 2)
|
||||
asynSetTraceIOMask("serial5", 0, 2)
|
||||
asynSetTraceIOMask("serial6", 0, 2)
|
||||
asynSetTraceIOMask("serial7", 0, 2)
|
||||
|
||||
# Turn on the power supply and set the deadband
|
||||
asynOctetConnect("initConnection", "serial0", 0)
|
||||
asynOctetWrite("initConnection", "EPS")
|
||||
asynOctetWrite("initConnection", "SDB 10")
|
||||
asynOctetDisconnect('initConnection')
|
||||
# Turn on the power supply and set the deadband
|
||||
asynOctetConnect("initConnection", "serial1", 0)
|
||||
asynOctetWrite("initConnection", "EPS")
|
||||
asynOctetWrite("initConnection", "SDB 10")
|
||||
asynOctetDisconnect('initConnection')
|
||||
# Turn on the power supply and set the deadband
|
||||
asynOctetConnect("initConnection", "serial2", 0)
|
||||
asynOctetWrite("initConnection", "EPS")
|
||||
asynOctetWrite("initConnection", "SDB 10")
|
||||
asynOctetDisconnect('initConnection')
|
||||
# Turn on the power supply and set the deadband
|
||||
asynOctetConnect("initConnection", "serial3", 0)
|
||||
asynOctetWrite("initConnection", "EPS")
|
||||
asynOctetWrite("initConnection", "SDB 10")
|
||||
asynOctetDisconnect('initConnection')
|
||||
# Turn on the power supply and set the deadband
|
||||
asynOctetConnect("initConnection", "serial4", 0)
|
||||
asynOctetWrite("initConnection", "EPS")
|
||||
asynOctetWrite("initConnection", "SDB 10")
|
||||
asynOctetDisconnect('initConnection')
|
||||
# Turn on the power supply and set the deadband
|
||||
asynOctetConnect("initConnection", "serial5", 0)
|
||||
asynOctetWrite("initConnection", "EPS")
|
||||
asynOctetWrite("initConnection", "SDB 10")
|
||||
asynOctetDisconnect('initConnection')
|
||||
# Turn on the power supply and set the deadband
|
||||
asynOctetConnect("initConnection", "serial6", 0)
|
||||
asynOctetWrite("initConnection", "EPS")
|
||||
asynOctetWrite("initConnection", "SDB 10")
|
||||
asynOctetDisconnect('initConnection')
|
||||
# Turn on the power supply and set the deadband
|
||||
asynOctetConnect("initConnection", "serial7", 0)
|
||||
asynOctetWrite("initConnection", "EPS")
|
||||
asynOctetWrite("initConnection", "SDB 10")
|
||||
asynOctetDisconnect('initConnection')
|
||||
|
||||
MD90CreateController("MD900", "serial0", 1, 100, 5000)
|
||||
MD90CreateController("MD901", "serial1", 1, 100, 5000)
|
||||
MD90CreateController("MD902", "serial2", 1, 100, 5000)
|
||||
MD90CreateController("MD903", "serial3", 1, 100, 5000)
|
||||
MD90CreateController("MD904", "serial4", 1, 100, 5000)
|
||||
MD90CreateController("MD905", "serial5", 1, 100, 5000)
|
||||
MD90CreateController("MD906", "serial6", 1, 100, 5000)
|
||||
MD90CreateController("MD907", "serial7", 1, 100, 5000)
|
||||
|
||||
### Motors
|
||||
dbLoadTemplate "motor.substitutions.md90.multi"
|
||||
|
||||
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial0,PORT=serial0,ADDR=0,OMAX=80,IMAX=80")
|
||||
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial1,PORT=serial1,ADDR=0,OMAX=80,IMAX=80")
|
||||
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial2,PORT=serial2,ADDR=0,OMAX=80,IMAX=80")
|
||||
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial3,PORT=serial3,ADDR=0,OMAX=80,IMAX=80")
|
||||
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial4,PORT=serial4,ADDR=0,OMAX=80,IMAX=80")
|
||||
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial5,PORT=serial5,ADDR=0,OMAX=80,IMAX=80")
|
||||
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial6,PORT=serial6,ADDR=0,OMAX=80,IMAX=80")
|
||||
dbLoadRecords("$(ASYN)/db/asynRecord.db", "P=DSM:,R=serial7,PORT=serial7,ADDR=0,OMAX=80,IMAX=80")
|
||||
|
||||
iocInit
|
||||
|
||||
# This IOC does not use save/restore, so set values of some PVs
|
||||
dbpf("DSM:m0.RTRY", "0")
|
||||
dbpf("DSM:m0.TWV", "0.1")
|
||||
dbpf("DSM:m0.VMAX", "0.625")
|
||||
|
||||
dbpf("DSM:m1.RTRY", "0")
|
||||
dbpf("DSM:m1.TWV", "0.1")
|
||||
dbpf("DSM:m1.VMAX", "0.625")
|
||||
|
||||
dbpf("DSM:m2.RTRY", "0")
|
||||
dbpf("DSM:m2.TWV", "0.1")
|
||||
dbpf("DSM:m2.VMAX", "0.625")
|
||||
|
||||
dbpf("DSM:m3.RTRY", "0")
|
||||
dbpf("DSM:m3.TWV", "0.1")
|
||||
dbpf("DSM:m3.VMAX", "0.625")
|
||||
|
||||
dbpf("DSM:m4.RTRY", "0")
|
||||
dbpf("DSM:m4.TWV", "0.1")
|
||||
dbpf("DSM:m4.VMAX", "0.625")
|
||||
|
||||
dbpf("DSM:m5.RTRY", "0")
|
||||
dbpf("DSM:m5.TWV", "0.1")
|
||||
dbpf("DSM:m5.VMAX", "0.625")
|
||||
|
||||
dbpf("DSM:m6.RTRY", "0")
|
||||
dbpf("DSM:m6.TWV", "0.1")
|
||||
dbpf("DSM:m6.VMAX", "0.625")
|
||||
|
||||
dbpf("DSM:m7.RTRY", "0")
|
||||
dbpf("DSM:m7.TWV", "0.1")
|
||||
dbpf("DSM:m7.VMAX", "0.625")
|
Reference in New Issue
Block a user