This chapter describes a framework for reading out events via the SBS PCI/VME bus bridge interface. This chapter describes
Basic concepts that underlie the framework
How to obtain a skeleton application which you can expand into a real application, and build it.
What parts of the skeleton application you will most likely have to modify to produce a real application.
Complete reference information is available in the 3sbsreadout part of this manual.
The SBS readout is an application framework. Application frameworks are nice because they already supply the main flow of control. Your job as an application programmer is to fill in the experiment specific pieces of the framework.
The disadvantage of an application framework is that it can be hard to figure out how to get started without a good orientation. This section aims to be that orientation. We will describe the flow of the application and the concepts you'll have to deal with.
Normally you will only need to be concerned with how the framework operates when data taking is active. When data taking is active, An independent thread loops checking a pair of triggers. These triggers are called the event trigger and tthe scaler triger. Each trigger has associated with it a set of code to execute. This code is organized hierarchically as event segments in the case of the event trigger and scaler banks in the case of the scaler trigger.
Triggers and the code that responds to them must be registered with the framework if it is to know about it. The specific triggers themselves must also be registered.
This section therefore will discuss the following objects:
Event segments.
Scaler banks
Triggers
Busys
Event Segments.
An event segment is a logical unit of data acquisitition. There
are two useful base classes:
CEventSegment
provides a primitive segment.
You extend CEventSegment
to build a class
that actually initializes, reads and clears some digitizer modules.
CCompoundEventSegment
provides a container
for other event segments (including other
CCompoundEventSegment
objects).
CCompoundEventSegment
provides the
glue that allows you to build an experiment readout from logical
chunks.
To use the CEventSegment
class, you create
a derived class and implement the pure virtual methods of
CEventSegment
. You can optionally override
the virtual methods supplied by CEvenSegment
(which are implemented to do nothing) if your electronics requires this.
The virtual methods you can implement are:
initialize
()This method is called once as data taking transitions to the active state (resume or begin). It is expected to perform any one-time initialization of the hardware managed by this event segment. This includes returning the module to a known state, reading setup files and applying them to the module, enabling data taking and so on.
clear
()
Clears any pending data from the module. This is called
after initialize
during startup.
It is also called after each event has been read.
You should implement this if the hardware this segment is reading
requires any post readout attention to be made ready for
the next event.
disable
()Called as data taking is being transitioned to an inactive state (paused or ended). This is expected to do any work needed to disable dat taking in the modules managed by this segment.
read
(
void* pBuffer
,
size_t maxwords
)
Called in response to a trigger. This function is expected
to read the hardware directly into pBuffer
which has maxwords
of 16 bit words
available. On return, the actual number of 16 bit words read
should be returned.
For reference information on this class see:
CEventSegment(3sbsreadout).
Closely allied with this is the concept of packets. Packets are supported
via the CDocumentedPacket(3sbsreadout).
The CEventPacket(3sbsreadout)
class extends CEventSegment
to provide a base
class for event segments that are wrapped in a packet.
Event segments are organized by placing them in CCompoundEventSegment
objects. CCompoundEventSegment
is itself an
CEventSegment
and therefore can contain other
compounds, which supports a hierarchical organization of the
experimental readout.
Ordinarily you will use a CCompoundEventSegment
by creating an instance of it and inserting other segments into it.
Here are the methods that allow you to manipulate the event segments
in a compound event segment.
AddEventSegment
(
CEventSegment* pSegment
)
Adds an event segment to the end of the ordered collection
of event segments in the list. Whenever a method like
initialize
orread
is invoked on a compound event segment it will invoke the
corresponding method in the elements it contains in
the order in which they were added.
DeleteEventSegment
(
CEventSegment* pSegment
)
If pSegment
is contained by
the compound, it will be removed from the container.
If not this method does nothing.
begin
()Returns an iterator which 'points' to the beginning of the collection. Refer to the description below for information about iterators.
end
()Returns an iterator that points just off the end of the collection. A typical usage pattern is shown below
The CCompoundEventSegment::EventSegmentIterator data typeis a pointer like object within the collection of event segments. Dereferencing it gives you a pointer to the event segmet at the current location. Increment advances the iterator to the next element of the collection.
For reference information about the CCompoundEventSegment
class see
CCompoundEventSegment(3sbsreadout).
The readout software has a single object from the
CExperiment(3sbsreadout)
class. This object contains a top level CCompoundEventSegment
.
It also provides a member function AddEventSegment
that
allows you to add an event segment (or compound event segment) to
that top level segment.
See the section: Modifying the skeleton application to meet your needs for information about where to add event segments.
Scaler banks. The Readout program supports a second trigger that reads out scaler banks. Scaler banks usually read out a set of counters that describe the rates in various detectors subsystems and other items of interest. Scaler banks operate in a manner analagous to the event segments we have just described.
The CScaler
class is intended to read a single
scaler module. CScalerBank
is a container for
other CScaler
objects including other
CScalerBank
objects. This pair of classes
allows you to build a modular hierarchy of scalers to read in
response to the scaler trigger. The scaler trigger is assumed
to come at a much lower rate than the event trigger and therefore can
tolerate alonger deadtime.
CScaler
is an abstract base class. You use
it by extending it by supplying code for the pure virtual methods,
and overriding the other virtual methods you need to override.
The virtual methods that are fair game to be overidden are:
initialize
()Invoked once as the readout program begins taking data. This happens after a begin and after a resume. The code you supply here is supposed to prepare modules for data taking. The base class implementation does nothing
clear
()Invoked once as data taking becomes active (begin or resume), and after the scaler is read. If something must be done to clear a scaler after it has been read write this method and put that code here. Note that many scalers have a destructive read method and that should be used by preference as it ensures that scaler counts will not be lost (those accepted between read and clear).
disable
()Called as data taking is halted (due to an end or pause). If a module requires special handling to disable it implement this method.
read
Reads the scaler(s) managed by this class. The scalers are returned as an STL vector of 32 bit unsigned values.
The CScalerBank
class is a parallel to the
CCompoundEventSegment
. It is a
CScaler
that contains other
CScaler
objects, including
CCompoundEventSegment
objects.
The following methods allow you to manipulate the container
in a CScalerBank
object:
AddScalerModule
(
CScaler* pScaler
)
Adds a scaler module to the end of the ordered container
of scaler modules that is managed by this object. The
virtual functions that make this module look like a
CScaler
iterate through the
set of scaler objects in the container in the order in
which they were added and invoke the corresponding
function in those objects.
DeleteScaler
(
CScaler* pScaler
)
If the scaler pointed to by pScaler
is in the container (shallow inclusion), it is removed
from the container. Note that the object is not destroyed.
IF pScaler
is not in the collection
this function does nothing.
begin
()Returns an iterator that 'points' to the first item in the container. Dereferencing a CScalerBank::ScalerIterator will result in a CScaler*. Incrementing the iterator will make it 'point' to the next object in the container.
end
()Returns an iterator that points just off the end of the collection. A typical use for this is:
For reference information see CScalerBank
As with event segments, the CExperiment
encapsulate as ScalerBank
that is the
top level of the scaler readout hierarchy.
CExperiment
exports methods that
allow you to add and remove scaler modules (including scaler banks)
to this top level scaler bank. See
Modifying the skeleton application to meet your needs
for iformation about how to use these.
Triggers.
We have seen how to build the list of stuff the readout program
will read. Triggers determine when the
top level event segment and scaler bank are read. In order to
make Readout to do anything with these you must supply appropriate
trigger objects and register them with the CExperiment
object. This registration is described in
"Modifying the skeleton application to meet your needs"
below.
All triggers are subclasses of CEventTrigger
.
Several of the commonly used triggers have been defined for you. You
can also build custom triggers by extending CEventTrigger
or any of the prebuilt classes that are close to what you want.
You write a trigger class by overriding the virtual methods in
CEventTrigger
supplying code that is
appropriate to your needs. You must define and implement
operator()
which is a pure virtual
method of CEventTrigger
.
The virtual member functions in the CEventTrigger
class are:
setup
()Called when data taking becomes active (begin or resume). This should perform any initialization of the trigger hardware or software.
teardown
()Called as data taking halts (end or pause). Any code required to make the trigger hardware or software insenstive to additional triggers should be supplied here.
operator()
()This is periodically called and should return true if the trigger actions should be peformed.
The following trigger classes are in the Readout library and can be used simplly by instantiatig and registering them.
CCAENV262Trigger
Triggers using the CAEN V262 module.
CNullTrigger
Trigger that never fires.
CTimedTrigger
Trigger that fires periodically
CV977Trigger
Trigger that uses the CAEN V977 module.
Busys. During the time in which Readout is responding to a trigger it is unable to accept a new trigger. During this time it is often important to veto external electronics until the system is able to accept the next trigger. This is the function of Busy objects.
Busy objects are members of classes that are derived from
CBusy
which has the following pure virtual
members:
GoBusy
This is called when due to software reasons the computer will be unable to accept a trigger. For example, as the run ends. It is important to note that the actual event by event busy should be generated by hardware and then only cleared by software.
GoClear
Called when the software is able to accept the next trigger.
The readout framework provides
CCAENV262Busy
,
and
CV977Busy
as
prebuilt busy classes. This, and any busy class you create must be
registered to be used. The example below shows the creation and
registration of a CV977Busy
object to
manage the busy. The physicsal module is in VME crate 0 and has a base
address of 0x00444400.