UK Astronomy Technology Centre | Chris Tierney |
Royal Observatory, Edinburgh | 31st March 2001 |
naomiMechs/src
, under the top-level NAOMI software directory.The source code files fall into the following categories:
recDeviceControl.c
and recDeviceControl.h
are the record support code for the deviceControl
record.
devDeviceControl.c
and devDeviceControl.h
are the device support code for the deviceControl
record.
drvOmsVme.c
and drvOmsVme.h
comprise the device driver for the OMS motor control cards. This
is used by the NAOMI deviceControl record.The reader is encouraged to read the documentation for the deviceControl record for details of its operation.
recAssControl.c
and recAssControl.h
are the record support code for the assemblyControl record.
devAssControl_*.c
and devAssControl.h
are the device support code for each of the NAOMI
assemblies. Each assembly has its own requirements of the assemblyControl record, and this
behaviour is defined in the device support files.The reader is encouraged to read the documentation for the assemblyControl record for details of its general operation. Below is a description of the device support code written for the pickoff assembly.
naomi_*_*_gsb.c
contain the SNAM functions used by gensub records in the NAOMI software. Most
are implementations of simple state machines that use the gensub input J to store the current state from one
processing cycle to the next.
naomi_general_cad.c
and naomi_general_car.stpp
are for the CAD/CAR records originally used
for each of the NAOMI assemblies. These records are no longer required by the software, but are
still included in the database.
naomi_ncu_mask_cad.c
is the SNAM code for CAD records used on those assemblies that contain
a gensub record rather than an assemblyControl record (WFS lamp etc). This code is required
by the NAOMI software.
devAssControl.h
:
typedef struct { long number; DEVSUPFUN devReport; DEVSUPFUN devInit; DEVSUPFUN initDeviceSupport; DEVSUPFUN devGetIoIntInfo; DEVSUPFUN checkAttributes; DEVSUPFUN stopDirective; DEVSUPFUN initMode; DEVSUPFUN moveMode; DEVSUPFUN trackMode; DEVSUPFUN jogMode; DEVSUPFUN indexMode; DEVSUPFUN testMode; DEVSUPFUN ackReceived; DEVSUPFUN updateMode; } ASSEMBLY_CONTROL_DSET;
In practice, the devReport
and devGetIoIntInfo
functions are not implemented
for any of the assemblies. The device support functions implemented for the pickoff assembly can be
found listed at the top of devAssControl_pickoff.c
:
/* * Device support function prototypes */ static long pickAckReceived(ASSEMBLY_CONTROL_RECORD *); static long pickCheckAttributes(ASSEMBLY_CONTROL_RECORD *); static long pickIndexMode (ASSEMBLY_CONTROL_RECORD *); static long pickInitDeviceSupport(ASSEMBLY_CONTROL_RECORD *); static long pickInitMode (ASSEMBLY_CONTROL_RECORD *); static long pickMoveMode (ASSEMBLY_CONTROL_RECORD *); static long pickStopDirective(ASSEMBLY_CONTROL_RECORD *); static long pickTestMode (ASSEMBLY_CONTROL_RECORD *); static long pickTrackMode (ASSEMBLY_CONTROL_RECORD *); static long pickJogMode (ASSEMBLY_CONTROL_RECORD *); static long pickUpdateMode (ASSEMBLY_CONTROL_RECORD *);
The functions are called by record support at the following times:
pickInitDeviceSupport()
is called at initialisation of the database, by record support during iocInit.
The internal structures required by the assembly are allocated, and some parameters set to their default values.
pickCheckAttributes()
is called by record support during the PRESET directive cycle. PRESET is always executed
before START, regardless of whether the user has requested this. The function examines the input atrributes (fields A
through J), to check that those required are of the required type. The directive is rejected if any fields have the wrong type.
pickInitMode(), pickIndexMode()
etc are called by record support when the START directive cycle is underway.
One function is supplied for each mode of the record. A start directive when in INDEX mode, for example, results in
the indexMode funtion (pickIndexMode()
in this case) being called by record support. The pickIndexMode()
and pickMoveMode()
functions are described in more detail below.
pickStopDirective()
is called by record support in response to a STOP directive. The device support code should
stop its current operation and clear out any remaining tasks from its list. It then forwards STOP directives to any attached devices
that are currently BUSY, creating a task for this operation. The task is complete when all the BUSY devices have returned to the IDLE
state.
pickAckReceived()
is called by record support whenever the BUSY state of an attached deviceControl record
changes, or in the event of a timeout. This function examines which devices are currently busy, against the list of devices
being used by the task currently being executed, and arranges for the next task to be started (if there is one) when all
device have returned to the IDLE state. Unexpected activity from a device, or a call that results from a timeout, will
cause the function to signal an appropriate error message.
checkAttributes()
function, followed by one of
the mode-specific device support functions, depending upon the current value of the MODE field of the record.
Some of these functions (for TEST and UPDATE modes, for example) take very little action and return. These modes are not
implemented in the NAOMI software. The other modes (INIT, INDEX, MOVE, TRACK, JOG and the stopDirective()
function), however, respond by building a list of tasks to perform, starting the first task, and returning. When the task
is complete, either by callback (timeout) or when one or more of the devices has returned to the IDLE state, the
ackReceived()
function clears the current task from the list and begins the next one. When all tasks are
complete, ackReceived informs record support that the assemblyControl record may return to the IDLE state from BUSY.
We examine here the operation of the pickIndexMode()
and pickMoveMode()
functions.
This list of tasks defined for this assembly is enumerated at the top of the file:
/* * List of tasks to ask the Assembly to do. */ typedef enum { PICK_IX_DEV1_LOW = 1, PICK_IX_DEV1_HIGH = 2, PICK_IX_DEV2_LOW = 3, PICK_IX_DEV2_HIGH = 4, PICK_IX_DEV3_LOW = 5, PICK_IX_DEV3_HIGH = 6, PICK_IX_DEV4_HOME = 7, PICK_IX_DEV5_LOW = 8, PICK_IX_DEV5_HIGH = 9, PICK_IX_DEV1_REIX = 10, PICK_IX_DEV2_REIX = 11, PICK_IX_DEV3_REIX = 12, PICK_IX_DEV4_REIX = 13, PICK_IX_DEV5_REIX = 14, PICK_MV_ALL = 15, PICK_MV_DEV1 = 16, PICK_MV_DEV2 = 17, PICK_MV_DEV3 = 18, PICK_MV_DEV4 = 19, PICK_MV_DEV5 = 20, PICK_MV_DEV5_SAFE = 21, PICK_JG_ALL = 22, PICK_JG_DEV1 = 23, PICK_JG_DEV2 = 24, PICK_JG_DEV3 = 25, PICK_JG_DEV4 = 26, PICK_JG_DEV5 = 27, PICK_INIT_ALL = 28, PICK_INIT_DEV1 = 29, PICK_INIT_DEV2 = 30, PICK_INIT_DEV3 = 31, PICK_INIT_DEV4 = 32, PICK_INIT_DEV5 = 33, PICK_STOP_ALL = 34 } tPickTaskList;
Those mode-specific functions that require a task list call the internal function pickBuildList()
,
which examines the current mode and constructs a task list accordingly. The list constructed when in INDEX
mode is specified near the top of the file:
static ASS_TASK_LIST pickIndex[] = { { PICK_IX_DEV5_LOW, FALSE, FALSE, FALSE, FALSE, TRUE }, { PICK_MV_DEV5_SAFE, FALSE, FALSE, FALSE, FALSE, TRUE }, { PICK_IX_DEV3_HIGH, FALSE, FALSE, TRUE, FALSE, FALSE }, { PICK_IX_DEV1_HIGH, TRUE, FALSE, FALSE, FALSE, FALSE }, { PICK_IX_DEV1_REIX, TRUE, FALSE, FALSE, FALSE, FALSE }, { PICK_IX_DEV3_LOW, FALSE, FALSE, TRUE, FALSE, FALSE }, { PICK_IX_DEV3_REIX, FALSE, FALSE, TRUE, FALSE, FALSE }, { PICK_IX_DEV5_LOW, FALSE, FALSE, FALSE, FALSE, TRUE }, { PICK_IX_DEV5_REIX, FALSE, FALSE, FALSE, FALSE, TRUE }, { PICK_MV_DEV5, FALSE, FALSE, FALSE, FALSE, TRUE }, { PICK_MV_DEV1, TRUE, FALSE, FALSE, FALSE, FALSE }, { PICK_MV_DEV3, FALSE, FALSE, TRUE, FALSE, FALSE }, { PICK_IX_DEV2_HIGH, FALSE, TRUE, FALSE, FALSE, FALSE }, { PICK_IX_DEV2_REIX, FALSE, TRUE, FALSE, FALSE, FALSE }, { PICK_MV_DEV2, FALSE, TRUE, FALSE, FALSE, FALSE }, { PICK_IX_DEV4_HOME, FALSE, FALSE, FALSE, TRUE, FALSE }, { PICK_MV_DEV4, FALSE, FALSE, FALSE, TRUE, FALSE } };
Note that the tasks are given in the order in which they will be performed. The five boolean entries
given on each line specify which devices should be operated for each task. So, for instance, the first
task is an INDEX to the lower limit switch from the fifth device, the CCD assembly. When the device
BUSY state has undergone an IDLE-BUSY-IDLE transition, pickAckReceived()
clears this task
from the list of tasks maintained by the device support code and proceeds to the next task.
The list of tasks above implement the indexing procedure detailed in the documentation for the pickoff assembly screen.
pickBuildList()
(after constructing a task list) and pickAckReceived()
(when
a task has completed) both call the function pickDoTask()
to execute the next task. This function
looks at the task being executed, fills an internal structure (of type ASS_DEV_PRIVATE, see file
devAssControl_general.h) with appropriate motion parameters for the required devices, and calls the
function pickExecuteTask()
to setup and start the devices. The first task above, for example,
tells pickDoTask()
that device 5 must be sent a mode of MOVE, a default velocity, and a target
position string "ixlow". pickExecuteTask()
sends these parameters, followed by the GO directive,
to the device.
The list of tasks for the assembly's MOVE mode is as follows:
static ASS_TASK_LIST pickMoveAll[] = { { PICK_MV_ALL, TRUE, TRUE, TRUE, TRUE, TRUE } };
A move operation consists of a single task, that of moving all devices simultaneously. For this task, the
pickDoTask()
uses function pickMoveParameters()
to calculate the motion
parameters (velocity, target position etc) for each device. This is an important function which contains
the algorithms that ensure that the wavefront sensor will maintain focus whilst the pickoff probe (devices
1 and 2, for this assembly) is being moved. Other assemblies have an analogous function.
[Note: In fact the single device moves, for example PICK_MV_DEV3 used in the index task list above, utilise the same function, in order that the wavefront sensor pickoff assembly finishes an index operation in focus.]
The reader is invited to examine the function (which is rather complex to reproduce here) if desired. The function implements the algorithms described in the documentation for the pickoff assembly screen, for calculating the required positions of each stage, based upon the (numeric or named position) strings found in record input fields A though E. If required (input attribute G), velocities are calculated such that the devices will finish motion at the same time. If not, default velocities are used.
Named positions for each of the devices, and offsets and parameters used in the pickMoveParameters()
algorithms, are contained in pick_assembly.lut, the lookup table for
the pickoff assembly.
A useful examination of the operation of the assemblyControl record can be acheived if the user changes the debug mode of the record. A menu for changing the debug mode can be found on the assemly screen.