Device Support for the CAEN V965 QDC Board


 

1. Board Configuration and Driver Initialization

The board address switches are located near P1 and P2 at the rear of the card. These are rotary switches with 16 positions so each switch sets 4 bits.
The uppermost switch sets bits <19..16> of the base addresss and other switch in the upper pair sets bits <23..20>.  The lower pair sets bits <27..24> and bits <31..28>.
By default the card can be addressed using an A24 address defined in the upper pair of switches only or an A32 address using all 4 switched.  Note that the MSB is the bottom switch.

Once the board is installed and the crate is powered up the position of the on board power switch must be determined.  The power switch is a alternate action pushbutton switch recessed in the front panel
between the banks of inputs.  The "Busy" led blinks on briefly when the crate is reset and the switch is on.  If the switch is not in the on position then the board will not respond to commands on the VME bus.

The Makefile in the src directory builds both a munch file and a library file supporting either run time or build time linking.
To initialize the board on a vxWorks or RTEMS IOC do the following:

Add the driver to the IOC's RELEASE file CAEN_V965=$(SHARE_RELEASE)/caen_v965/Initial
Link or Load the driver.
Build time linking case: Add to src/Makefile in your iocApp directory.
timingLabAll_LIBS_vxWorks += caen_v965

Run time linking case: Add to st.cmd
cd caen_v965bin
ld <caen_v965Lib.munch
Load the dbd file
Build time linking case: (in myApp/src/myAppInclude.dbd)
include "caen_V965.dbd"

Run time linking case: (in st.cmd)
cd caen_v965
dbLoadDatabase("dbd/caen_v965.dbd",0,0)
caen_v965_registerRecordDeviceDriver
Initialize the driver
caenV965Config 0, 0xca0000, 24, 0x99, 1, 0
Where argument 1 is the board instance number,
argument 2 is the base address of the board in A24 or A32 space,
argument 3 is the address space (24 or 32),
argument 4 is the interrupt vector,
argument 5 is the interrupt level, and
argument 6 is the number of samples per cycle, 1 trigger per sample
Load the database
See the database section.

2. Device Support

The V965 card has a rather specialized register interface.  Some of the features of this board have been disabled while other features have been hidden by the driver in order to provide a standard interface.

Q/D conversion is done using two a/d conversions on each channel such that a low range returns values from 0 to 3840 counts and the high range returns 0 to 4095 counts scaled by 8.  By using the high range scaled by multiplying by 8 only when the low range conversion is out of range high an effective 15 bit dynamic range is possible.

The sliding scale feature of this board is not supported and is disabled by the driver.  Our application is mostly single pulse and the use of the sliding scale would introduce errors.

The IPED register is supported.  The IPED register controls a current source connected to each channel so that the internal bias currents can be nulled out.  For a current measurement this value should be set using an open channel and at the operating gate width.

Unused channels, those with no associated records, will be configured with the 'kill' bit set in the threshold register.  The threshold register is not otherwise used.  Both under and over range readings will be saved on each gate for each active channel and read by the ISR.  The device support will provide threshold subtraction as described below.

The following is the contents of caen_v965.dbd:
driver(drvCaenV965)
# ai device support
device(ai,VME_IO,devCaenV965AI,"CAEN V965")
# longin device support
device(longin,VME_IO,devCaenV965Longin,"CAEN V965")
# longout device support
device(longout,VME_IO,devCaenV965Longout,"CAEN V965")



Device support is provided for record types ai, longin, and longout. All record types share a common device support layer requiring an INP or OUT field in the record to provide VME_IO parameters.
The card field in the record's link is the same card number used in the initialize call. The signal number field refers to the QDC channel number. The parameter field can have the following values and meanings.

param
Meaning
'I'
Read and set the IPED Register
'N'
Read the board serial number
'H'
Read the raw high range ADC value for the channel (I/O intr scan supported)
'L'
Read the raw low range ADC value for the channel (I/O intr scan supported)
'S'
Read the status bits for the channel.  (I/O intr scan supported)
Bits <3..0> are:
HIGH Over range, HIGH under range, LOW over range, LOW under range.
'TH'
Read and set the high channel threshold or zero offset.
'TL'
Read and set the low channel threshold.
Anything else or nothing
Read the value.  (I/O intr scan supported) If the low range ADC value is not over range then subtract the 'TL' value and return the result. Otherwise, subtract the 'TH' value from the high range ADC value and return 8* the result.  Ai record scaling constants should be supplied based on a 15 bit raw ADC value.

If the parameter is a number then it sets the multiple sample mode. In that case the sample is taken on the Nth trigger on this channel.
The last chanel to initialize on this channel sets this.

3. API

extern "C" STATUS drvCaenV965SetState(int board , int state);
void drvCaenV965Device::setState(int newState);
Set the state counter to state.  Typically you would set the state counter to zero just before triggering a threshold reading.

extern "C" STATUS drvCaenV965Wait(int board);
long drvCaenV965Device::wait();
 Wait for an interrupt after a gate.  A process can then use the getValue() function to process incoming data.
Wait only returns after the state reaches the number of states initialized in argument 6 of caenV965Config(). At that point you must either call revCaenV965SetState() or accept data on every gate.

int drvCaenV965Device:getValue( int signal, const char * parm , epicsInt32  * value);
Get a value.  Signal number and parm are the same as is used by a record.

int drvCaenV965Device:putValue( int signal, const char * parm , epicsInt32  value);
Set a value.  Signal number and parm are the same as is used by a record.

drvCaenV965Device * drvCaenV965Device::getV965Handle(int card);
Get a pointer to a drvCaenV965Device object.

4. Implementation notes

This driver is implemented in C++.  The main class objects are listed below:
Class
Declared in:
Implemented in: Purpose
drvCaenV965DSet
drvV965.cc
drvV965.cc
Required for all EPICS Device Drivers
aidset,longindset,longoutdset devV965.cc devV965.cc Required for all EPICS Device Support.  These classes implement InitRecord(),GetIOIntInfo(), and read()/write() methods as static members.
CaenD16, CaenD32
drvV965p.h
drvV965p.h
Wrapper classes for device registers.  Overloaded operator int()  and operator=() enforce the use of sysInXXX() and sysOutXXX() calls to do actual board IO.
drvCaenV965Registers
drvV965p.h
drvV965p.h
Wrapper class for the board.  All methods must be static and the constructor must be private.  Access to the board's registers are by name ant through this class.  The boards physical address in memory space is cast as this type.
drvCaenV965Device
drvV965.h
drvV965.cc
Driver support data for the driver.  Keeps stored state, the board address, and data recorded during the ISR.   Methods required to support the device support layer are implemented here.  A static member array of up to 20 pointers to drvCaenV965Device objects is used to store information about all configured boards.


Our SNS application required that we take three samples in rapid succession.  We dont need the data on all three samples for all channels, sample 1 has part of the data and sample 2 has part of the data. We used sample 0 to set thesholds.