Most real experiments will need to monitor the rates in various detector systems, as well as maintain other counter based items such as the master trigger rate, and the accepted trigger rate, the beam current etc. These are conveniently managed through the periodic scaler readout system. The production readout framework allows you to specify a set of scalers that are read periodically. It is also possible to replace this periodic trigger with an external trigger. The reference section describes how to do this.
In this section we will:
Add an SIS 3820 scaler to our set up and modify the setup so that we get counts in one of the channels of the scaler.
Modify the packetized readout software to read an SIS 3820 scaler when the scaler trigger fires.
Test this modification by using bufdump to look at scaler buffers
Setup a description file for the NSCL Scaler program to display scaler buffers and test that as well.
The SIS 3820 is a 32 channel VME scaler. It is addressed via a settable base address. The address is set via rotary switches at the top part of the circuit board. See the SIS 3820 manual for more information about this module.
The SIS module is an address space hungry module. It requires 0x1000000 bytes of A32 address space. We have configured it for a base address of 0x38000000 which means that it spans the address range 0x38000000-0x38ffffff. This keeps it clear of both the V775 and V262. To test, we will just cable the TDC stops into the first set of channels for the module. We will not be looking at events.
Exercise for the reader: By selectively terminating the inputs of either the V775 or SIS 3820, you can bus the ribbon cable between the individual inputs of the TDC and the scaler. Do this by ensuring that only the last module on the physical bus has termination enabled.
The production readout software allows you to devine any number of scaler modules.
A scaler module is a set of scaler channels that are read via a class that inherits
from the abstract base class CScaler. The key features of the
header for this class are shown below:
Example 2-17. Key features of the CScaler ABC
class CScaler
{
public:
CScaler (); //!< Default constructor.
virtual void Initialize () = 0;
virtual void Read (STD(vector)<unsigned long>& Scalers) = 0;
virtual void Clear () = 0;
virtual unsigned int size () = 0;
};
#endif
CEventSegment class.
The main difference is that the CScaler class appends data
to a standard template library vector container class, rather than
to a buffer of unchecked memory.
We must write a class that will manage an SIS 3820 scaler module within the
framework of the CScaler interface, and we must register
an object of this class for our scaler with the framework so that its interfaces
will be called at the appropriate time.
To write this class we will make use of the CSIS3820 class.
CSIS3820 provides software support for the scaler module.
The parts of the class we will use are shown below:
Example 2-18. Extract from the CSIS3820 header
/*!
Controls an SIS3820 module. The SIS3820 is a 32 channel latching
VME scaler module.
*/
class CSIS3820 : public CModule32
{
public:
enum OperatingMode { //
LatchingScaler = 0x00000000,
ReservedScaler1 = 0x10000000,
MultiChannelScaler = 0x20000000,
HistogrammingScaler= 0x30000000,
ReservedScaler2 = 0x40000000,
ReservedScaler3 = 0x50000000,
ReservedScaler4 = 0x60000000,
RamTestScaler = 0x70000000
};
enum LNESource { //
LatchVMEOnly = 0x00000000,
LatchFP = 0x00000010,
Latch10Mhz = 0x00000020,
LatchChannelN = 0x00000030,
LatchPresetN = 0x00000040,
LatchReserved5 = 0x00000050,
LatchReserved6 = 0x00000060,
LatchReserved7 = 0x00000070
};
public:
CSIS3820(unsigned long base, //
int crate = 0) ;
void Reset() const; //
void setOperatingMode(OperatingMode mode); //
void setLatchSource(LNESource mode); //
void Arm() const; //
void Enable() const; //
void ClearChannels() const; //
void EnableClearOnLatch() const; //
void LatchAndRead(unsigned long* buffer) const; // (11)
};

CSIS3820::LatchingScaler in a call to
setOperatingMode.
When writing code it is best to use symbolic constants where practical,
rather than using magic numbers whose meaning you will
have to grope for when looking at the code later on.

CSIS3820::LatchVMEOnly.

base parameter (the base
address), and a VME crate number (crate).

Reset member function resets the module
to its power up condition.

mode parameter
set at CSIS3820::LatchingScaler to set the operating mode
to be that of a latching scaler.





