Many of Fermilab's data acquisition and control devices reside on a CAMAC serial link. CAMAC is a protocol/hardware bus that allows instruments to communicate. Up to 256 CAMAC "crates" can be attached to a serial link and each crates can have up to 20 slots containing CAMAC modules.
At Fermilab, our front-ends initiate the communications with CAMAC modules. This is done by writing a "CNAF" to the link. A CNAF contains crate and slot information, which addresses a specific module on the link. It also contains "sub-address" and "function" information which is device-specific and determines the functionality requested of the module. If the CNAF specifies a write-operation, 24-bits of data will also be sent. If the CNAF requests data from the module, 24-bits of return data will be expected.
The SLD library allows an application to create a CNAF
by using the CamacRequest
structure:
typedef struct {
unsigned char C;
unsigned char N;
unsigned char F;
unsigned char A;
unsigned long data;
unsigned char retries;
unsigned char lock;
} CamacRequest;
The C, N, A, and F, fields specify, obviously, the CNAF. If the CNAF is writing data to the module, the data field should be filled. Only the low 24 bits of the field will be sent.
Some CAMAC modules are slow in responding and will return an error. If the same CNAF is sent, eventually a good result can be obtained. The SLD hardware will automatically retry up to three times. The application can further increase the number by setting the retries field for modules that are known to be slow (this field is multiplicative -- i.e. setting retries to 4 results in 12 hardware retries!)
On systems where multiple front-ends can send CNAFs, it is sometimes useful to "lock" the serial link to ensure that a group of CNAFs are processed atomically. If the lock field is set, the current and next CNAFs will be sent on the serial link atomically.
The results of a CAMAC operation are stored in a
CamacReply
structure:
typedef struct {
unsigned long data;
unsigned long flag;
} CamacReply;
The data field will hold return data (if the CNAF performed a read operation.)
The flag field is used to report any errors that occurred during the CAMAC operation. An error is tested by checking individual bits in flag:
SLD_NO_GNT --
(No Grant) The SLD
couldn't gain access to the serial link.
SLD_TIMEOUT --
(No Answer) The crate
doesn't exist on the serial link.
SLD_NO_Q --
(No Q) Either the CAMAC
module doesn't exist in the slot, or the module hasn't
been given enough time to respond. Increasing the
number of retries should correct the latter case.
SLD_ERROR_PARITY --
The command sent by
the SLD became corrupted. This indicates a serial link
problem. Retrying the command might work for the
short-term.
Sending CAMAC commands only requires the use of one
function, sendCamacIO()
. An array of
CamacRequests, along with an array of
CamacReplys, is passed. The calling task will
block until the entire transaction has completed.
A module in crate $40
, slot 7 responds to
A(0)F(6)
by returning its module ID.
#include <logMods.h>
#include <sld.h>
struct CamacRequest req = { 0x40, 7, 0, 6, 0, 0, 0 };
struct CamacReply rep = { 0, 0 };
if (OK == sendCamacIO(& req, & rep, 1) && !rep.flag)
logMsg1("CAMAC module ID: %d", rep.data);
else
logMsg0("Error sending CAMAC command!");