IOC Configuration¶
This section covers everything needed to build, configure, and run a Galil EPICS IOC: build requirements, shell commands, database substitution files, autosave setup, and custom code.
Building¶
Compiler Requirements¶
The Galil EPICS driver requires a C++11-compliant compiler because it uses the unordered_map container. On Linux, gcc 4.8.1 or later is recommended. Older Linux distributions may require the devtoolset2 toolchain or newer. On Windows, Visual Studio 2010 or later is required.
EPICS Base¶
EPICS base version 3.14.12.2 or newer is required.
Required Support Modules¶
| Module | Minimum Version |
|---|---|
| ASYN | 4-26 |
| Autosave | 5-5 |
| SNCSEQ | 2-1-8 |
| SSCAN | 2-8-1 |
| CALC | 3-4-2 |
| Busy | 1-6 |
| Motor | 6-8-1 |
| IPAC | 2-11 |
Release Configuration¶
The driver has both a config directory and a standard configure directory. The file config/GALILRELEASE serves as both a standard release file and a master release file. The configure/RELEASE file simply includes GALILRELEASE. The config directory supports building both the driver and the included example IOC using the SynApps build approach.
To define the paths to all required support modules, either:
- Populate
config/GALILRELEASEas a normal release file, or - Populate
configure/RELEASEas a normal release file and delete the line that includes$(TOP)/config/GALILRELEASE.
Creating an IOC¶
Create the Application¶
Create an IOC application using the EPICS makeBaseApp.pl script:
mkdir <IOCName>
cd <IOCName>
makeBaseApp.pl -t ioc <IOCName>
makeBaseApp.pl -i -t ioc <IOCName>
Adding Galil Support¶
Add the following lines to <IOCApp>/src/Makefile:
<IOCName>_DBD += GalilSupport.dbd
<IOCName>_LIBS += GalilSupport
IOC Shell Commands¶
GalilCreateController¶
GalilCreateController(portName, address, updatePeriod)
Creates a connection to a Galil controller and registers an asyn port. This must be called before all other Galil driver commands for a given controller.
| Parameter | Description |
|---|---|
portName |
Asyn port name (e.g. "Galil1", "RIO01") |
address |
Controller IP address or serial port (e.g. "192.168.0.67", "COM1") |
updatePeriod |
Data record update period in ms (valid range: 2--200). A positive value tries asynchronous UDP first and falls back to TCP. A negative value forces synchronous TCP only. For ethernet connections, 50 ms or less is recommended; 8 ms is typical. |
Example -- two controllers:
GalilCreateController("Galil1", "192.168.0.67", 8)
GalilCreateController("Galil2", "192.168.0.68", 8)
GalilCreateAxis¶
GalilCreateAxis(portName, axis, limitsAsHome, motorInterlocks, switchType)
Creates a motor axis on a previously created controller. Must be called after GalilCreateController and before GalilStartController.
| Parameter | Description |
|---|---|
portName |
Asyn port name matching a prior GalilCreateController call |
axis |
Axis letter, A through H (up to 8 axes per controller) |
limitsAsHome |
Use limit switches as home switches. 0 = off (default), 1 = on. |
motorInterlocks |
Comma-separated digital port numbers (1--8) that interlock this motor (e.g. "1,2,4"). Only the first 8 bits are supported. Use "" for no interlocks. |
switchType |
Interlock switch type. 0 = interlock is active when the opto is active. Any other value = interlock is active when the opto is inactive. |
Example -- two axes on each of two controllers:
GalilCreateAxis("Galil1", "A", 1, "", 1)
GalilCreateAxis("Galil1", "B", 1, "", 1)
GalilCreateAxis("Galil2", "A", 1, "", 1)
GalilCreateAxis("Galil2", "B", 1, "", 1)
GalilCreateCSAxes¶
GalilCreateCSAxes(portName)
Creates all coordinate system axes (I--P) on the specified controller. This must be called after all GalilCreateAxis calls for that controller, and before GalilStartController.
Example:
GalilCreateCSAxes("Galil1")
GalilCreateCSAxes("Galil2")
GalilStartController¶
GalilStartController(portName, codeFile, burnProgram, threadMask)
Downloads DMC code to the controller and starts execution. Must be called after all other Galil driver commands for the controller, but before iocInit().
| Parameter | Description |
|---|---|
portName |
Asyn port name |
codeFile |
DMC code file(s) to deliver. Use "" to use auto-generated code (recommended for most setups). For template-based code, specify header, body, and footer files in the format "headerfile;bodyfile1!bodyfile2!bodyfileN;footerfile". |
burnProgram |
0 = transfer code if it differs from what is on the controller, do not burn to EEPROM, execute thread 0. 1 = transfer code if it differs, burn to EEPROM, execute thread 0. |
threadMask |
Specifies which threads to verify are running after start. Bit 0 corresponds to thread 0, bit 1 to thread 1, and so on. A negative value disables the check. 0 checks threads 0 through N, where N is the number of GalilCreateAxis calls -- this is the correct setting when using auto-generated code. |
Example:
GalilStartController("Galil1", "", 1, 0)
GalilStartController("Galil2", "", 1, 0)
The driver writes a copy of the code delivered to the controller to the iocBoot directory with extension .gmc.
GalilCreateProfile¶
GalilCreateProfile(portName, maxPoints)
Enables profile (trajectory) motion support on the controller. Must be called after all other Galil driver commands except GalilStartController.
| Parameter | Description |
|---|---|
portName |
Asyn port name |
maxPoints |
Maximum number of points in a trajectory (e.g. 2000) |
Example:
GalilCreateProfile("Galil1", 2000)
GalilCreateProfile("Galil2", 2000)
GalilAddCode¶
GalilAddCode(portName, section, codeFile)
Inserts custom DMC code into the auto-generated code at a specified section.
| Parameter | Description |
|---|---|
portName |
Asyn port name |
section |
Target section: 0 = card code, 1 = thread code, 2 = limits code, 3 = digital code |
codeFile |
Path to the custom DMC code file |
GalilReplaceHomeCode¶
GalilReplaceHomeCode(portName, axis, codeFile)
Replaces the auto-generated homing routine for a single axis with custom DMC code from a file.
| Parameter | Description |
|---|---|
portName |
Asyn port name |
axis |
Axis letter (A--H) |
codeFile |
Path to the custom homing code file |
Environment Variables¶
The following environment variables are used in Galil IOC startup scripts and database substitution files.
| Variable | Description | Example |
|---|---|---|
PORT |
Asyn port name | Galil1 |
ADDRESS |
Controller IP address or serial port | 192.168.0.67 |
UPDPERIOD |
Data record update period in ms | 8 |
P |
PV prefix, typically derived from PORT |
DMC01: |
GALIL_DEBUG_FILE |
When set, all commands sent to the Galil controller are logged to this file | galil_debug.txt |
Database Substitution Files¶
Each driver feature has a corresponding substitution file that loads the EPICS database records for that feature. Below are representative examples showing the substitution file format and macros for each feature category.
General Principles¶
Configuring a feature typically requires three steps:
- Configure autosave request files for the feature.
- Configure the database substitution file for the feature.
- Add the appropriate shell commands to the IOC start script.
It is recommended that only the controller prefix (P) be changed between controllers. To identify individual motors or ports, use the record DESC field rather than changing record names. The description field is shown on all provided display screens and is saved/restored by autosave.
Hardware configuration (motor type, encoder type, etc.) is done at runtime through the provided display screens and saved by autosave -- not through substitution file macros.
Controller¶
The controller database is loaded using galil_ctrl_extras.substitutions:
# P - PV prefix
# PORT - Asyn port name
# SCAN - Scan period for monitor records. "Passive" recommended (default).
# DEFAULT_LIMITTYPE - 0 Normally open, 1 Normally closed
# DEFAULT_HOMETYPE - 0 Normally open, 1 Normally closed
# PREC - Precision
file "$(GALIL)/GalilSup/Db/galil_ctrl_extras.template"
{
pattern
{ P, PORT, SCAN, DEFAULT_HOMETYPE, DEFAULT_LIMITTYPE, PREC}
{ "DMC01", "Galil1", "Passive", 1, 1, 5 }
}
For RIO installations, only the start script section of the controller configuration is needed -- the autosave and database sections can be skipped.
Motor Records¶
The motor database is loaded using galil_motors.substitutions. At minimum, the galil_motor.template file must be used. Loading motor records with the templates that ship with the EPICS motor record (instead of the Galil-specific template) is not supported.
Each motor (real axes A--H and CS axes I--P) requires a single line entry. Motor record addresses are numbered from 0: real axes are 0--7 and CS axes are 8--15.
Motor Extras¶
Motor extras provide per-axis features not covered by the EPICS motor record (motor type, encoder type, home type, etc.). Motor extras are mandatory for real motors and are not used for CS motors.
The motor extras database is loaded using galil_motor_extras.substitutions:
# P - Controller prefix
# M - Motor name
# PORT - Asyn port of controller
# ADDR - Axis number 0-7
# PREC - Precision of analog records
# SCAN - Scan period for monitor records. "Passive" recommended.
# MTRTYPE - Motor type:
# 0 - Servo
# 1 - Reverse servo
# 2 - High active stepper
# 3 - Low active stepper
# 4 - Reverse high active stepper
# 5 - Reverse low active stepper
# MTRON - Motor off 0, motor on 1
# EGU - Engineering units
file "$(GALIL)/GalilSup/Db/galil_motor_extras.template"
{
pattern
{ P, M, PORT, ADDR, PREC, SCAN, MTRTYPE, MTRON, EGU }
{ "DMC01", "A", "Galil1", 0, 3, "Passive", "0", "0", "mm" }
{ "DMC01", "B", "Galil1", 1, 3, "Passive", "0", "0", "mm" }
}
CS Motors¶
CS motors use the EPICS motor record, so the autosave and database setup is identical to that for real motors (see Motor Records above). However, CS motor positions are not managed by autosave -- they are calculated from real motor positions via the forward kinematic transform.
Coordinate Systems¶
Galil controllers provide two hardware coordinate systems, S and T. Coordinate systems are used when coordinating the motion of two or more motors in linear interpolation mode. They are also used for "sync start and stop" deferred moves and "linear mode" profile motion.
In PVT mode (Accelera series and above), more than two motors can be coordinated without using a coordinate system. For this reason, configuring coordinate systems is not mandatory in all cases, but is recommended for completeness.
Autosave is not used for coordinate systems.
The coordinate system database is loaded using galil_coordinate_systems.substitutions:
# P - PV prefix
# R - Record Name (S or T)
# PORT - Asyn port name
# ADDR - Hardware port to read (0 for S, 1 for T)
# SCAN - Scan period for monitor records
file "$(GALIL)/GalilSup/Db/galil_coordinate_system.template"
{
pattern { P, R, PORT, ADDR, SCAN }
{ "DMC01", "S", "Galil1", "0", ".1 second" }
{ "DMC01", "T", "Galil1", "1", ".1 second" }
}
Kinematics¶
Kinematics define the relationship between real motors and CS motors. For each CS motor there is one forward transform (readback) and eight reverse transforms (setpoints, one per real motor A--H). Kinematic variables (Q--Z) have controller-wide scope and can be used in transform expressions. All equations and variables are runtime-adjustable via the EPICS database.
The kinematics database is loaded using galil_csmotor_kinematics.substitutions, which has three sections: forward transforms, reverse transforms, and kinematic variables.
Forward transforms (one per CS motor):
file "$(GALIL)/GalilSup/Db/galil_forward_transform.template"
{
pattern { P, M, PORT, ADDR }
# CS motor I (address 8)
{ "DMC01", "I", "Galil1", "8" }
}
Reverse transforms (one per CS motor, maps back to real motors):
file "$(GALIL)/GalilSup/Db/galil_reverse_transforms.template"
{
pattern { P, M, PORT, ADDR }
{ "DMC01", "I", "Galil1", "8" }
}
Kinematic variables (10 per controller, Q--Z, addressed 0--9):
file "$(GALIL)/GalilSup/Db/galil_kinematic_variable.template"
{
pattern { P, R, PORT, ADDR, PREC }
{ "DMC01", "Q", "Galil1", "0", "5" }
}
An example substitution file is provided at GalilTestApp/Db/galil_csmotor_kinematics.substitutions.
Analog I/O¶
The analog I/O database is loaded using galil_analog_ports.substitutions. The file has separate sections for input and output ports.
DMC ports are numbered 1--8 on the controller hardware but 0--7 at the database layer for the GUI.
Input ports:
# P - PV prefix
# R - Record Name
# PORT - Asyn port name
# ADDR - Hardware port to read
# SCAN - Scan period
# PREC - Precision
file "$(GALIL)/GalilSup/Db/galil_analog_in.template"
{
pattern { P, R, PORT, ADDR, SCAN, PREC }
{ "DMC01", "GalilAi0", "Galil1", "1", "I/O Intr", "3" }
{ "DMC01", "GalilAi1", "Galil1", "2", "I/O Intr", "3" }
}
Output ports:
# P - PV prefix
# R - Record Name
# PORT - Asyn port name
# ADDR - Hardware port
# PREC - Precision
# LOPR - Low operating range
# HOPR - High operating range
file "$(GALIL)/GalilSup/Db/galil_analog_out.template"
{
pattern { P, R, PORT, ADDR, PREC, LOPR, HOPR }
{ "DMC01", "GalilAo0", "Galil1", "1", "3", "-10", "10" }
{ "DMC01", "GalilAo1", "Galil1", "2", "3", "-10", "10" }
}
Digital I/O¶
On DMC controllers, digital inputs are organized in bytes and digital outputs are organized in 16-bit words. On RIO units, both inputs and outputs are organized in bytes. However, at the database layer the RIO digital outputs are named in words (to be consistent with DMC units) so the same GUI can be used.
The digital I/O database is loaded using galil_digital_ports.substitutions. The file has separate sections for input and output bit records.
Input bits:
# P - PV prefix
# R - Record Name
# PORT - Asyn port name
# BYTE - Hardware byte to read
# MASK - Mask for this bit
# ZNAM/ONAM - State names
# ZSV/OSV - Alarm severities
file "$(GALIL)/GalilSup/Db/galil_digital_in_bit.template"
{
pattern {P, R, PORT, BYTE, MASK, ZNAM, ONAM, ZSV, OSV }
{DMC01, Galil0Bi0, Galil, 0, 0x000001, "Off", "On", "NO_ALARM", "NO_ALARM" }
{DMC01, Galil0Bi1, Galil, 0, 0x000002, "Off", "On", "NO_ALARM", "NO_ALARM" }
}
Output bits:
# P - PV prefix
# R - Record Name
# PORT - Asyn port name
# WORD - Hardware word to read
# MASK - Mask for this bit
file "$(GALIL)/GalilSup/Db/galil_digital_out_bit.template"
{
pattern {P, R, PORT, WORD, MASK, ZNAM, ONAM, ZSV, OSV }
{DMC01, Galil0Bo0, Galil, 0, 0x000001, "Off", "On", "NO_ALARM", "NO_ALARM" }
{DMC01, Galil0Bo1, Galil, 0, 0x000002, "Off", "On", "NO_ALARM", "NO_ALARM" }
}
Profile Motion¶
Profile motion involves one or more motors following a user-defined position profile, executed using linear interpolation mode or PVT mode (Accelera series and above). Some profile features relate to the controller and others to the individual axes.
Autosave is not used for profile motion settings.
Controller-level profile records are loaded using galil_profileMoveController.substitutions:
# Profile move controller (from motor module)
file "$(MOTOR)/db/profileMoveController.template"
{
pattern
{P, R, PORT, NAXES, NPOINTS, NPULSES, TIMEOUT}
{DMC01:, Prof1:, Galil, 8, 1441, 1441, 1}
}
# Galil-specific profile move controller features
file "$(GALIL)/GalilSup/Db/galil_profileMoveController.template"
{
pattern
{P, R, PORT, TIMEOUT}
{DMC01:, Prof1:, Galil, 1}
}
Per-axis profile records are loaded using galil_profileMoveAxes.substitutions. Refer to GalilTestApp/Db/galil_profileMoveAxis.substitutions for an example.
Database Loading Order¶
A typical DMC startup script (e.g. DMC01Configure.cmd) loads databases in the following order:
- Motor records -- real axes and coordinate system axes, loaded via substitution files.
- DMC controller features --
galil_dmc_ctrltemplate (controller-wide status and settings). - Amplifier status --
galil_quadAmpStatustemplate (per-amplifier diagnostics). - Motor extras -- motor type, encoder type, and other per-axis settings beyond what the motor record provides.
- CS motor extras -- additional settings for coordinate system axes.
- Kinematics -- forward and reverse kinematic transform definitions.
- Coordinate system features -- coordinate system status and control records.
- Digital I/O -- digital input and output port records.
- Analog I/O -- analog input and output port records.
- User-defined records -- any site-specific records.
- User arrays -- Galil user array records.
- Profile move support -- profile move controller and per-axis trajectory records.
Autosave Configuration¶
Autosave preserves settings and positions across IOC restarts. Configuring autosave typically requires three things: request files, a configuration script, and monitor set creation in the IOC start script.
Request Files¶
Two autosave request files should be created in the iocBoot directory for each IOC:
IOCName_settings.req-- saves all settings for connected controllers and their motors.IOCName_positions.req-- saves motor positions.
Configuration Script¶
An autosave command script (e.g. autosave.cmd) should be added to the iocBoot directory and sourced from the IOC start script. It must contain the request file search paths so autosave can find the provided .req files:
set_requestfile_path("${GALIL}/GalilSup/Db", "")
set_requestfile_path("${MOTOR}/motorApp/Db", "")
set_requestfile_path("${TOP}/iocBoot/${IOC}", "")
It must also configure the restore operations. Positions and settings are restored at pass 0 (before record initialization) so that raw counts are converted correctly and motors do not move to zero on restart:
# Restore positions at pass 0 so motors don't move
set_pass0_restoreFile("IOCName_positions.sav")
# Restore settings at pass 0
set_pass0_restoreFile("IOCName_settings.sav")
Optionally, specify where autosave stores its backup files:
set_savefile_path("/autosave", "")
Kinematic equations (stored in waveform records) must be restored at pass 1, after record initialization:
Kinematics.sav-- kinematic equation character arrays (forward and reverse transform expressions).
Monitor Sets¶
In the IOC start script, after iocInit(), create monitor sets for each request file:
# Save motor positions every 5 seconds
create_monitor_set("IOCName_positions.req", 5, "P1=DMC01:, P2=DMC02:")
# Save motor settings every 30 seconds
create_monitor_set("IOCName_settings.req", 30, "P1=DMC01:, P2=DMC02:")
Per-Feature Request Files¶
The driver provides ready-made .req files for each feature. Add lines to IOCName_settings.req for each feature in use:
Controller (one per controller):
file "galil_ctrl_extras.req" P=$(P)
Motor records (one per motor, real and CS):
file "motor_settings.req" P=$(P), M=A
Motor positions (add to IOCName_positions.req, one per real motor):
$(P)A.DVAL
CS motor positions are not saved -- they are calculated from real motor positions.
Motor extras (one per real motor):
file "galil_motor_extras.req" P=$(P), M=A
Analog inputs (one per channel):
file "galil_analog_in.req" P=$(P), R=GalilAi0
Analog outputs (one per channel):
file "galil_analog_out.req" P=$(P), R=GalilAo0
Digital inputs (one per bit):
file "galil_digital_in.req" P=$(P), R=Galil0Bi0
Digital outputs (one per bit):
file "galil_digital_out.req" P=$(P), R=Galil0Bo0
Kinematics -- forward transforms (one per CS motor):
file "galil_forward_transform.req" P=$(P), M=I
Kinematics -- reverse transforms (one per CS motor):
file "galil_reverse_transforms.req" P=$(P), M=I
Kinematics -- variables (one per variable, Q--Z):
file "galil_kinematic_variable.req" P=$(P), R=Q
Custom Controller Code¶
The DMC code that runs on the controller defines homing behavior, limit switch activation behavior, and motor enable/interlock behavior for each motor. In most cases, the auto-generated code from the Galil EPICS driver is sufficient, and the codeFile parameter of GalilStartController should be an empty string "".
When custom code is needed, the recommended process is:
- Run the IOC once with no code file specified in
GalilStartController(use""). - Open the auto-generated code file that the driver dumps to the
iocBootdirectory (extension.gmc). - Add custom code in the correct thread, without changing the overall structure.
- Save the file with a meaningful name.
- Specify the custom code file in
GalilStartController, or useGalilAddCode/GalilReplaceHomeCodeto inject code into specific sections.
Logging¶
Solicited command/response traffic between the IOC and controller can be logged to a file. To enable logging, add the following to the IOC start script:
epicsEnvSet("GALIL_DEBUG_FILE", "galil_debug.txt")
When using the provided example IOC, uncomment the corresponding line in iocBoot/iocGalil/st.cmd.
User Display Configuration¶
MEDM and Qt (QEGUI) displays are provided with the driver. The Qt screens are recommended as they provide a more intuitive interface, a modern look and feel, and "user levels" to protect engineering settings from accidental changes.
MEDM¶
- DMC controllers: launch with the
start_dmc_screen.shscript. - RIO controllers: launch with the
start_rio_screen.shscript.
The screen start scripts use config/GALILRELEASE to construct the EPICS_DISPLAY_PATH environment variable so that MEDM can find the necessary community screens and the Galil-specific screens. Depending on the release configuration approach chosen (see Building above), the scripts may need to reference configure/RELEASE instead.
QEGUI¶
The QEGUI framework (a Qt-based EPICS display manager developed at the Australian Synchrotron) is available at https://sourceforge.net/projects/epicsqt/.
- DMC controllers: launch with the
start_qedmc_screen.shscript. - RIO controllers: launch with the
start_qerio_screen.shscript.
These scripts use config/GALILRELEASE to construct the QE_UI_PATH environment variable.
DMC vs RIO¶
Galil produces two categories of controller relevant to IOC configuration: DMC and RIO. The choice determines which templates and shell commands are appropriate.
DMC (Digital Motion Controller) provides full motion control capability: motor axes, coordinate system axes, digital and analog I/O, profile moves, and output compare. The IOC uses galil_dmc_ctrl.template for controller-level records and calls GalilCreateAxis, GalilCreateCSAxes, and the full set of shell commands documented above.
RIO (Remote I/O) provides digital and analog I/O only, with no motor axis support. The IOC uses galil_rio_ctrl.template, which omits limit/home switch type configuration, deferred move support, coordinate systems, and output compare. A RIO startup script calls GalilCreateController and GalilStartController but does not call GalilCreateAxis, GalilCreateCSAxes, or GalilCreateProfile.
The building requirements, substitution file examples, autosave configuration details, custom code workflow, and user display information in this section are adapted from the "Galil EPICS Driver Configuration Guide" (Rev 1.2, June 2016) by Mark Clift, Australian Synchrotron. Refer to the original documentation for the full document.