EnableClearOnLatch
tells the module hardware to clear the front end counters when they are
transferred to the latched registers.
buffer must
point to at least 32 longwords worth of storage.
CMyScaler class header.
We will write a class named CMyScaler. This class will
use the CSIS3820 class to communicate with the scaler.
The header for this class is:
Example 2-19. Header for the CMyScaler class.
#ifndef __CSCALER_H
#include <CScaler.h>
#endif
class CSIS3820;
class CMyScaler : public CScaler
{
private:
CSIS3820* m_pModule;
public:
CMyScaler(unsigned long base);
~CMyScaler();
virtual void Initialize () ;
virtual void Read (STD(vector)<unsigned long>& Scalers) ;
virtual void Clear () ;
virtual unsigned int size () ;
};
CMyScaler class implementation.
The code to construct and destroy a CMyScaler object
is shown below:
Example 2-20. Constructors and destructors for a CMyScaler object
#include <config.h>
#include "CMyScaler.h"
#include <CSIS3820.h>
#ifdef HAVE_STD_NAMESPACE
using namespace std;
#endif
CMyScaler::CMyScaler(unsigned long base) :
m_pModule(new CSIS3820(base))
{
}
CMyScaler::˜CMyScaler()
{
delete m_pModule;
}
Since our assumption is that the VME crate could have been turned off and on prior
to each run the initialization of the scaler will be done in
CMyScaler::Initialize:
Example 2-21. CMyScaler::Initialize implementation
void
CMyScaler::Initialize()
{
m_pModule->Reset(); //
m_pModule-*gt'setOperatingMode(CSIS3820::LatchingScaler);
m_pModule->setLatchSource(CSIS3820::LatchVMEOnly); //
m_pModule->EnableClearOnLatch();
Clear(); //
m_pModule->Arm(); //
m_pModule->Enable();
}



Clear member function. While we could
have just done a:
m_pModule->ClearChannels();
here, wherever possible avoid duplicating code sequences. Factor
duplicated code sequences out into functions or member functions.
This results in much more maintainable code in the long run.

The implementation of the Clear member is:
void
CMyScaler::Clear()
{
m_pModule->ClearChannels();
}
This simply asks the modules to clear its front end counters.
To read the module we need to transfer data from the module using
CSIS3820::LatchAndRead, however that transfers data
to a plain memory buffer and we have to put our scalers into a vector.
We therefore read the data into an internal buffer and transfer it to the
vector as shown below:
Example 2-22. CMyScaler::Read implementation
void
CMyScaler::Read(vector<unsigned long>& Scalers)
{
unsigned long data[32];
m_pModule->LatchAndRead(data);
for (int i =0; i < 32; i++) {
Scalers.push_back(data[i]);
}
}
Finally, the size member is also obsolete for the
CScaler class just as it is for the
CEventSegment class:
CMyScaler object with the frameworkNow we need to register an object to readout the scaler we have installed. We will also need to build the new Readout program.
Edit Skeleton.cpp. Locate the header includes and add an include directive for our class header e.g.:
#include <CEventSegment.h>
#include "CMyEventSegment.h"
#include "CMyScaler.h" // <---- add this line.
Locate the implementation of SetupScalers. This function is
called by the framework when it is able to accept registrations of scaler
modules. Modify it as shown below:
void
CMyExperiment::SetupScalers(CExperiment& rExperiment)
{
CReadoutMain::SetupScalers(rExperiment);
// Insert your code below this comment.
rExperiment.AddScalerModule(new CMyScaler(0x38000000)); // <---- Add this line.
// For test,setup an LRS 1151 at 0x200c00
// CScaler* pScaler = new CVMEScalerLRS1151(0xc00200);
// rExperiment.AddScalerModule(pScaler);
}
Now edit the Makefile. Locate the definition of
OBJECTS and add CMyScaler.o to the
list of objects the program needs:
Objects=Skeleton.o CMyEventSegment.o CMyScaler.o
Use the make command to build your new event sourcde.
Bufdump can dump formatted scaler buffers as well. This will give us a chance to see if our software works.
Start bufdump. Connect it to the online system. Establish a filter that accepts only scaler buffers. Tell it to get the next buffer from the source.
Start the readout program and begin a run (don't forget to move the ribbon cable from the inputs of the TDC to the inputs of the scaler). The default time interval for a scaler readout is 10 seconds. After 10 seconds you should get output that looks something like:
Scaler Buffer for interval 0-00:00:00 through 0-00:00:10
32 scalers follow:
Scaler Increment Rate over interval
0 102910 10291.000000
1 0 0.000000
2 0 0.000000
3 0 0.000000
4 0 0.000000
5 0 0.000000
6 0 0.000000
7 0 0.000000
8 0 0.000000
9 0 0.000000
10 0 0.000000
11 0 0.000000
12 0 0.000000
13 0 0.000000
14 0 0.000000
15 0 0.000000
16 0 0.000000
17 0 0.000000
End the run and type the following command to the Readout program: set frequency 5. This sets the readout period to 5 seconds. Tell bufdump to request another buffer and start the run. You should now get something like:
Scaler Buffer for interval 0-00:00:00 through 0-00:00:05
32 scalers follow:
Scaler Increment Rate over interval
0 51004 10200.800000
1 0 0.000000
2 0 0.000000
3 0 0.000000
4 0 0.000000
5 0 0.000000
6 0 0.000000
7 0 0.000000
8 0 0.000000
9 0 0.000000
10 0 0.000000
11 0 0.000000
12 0 0.000000
13 0 0.000000
14 0 0.000000
15 0 0.000000
16 0 0.000000
17 0 0.000000
18 0 0.000000
19 0 0.000000
20 0 0.000000
As expected the increment column is halved, but the rate column is constant.