CMS 3D CMS Logo

CastorCORData.cc
Go to the documentation of this file.
1 //#include "Utilities/Configuration/interface/Architecture.h"
2 /*
3  * \author A. Campbell - DESY
4  */
5 #ifndef HTBDAQ_DATA_STANDALONE
7 #else
8 #include "CastorCORData.h"
9 #endif
10 #include <cstring>
11 #include <iostream>
12 #include <algorithm>
13 #include <iomanip>
14 
15 using namespace std;
16 
19 
20 CastorCORData::CastorCORData() : m_formatVersion(-2), m_rawLength(0), m_rawConst(nullptr), m_ownData(nullptr) { }
21 CastorCORData::CastorCORData(const unsigned short* data, int length) {
22  adoptData(data,length);
23  m_ownData=nullptr;
24 }
26 
27 CastorCORData::CastorCORData(int version_to_create) : m_formatVersion(version_to_create) {
28  allocate(version_to_create);
29 }
30 
31 void CastorCORData::allocate(int version_to_create) {
32  m_formatVersion=version_to_create;
33  // the needed space is for the biggest possible event...
34  const int needed=0x200;
35  // create a buffer big enough...
36  m_ownData=new unsigned short[needed];
37  m_rawLength=0;
39 }
40 
42  if (m_ownData==nullptr) {
46  }
47  return (*this);
48 }
49 
50 void CastorCORData::adoptData(const unsigned short* data, int length) {
51  m_rawLength=length;
53  if (m_rawLength<5) {
54  m_formatVersion=-2; // invalid!
55  } else {
56  m_formatVersion=(m_rawConst[4]>>12)&0xF;
57  }
58 }
59 
60 // check :: not EE, length is reasonable, length matches wordcount
61 // length required for tp+daq is correct
62 
63 bool CastorCORData::check() const {
64  // length checks
65  // minimum length
66  if (m_rawLength<6+12) return false;
67  // matches wordcount
68  if (m_rawLength!=m_rawConst[m_rawLength-3]) return false;
69 
70  // daq/tp length check
71  int tp, daq, header, trailer, trigger;
72  determineSectionLengths(tp,daq,header,trailer,trigger);
73  if (trigger+daq+header+trailer>m_rawLength) return false;
74 
75  return true;
76 }
77 
78 void CastorCORData::determineSectionLengths(int& tpWords, int& daqWords, int& headerWords, int& trailerWords, int& triggerLen) const {
79 
80  tpWords=m_rawConst[5]>>8; // should be 8 but could be up to 12
81  if (m_rawLength>4)
82  daqWords=m_rawConst[m_rawLength-4]&0x7FF; // no zero suppression supported
83  // there are 24 16bit words per time sample
84  // these contain the data from 36 channels
85  // daqWords is number of 16 bit words of qie data
86  // hence #qie data values id daqWords*3/2
87  headerWords=8;
88  triggerLen=12; // total space reserved for trigger information
89  trailerWords=12; // minimum, may be more...
90 }
91 
92 void CastorCORData::determineStaticLengths(int& headerWords, int& trailerWords, int& triggerLen) const {
93  headerWords=8;
94  triggerLen=12; // total space reserved for trigger information
95  trailerWords=12; // minimum, may be more...
96 
97 }
98 
99 
100 void CastorCORData::unpack(unsigned char* daq_lengths, unsigned short* daq_samples,
101  unsigned char* tp_lengths, unsigned short* tp_samples) const {
102 
103  if (daq_lengths!=nullptr) memset(daq_lengths,0,CHANNELS_PER_SPIGOT);
104  if (tp_lengths!=nullptr) memset(tp_lengths,0,1);
105 
106  int tp_words_total = 0;
107  int daq_words_total = 0;
108  int headerLen = 0;
109  int trailerLen = 0;
110  int triggerLen = 0;
111  determineSectionLengths(tp_words_total,daq_words_total,headerLen,trailerLen,triggerLen);
112 
113  int wordPtr;
114  const unsigned short* tpBase=m_rawConst+headerLen;
115  // process the trigger primitive words
116  if (tp_lengths!=nullptr) {
117  for (wordPtr=0; wordPtr<tp_words_total; wordPtr++) {
118  tp_samples[tp_lengths[0]]=tpBase[wordPtr];
119  tp_lengths[0]++;
120  }
121  }
122 
123  const unsigned short* daqBase=m_rawConst+headerLen+triggerLen;
124  unsigned long dat;
125  // process the DAQ words
126  int lastCapid=0;
127  int ts,dv;
128  int tsamples = daq_words_total/24;
129  if (daq_lengths!=nullptr) {
130  for ( ts = 0; ts < tsamples; ts++ ) {
131  for (int j=0; j<12 ; j++) {
132  dat = daqBase[(ts*12+j)*2]<<16 | daqBase[(ts*12+j)*2+1];
133  dv = ( dat & 0x80000000 ) >> 31;
134  daq_samples[(j*3) *MAXIMUM_SAMPLES_PER_CHANNEL+ts]= (( dat & 0x40000000 ) >> 20 ) | (( dat & 0x3fe00000 ) >> 21 ) | ( dv << 9 );
135  daq_samples[(j*3+1)*MAXIMUM_SAMPLES_PER_CHANNEL+ts]= (( dat & 0x00100000 ) >> 10 ) | (( dat & 0x000ff800 ) >> 11 ) | ( dv << 9 );
136  daq_samples[(j*3+2)*MAXIMUM_SAMPLES_PER_CHANNEL+ts]= (( dat & 0x00000400 ) ) | (( dat & 0x000003fe ) >> 1 ) | ( dv << 9 );
137  }
138  }
139  // now loop over channels - set daq_lengths with error bits
140  int ichan;
141  for ( ichan = 0; ichan<CHANNELS_PER_SPIGOT; ichan++) {
142  daq_lengths[ichan]=tsamples;
143  for ( ts = 0; ts < tsamples; ts++ ) {
144  int erdv =(daq_samples[ichan*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x600 ) >> 9;
145  int capid=(daq_samples[ichan*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x180 ) >> 7;
146  if ( erdv!=1 || ( ts!=0 && (capid!=((lastCapid+1)%4)))) {
147  daq_lengths[ichan]|=0x80;
148  }
149  lastCapid=capid;
150  }
151  }
152  }
153 }
154 
155 void CastorCORData::pack(unsigned char* daq_lengths, unsigned short* daq_samples,
156  unsigned char* tp_lengths, unsigned short* tp_samples, bool do_capid) {
157 
158  int tp_words_total=0, daq_words_total=0, headerLen, trailerLen, triggerLen;
159  determineStaticLengths(headerLen,trailerLen,triggerLen);
160 
161  tp_words_total=0;
162  daq_words_total=0;
163  int isample;
164 
165  // trigger words
166  unsigned short* ptr=m_ownData+headerLen;
167  if (tp_samples!=nullptr && tp_lengths!=nullptr) {
168  for (isample=0; isample<tp_lengths[0] && isample<12; isample++) {
169  ptr[tp_words_total]=tp_samples[isample];
170  tp_words_total++;
171  }
172  }
173 
174  // daq words
175  ptr=m_ownData+headerLen+triggerLen;
176  int timesamples = std::min (daq_lengths[0]&0x3f,MAXIMUM_SAMPLES_PER_CHANNEL) ;
177  int ts, capid, j;
178  unsigned long dat;
179  unsigned short s1,s2,s3;
180  bool somevalid;
181 
182  for (ts=0; ts<timesamples; ts++){
183  capid = ts%4;
184  for (j=0; j<12 ; j++) {
185  somevalid = false;
186  if ( daq_lengths[j*3] == 0 || ( daq_lengths[j*3] & 0xc0 ) ) {
187  s1 = 0x400; // ER !DV
188  } else {
189  s1 = daq_samples[(j*3 )*MAXIMUM_SAMPLES_PER_CHANNEL+ts];
190  somevalid = true;
191  }
192  if ( daq_lengths[j*3+1] == 0 || ( daq_lengths[j*3+1] & 0xc0 ) ) {
193  s2 = 0x400; // ER !DV
194  } else {
195  s2 = daq_samples[(j*3+1)*MAXIMUM_SAMPLES_PER_CHANNEL+ts];
196  somevalid = true;
197  }
198  if ( daq_lengths[j*3+2] == 0 || ( daq_lengths[j*3+2] & 0xc0 ) ) {
199  s3 = 0x400; // ER !DV
200  } else {
201  s3 = daq_samples[(j*3+2)*MAXIMUM_SAMPLES_PER_CHANNEL+ts];
202  somevalid = true;
203  }
204  //dat = 0x80000001 // msb is dv for the fibre
208  //| ( daq_samples[(j*3 )*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x1ff ) << 21
209  //| ( daq_samples[(j*3+1)*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x1ff ) << 11
210  //| ( daq_samples[(j*3+2)*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x1ff ) << 1
211  //| ( daq_samples[(j*3 )*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x400 ) << 20
212  //| ( daq_samples[(j*3+1)*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x400 ) << 10
213  //| ( daq_samples[(j*3+2)*MAXIMUM_SAMPLES_PER_CHANNEL+ts] & 0x400 ) ;
214  dat = 0x00000001 // msb is dv for the fibre
215  // sample data is ER(1)+CAPID(2)+EXP(2)+Mantissa(5)
216  // daq_samples has ER(1)+DV(1)+CAPID(2)+EXP(2)+Mantissa(5)
217  // should check daq_lengths for the 3 channels here ??
218  | ( s1 & 0x1ff ) << 21
219  | ( s2 & 0x1ff ) << 11
220  | ( s3 & 0x1ff ) << 1
221  | ( s1 & 0x400 ) << 20
222  | ( s2 & 0x400 ) << 10
223  | ( s3 & 0x400 ) ;
224  if ( somevalid ) dat |= 0x80000000;
225  // should we set dv from daq_samples ??
226  if (do_capid) dat = ( dat & 0xcff3fcff ) | capid << 28 | capid << 18 | capid << 8;
227  ptr[daq_words_total++] = dat >> 16;
228  ptr[daq_words_total++] = dat & 0xffff;
229 
230  }
231  }
232 
233  m_ownData[5]=(tp_words_total<<8)|0x1;
234  unsigned short totalLen=headerLen+12+daq_words_total+trailerLen;
235 
236  m_rawLength=totalLen;
237  m_ownData[totalLen-2]=totalLen/2; // 32-bit words
238  m_ownData[totalLen-3]=totalLen;
239  m_ownData[totalLen-4]=daq_words_total;
240 
241 }
242 
243 void CastorCORData::packHeaderTrailer(int L1Anumber, int bcn, int submodule, int orbitn, int pipeline, int ndd, int nps, int firmwareRev) {
244  m_ownData[0]=L1Anumber&0xFF;
245  m_ownData[1]=(L1Anumber&0xFFFF00)>>8;
246 
247  m_ownData[2]=0x8000; // Version is valid, no error bits - status bits need definition
248  m_ownData[3]=((orbitn&0x1F)<<11)|(submodule&0x7FF);
249  m_ownData[4]=((m_formatVersion&0xF)<<12)|(bcn&0xFFF);
250  m_ownData[5]|=((nps&0xF)<<4)|0x1;
251  m_ownData[6]=((firmwareRev&0x70000)>>3)|(firmwareRev&0x1FFF);
252  m_ownData[7]=(pipeline&0xFF) | ((ndd&0x1F)<<8);
253  m_ownData[m_rawLength-4]&=0x7FF;
254  m_ownData[m_rawLength-4]|=(ndd&0x1F)<<11;
255 
256  m_ownData[m_rawLength-2]=m_rawLength/2; // 32-bit words
257  m_ownData[m_rawLength-1]=(L1Anumber&0xFF)<<8;
258 }
259 
260 unsigned int CastorCORData::getOrbitNumber() const {
261  return (m_rawConst[3]>>11);
262 }
263 unsigned int CastorCORData::getSubmodule() const {
264  return (m_rawConst[3]&0x7FF);
265 }
266 unsigned int CastorCORData::htrSlot() const{
267  const unsigned int smid = getSubmodule();
268  return ((smid>>1)&0x1F);
269 }
270 unsigned int CastorCORData::htrTopBottom() const{
271  const unsigned int smid = getSubmodule();
272  return (smid&0x01);
273 }
274 unsigned int CastorCORData::readoutVMECrateId() const{
275  const unsigned int smid = getSubmodule();
276  return ((smid>>6)&0x1F);
277 }
279  return (m_formatVersion==-1)?(false):(m_rawConst[2]&0x4000);
280 }
282  return (m_formatVersion<4)?(false):(m_rawConst[6]&0x8000);
283 }
284 bool CastorCORData::wasMarkAndPassZS(int fiber, int fiberchan) const {
285  if (fiber<1 || fiber>8 || fiberchan<0 || fiberchan>2) return false;
286  if (!isUnsuppressed() || m_formatVersion<5) return false;
287  unsigned short val=(fiber<5)?(m_rawConst[m_rawLength-12]):(m_rawConst[m_rawLength-11]);
288  int shift=(((fiber-1)%4)*3)+fiberchan;
289  return ((val>>shift)&0x1)!=0;
290 }
291 
293  return (m_formatVersion==-1)?(false):(m_rawConst[2]&0x1000);
294 }
296  return (m_formatVersion==-1)?(m_rawConst[2]&0x2):(m_rawConst[2]&0x2000);
297 }
299  return (m_formatVersion==-1)?(m_rawConst[m_rawLength-4]>>8):(m_rawConst[m_rawLength-4]>>11);
300 }
302  int retval=-1;
303  if (m_formatVersion==-1) retval=m_rawConst[m_rawLength-4]&0xFF;
304  else if (m_formatVersion<3) retval=m_rawConst[m_rawLength-4]>>11;
305  return retval;
306 }
308  return (m_formatVersion==-1)?(m_rawConst[m_rawLength-4]&0xFF):(m_rawConst[m_rawLength-4]&0x7FF);
309 }
311  return (m_formatVersion==-1)?(0):((m_rawConst[5]>>4)&0xF);
312 }
313 unsigned int CastorCORData::getPipelineLength() const {
314  return (m_rawConst[7]&0xFF);
315 }
317  return (m_rawConst[6]);
318 }
319 
320 void CastorCORData::getHistogramFibers(int& a, int& b) const {
321  a=-1;
322  b=-1;
323  if (m_formatVersion==-1) {
324  a=((m_rawConst[2]&0x0F00)>>8);
325  b=((m_rawConst[2]&0xF000)>>12);
326  } else {
327  a=((m_rawConst[5]&0x0F00)>>8);
328  b=((m_rawConst[5]&0xF000)>>12);
329  }
330 }
331 
332 bool CastorCORData::unpackHistogram(int myfiber, int mysc, int capid, unsigned short* histogram) const {
333  // check for histogram mode
334  if (!isHistogramEvent()) return false;
335 
336  int fiber1, fiber2;
337  getHistogramFibers(fiber1,fiber2);
338  if (fiber1!=myfiber && fiber2!=myfiber) return false;
339 
340  if (m_formatVersion==-1) {
341  int offset=6+mysc*4*32+capid*32;
342  if (myfiber==fiber2) offset+=3*4*32; // skip to the second half...
343  for (int i=0; i<32; i++)
344  histogram[i]=m_rawConst[offset+i];
345  return true;
346  } else {
347  int offset=8+mysc*4*32+capid*32;
348  if (myfiber==fiber2) offset+=3*4*32; // skip to the second half...
349  for (int i=0; i<32; i++)
350  histogram[i]=m_rawConst[offset+i];
351  return true;
352  }
353 }
354 
CastorCORData & operator=(const CastorCORData &)
int getNPS() const
Get the number of presamples in daq data.
bool isCalibrationStream() const
Is this event a calibration-stream event?
static const int CHANNELS_PER_SPIGOT
Definition: CastorCORData.h:16
void adoptData(const unsigned short *data, int length)
void pack(unsigned char *daq_lengths, unsigned short *daq_samples, unsigned char *tp_lengths, unsigned short *tp_samples, bool do_capid=false)
Unpack the HTR data into TP and DAQ data sorted by channel.
int getNDD() const
Get the number of daq data samples per channel when not zero-suppressed.
void packHeaderTrailer(int L1Anumber, int bcn, int submodule, int orbitn, int pipeline, int ndd, int nps, int firmwareRev=0)
pack header and trailer (call after pack)
#define nullptr
void unpack(unsigned char *daq_lengths, unsigned short *daq_samples, unsigned char *tp_lengths, unsigned short *tp_samples) const
Obtain the starting and ending pointers for external unpacking of the data.
unsigned int getFirmwareRevision() const
Get the COR firmware version.
bool unpackHistogram(int fiber, int fiberchan, int capid, unsigned short *histogram) const
Unpack special histogramming mode data.
unsigned int getSubmodule() const
Get the HTR submodule number.
unsigned int getOrbitNumber() const
Get the HTR orbit number.
int getNTP() const
Get the number of trigger data samples when not zero-suppressed (not available after FW 4) ...
int getNPrecisionWords() const
Get the total number of precision data 16-bit words.
static const int MAXIMUM_SAMPLES_PER_CHANNEL
Definition: CastorCORData.h:17
bool isUnsuppressed() const
Is this event an unsuppresed event?
bool check() const
Check for a good event Requires a minimum length, matching wordcount and length, not an empty event...
unsigned int getPipelineLength() const
Get the pipeline length used for this event.
T min(T a, T b)
Definition: MathUtil.h:58
unsigned short * m_ownData
unsigned int htrSlot() const
HcalElectronicsId-style HTR slot.
void getHistogramFibers(int &a, int &b) const
Get the fiber numbers for the data present in this event (only in histogram mode!) ...
void allocate(int version_to_create=0)
double b
Definition: hdecay.h:120
bool isHistogramEvent() const
Is this event a histogram event? (do not call standard unpack in this case!!!!!)
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
bool wasMarkAndPassZS(int fiber, int fiberchan) const
Was this channel passed as part of Mark&Pass ZS?
double a
Definition: hdecay.h:121
unsigned int htrTopBottom() const
HcalElectronicsId-style HTR top/bottom (1=top/0=bottom)
bool isPatternRAMEvent() const
Is this event a pattern-ram event?
static unsigned int const shift
unsigned int readoutVMECrateId() const
HcalElectronicsId-style VME crate number.
void determineStaticLengths(int &headerWords, int &trailerWords, int &triggerWords) const
const unsigned short * m_rawConst
void determineSectionLengths(int &tpWords, int &daqWords, int &headerWords, int &trailerWords, int &triggerWords) const
Was there an error on the given fiber for this event (only in histogram mode!)