This file: http://www.jlab.org/~rom/scaler_roc10.html
Last updated July 2006
R. Michaels rom@jlab.org
The following explains the structure of data for ROC10 and ROC11
scaler data. ROC10 is on the Right spectrometer and ROC11 is on
the Left. For a general overview see
www.jlab.org/~rom/g0helicity.html.
NEW INFO for analysis folks: (ca. July 2006) Here is how to
implement the helicity in Podd. Using that you probably don't
need the following info, since the work is done for you !!
For most events you will see the following data (in hex format):
0x00000007 0x00000040 0x0004ca58 0x00000023 0xfb0b0000
The first word is the event type, here it was trigger 7.
Second word is the bit pattern consisting of helicity, QRT, and gate.
Helicity = 5th bit
QRT = 6th bit
Gate = 7th bit
Examples:
0x50 ==> gate = 1, QRT = 0, helicity = 1
0x60 ==> gate = 1, QRT = 1, helicity = 0
Third word is 100 kHz clock.
Starting April 2003, 4th word (here 0x23) is an event counter which
should be in synch with the other crates.
Next word (e.g. 0xfb0b0000) is a header indicating how much scaler
data follows. This is encoded in the lowest 3 bits and is zero here.
Every synch event (100 events, typically) or every 200 events (whether
synch or not), you will see a much longer event in ROC10/11.
0x00000007 0x00000070 0x0007da75 0x00000442 0xfb0b0002 0xceb70000
0x00000002 0x00000000 0x00000024 0x00000002 0x00000000 0x00000000
0x00000035 0x00000000 0x0000002e 0x00000031 0x00000068 0x00000000
0x00000039 0x00000063 0x00000000 0x0000003a 0x00000000 0x00000000
0x00000242 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0xceb90000 0x00000003 0x00000001 0x00000022
0x00000004 0x00000000 0x00000000 0x00000039 0x00000000 0x00000032
0x00000033 0x0000006e 0x00000000 0x0000003d 0x00000065 0x00000000
0x0000003f 0x00000000 0x00000000 0x00000269 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000093
0x00000000 0xfb1b0005 0x00000000 0x00000011 0x00000000 0x00000003
0x00000000 0x00000000 0x00000000 0x00000002 0x00000004 0x00000003
0x00000000 0x00000000 0x00000000 0x00000003 0x00000003 0x00000000
0x00000001 0x00000000 0x00000003 0x00000004 0x00000000 0x00000011
0x00000000 0x00000003 0x00000003
After April 2003 you will see additional data at the end of this,
starting at 0xfed00015 which is described below (see "TS2 scalers").
0xfed00015 0x000000f4 0x00000000 0x00000000 0x00000000 0x00000000
0x00000000 0x00000000 0x00000000 0x00000001 0x00000000 0x00000000
0x00000000 0x000000f5 0x00000064 0x00000001 0x00000000 0x00000064
0x00000000 0x00000064 0x0000116f 0x00001f10
The first five words are the same as described for the short events.
Note, the header 0xfb0b0002 means that there are now 2 scalers.
They are not physical scalers, but are banks of 32 words consisting
firstly of the negative helicity data followed by the positive helicity
data on 32 channels of a normalization scaler (only one scaler), where
negative & positive helicity correspond to a 0 or 1 bit in helicity.
After 0xfb0b0002 you will see 0xceb70000 in this example. This is a
header used by the event decoder. You may ignore this. (The header
is different between ROC10 and ROC11). Following this
header are 32 words of data for negative helicity, and then another
header 0xceb90000 denoting the start of the next scaler, then 32 more
words for positive helicity.
At the end of the 2 helicity scalers and just prior to the word
0xfb1b0005 in the above example, you have two words related to
the count of readings from the FIFO. The first word (here 0x93)
is the FIFO reading number where the latest valid reading was added
to the cumulative count. The 2nd is the FIFO reading where the latest
problematic reading occured. (A "problematic" reading is one for
which the helicity made no sense.) If this is nonzero, then one
would need to match the FIFO reading number of the last valid
reading to that of the last problematic reading to decide where
to cut out bad data.
The follwing point should be EMPHASIZED: If the number of bad readings
is always zero, one may IGNORE it and IGNORE the subsequent ring buffer
data (see below). In that case, simply use the helicity gated
scaler data. The ring buffer is *ONLY* necessary as a recovery in case
something goes wrong with the helicity gating. Actually the simplest
recovery would be to identify the bad intervals (see explanation above).
Also, for in-time helicity mode, none of this is necessary.
Starting with the word 0xfb1b0005 in the above dump, one finds "Ring
Buffer Data". The header is 0xfb1b0000 + NRING, where NRING is the
number of data from the ring buffer (here 5). What's this ring buffer ?
The scalers are read at 30 Hz with zero deadtime. A portion of the
channels are stored in a ring buffer, which is a section of memory which
can be overwritten (a circular ring). The ring buffer has a length
to store about 1 minute of data. The ROC10/11 readout flushes the
ring buffer into the datastream starting at header 0xfb1b0000 + NRING.
As long as NRING is small, you can be sure you flushed out all of it
and missed no data. For each of the buffers in the ring buffer, you
get the following 5 words:
word # meaning of data
1st clock (1024 Hz)
2nd qrt & helicity. (qrt in 5th bit, helicity in 1st)
3rd main trigger
4th current monitor (one BCM is chosen, upstream x3 gain)
5th L1A (accepted triggers)
NOTE: After Jan 10, 2003 at 01:20 there is a 6th word stuffed
into the data. This is because the input bits for helicity are
found to be one 30 Hz cycle delayed w.r.t. the data.
6th Helicity (using a V-to-F to convert level)
TS2 SCALERS
Now I come to the new "TS2 scaler" data from April 2003 starting with
header 0xfed00015. Firstly, the 0x15 in lower bits encodes how many data
follows. These data are the 21 scaler data from the new trigger
supervisor installed in March 2003 shutdown. Here is the format:
scaler 1 = trigger 1 input, i.e after prescaling.
2 = trigger 2
3 = trigger 3
same 4,5,6... 12
13 = "OR" of triggers
14 = Level 1 accept (can use this as alternative to external scaler L1A)
15 = scheduled sync's
16 = programmed events (normally zero unless I program special events)
17 = latched triggers
18 = program 2 events
After these 18 scalers are 3 more data that come from TS2 registers:
19th = Event count
20th = Live 1 count (see below)
21st = Live 2 count
---------------
Live 1 count = free running 200 kHz clock gated by DAQ live signal (.NOT. busy)
Live 2 count = same clock, no gate.
Live Time = (Live 1 count) / (Live 2 count) <= 1.0
However, this live1/live2 ratio is correct only if psfactor = 1.
If psfactor!=1 it is wrong because it assumes the trigger is still random.
The TS2 scalers are latched at start of ring buffer readout
to avoid time slewing. The latch is freed after a read, but
the latching doesn't affect the actual counting.
***************************************************************
Below is an example C++ code to interpret the ROC10/11 data:
It uses the scaler class documented in
hallaweb.jlab.org/equipment/daq/THaScaler.html.
//---------------------------------------------------------------
// tscalroc10_main.C
//
// Test of the ROC10 scalers which are read in the datastream
// typ. every 100 events. This code was written in Aug 2002
// and things might have changes slightly (sorry, no time to
// rewrite it now).
//
// R. Michaels
//---------------------------------------------------------------
#define MYROC 10
#include < iostream >
#include "THaCodaFile.h"
#include "THaEvData.h"
int main(int argc, char* argv[]) {
int helicity, qrt, gate, timestamp;
int len, data, status, nscaler, found, header;
int numread, badread;
int ring_clock, ring_qrt, ring_helicity, ring_hel2;
int ring_trig, ring_bcm, ring_l1a;
if (argc < 2) {
cout << "You made a mistake... bye bye !\n" << endl;
cout << "Usage: 'tscalroc10 filename'" << endl;
cout << " where 'filename' is the CODA file." << endl;
exit(0);
}
THaCodaFile *coda = new THaCodaFile(TString(argv[1]));
THaEvData evdata;
status = 0;
while (status == 0) {
status = coda->codaRead();
if (status != 0) break;
evdata.LoadEvent(coda->getEvBuffer());
len = evdata.GetRocLength(MYROC);
if (len <= 4) continue;
data = evdata.GetRawData(MYROC,3);
helicity = (data & 0x10) >> 4;
qrt = (data & 0x20) >> 5;
gate = (data & 0x40) >> 6;
timestamp = evdata.GetRawData(MYROC,4);
found = 0;
index = 5;
while ( !found ) {
data = evdata.GetRawData(MYROC,index++);
if ( (data & 0xffff0000) == 0xfb0b0000) found = 1;
if (index >= len) break;
}
if (!found) break;
nscaler = data & 0x7;
if (nscaler <= 0) continue;
int index = 6;
if (nscaler > 2) nscaler = 2; // shouldn't be necessary
// 32 channels of scaler data for two helicities.
cout << "Synch event ----> " << endl;
for (int ihel = 0; ihel < nscaler; ihel++) {
header = evdata.GetRawData(MYROC,index++);
cout << "Scaler for helicity = " << dec << ihel;
cout << " unique header = " << hex << header << endl;
for (int ichan = 0; ichan < 32; ichan++) {
data = evdata.GetRawData(MYROC,index++);
cout << "channel # " << dec << ichan+1;
cout << " (hex) data = " << hex << data << endl;
}
}
numread = evdata.GetRawData(MYROC,index++);
badread = evdata.GetRawData(MYROC,index++);
cout << "FIFO num of last good read " << dec << numread << endl;
if (badread != 0) {
cout << "DISASTER: There are bad readings " << endl;
cout << "FIFO num of last bad read " << badread << endl;
}
// Subset of scaler channels stored in a 30 Hz ring buffer.
int nring = 0;
while (index < len && nring == 0) {
header = evdata.GetRawData(MYROC,index++);
if ((header & 0xffff0000) == 0xfb1b0000) {
nring = header & 0x3ff;
}
}
cout << "Num in ring buffer = " << dec << nring << endl;
for (int iring = 0; iring < nring; iring++) {
ring_clock = evdata.GetRawData(MYROC,index++);
data = evdata.GetRawData(MYROC,index++);
ring_qrt = (data & 0x10) >> 4;
ring_helicity = (data & 0x1);
ring_trig = evdata.GetRawData(MYROC,index++);
ring_bcm = evdata.GetRawData(MYROC,index++);
ring_l1a = evdata.GetRawData(MYROC,index++);
// After Jan 10, 01:20 there was a 6th word, see document above
ring_hel2 = evdata.GetRawData(MYROC,index++);
cout << "buff [" << dec << iring << "] ";
cout << " clock " << ring_clock << " qrt " << ring_qrt;
cout << " helicity " << ring_helicity << " " << ring_hel2;
cout << " trigger " << ring_trig << " bcm " << ring_bcm;
cout << " L1a " << ring_l1a << endl;
}
}
return 0;
}
// End of C++ code to read ROC10.
Some FAQs:
==========
1. Do we have 2 helicity scalers ? In some earlier era we did,
but now there is one helicity scaler in each HRS. The data are
sorted by helicity and packaged online, for convenience and the
use by various clients like xscaler and event-type-140.
See also dstruct.html for info about the data structure
including scalers.
3. What if there are problems, e.g. the helicity makes no sense or
the two FIFO scalers disagree ? Answers: For most errors (like
cables falling out or glitches in the helicity sequence), there
should be clear messages printed on the VME computer for scalers.
It will also appear as a nonzero number of FIFO readings for
"problematic" data in the datastream, as explained above.
Finally, the end-of-run summary maintains a scaler_history_bad.dat
file in addition to a scaler_history.dat file for each run. If
there are non-zero data in the *bad.dat, there was a problem.
4. The ring buffer only contains a subset of the 32 channels. Why not
put all channels into ROC10/11 ? Answer: You can have it, but
the cost is a slower DAQ.
5. What about the ADCs that measure helicity ? Answer: This was
a prior mode of putting helicity data into datastream. If I
get around to it, I will add this to the fastbus data as a
redundant check.