Privacy and Security Notice

Scaler and Helicity Data

Scaler and Helicity Data in ROC10/11

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.