ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
oncsSub_idfnalmwpc.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file oncsSub_idfnalmwpc.cc
1 #include "oncsSub_idfnalmwpc.h"
2 #include <cstring>
3 
4 // for ntohl and ntohs
5 #include <arpa/inet.h>
6 
7 
8 using namespace std;
9 
11  :oncsSubevent_w4 (data)
12 {
13  n_tdcs = 0;
14  length= 0;
15  _decoded = 0;
16 
17  // initialize all to 0
18  memset (&spillinfo, 0 , sizeof(spillinfo) );
19  memset (tsh, 0 , MAXNROFTDCS * sizeof(TDCspillheader) );
20 
21 
22 }
23 
24 
25 int *oncsSub_idfnalmwpc::decode ( int *nwout)
26 {
27 
28  if ( _decoded) return 0;
29 
30  _decoded = 1;
31 
32  int i;
33 
34  int *d = (int *) &SubeventHdr->data; // here begins the payload
35 
36  tdcmask = d[0];
37 
38  // count the number of "on" bits = number of TDCs
39  n_tdcs=0;
40  for ( i = 0; i < MAXNROFTDCS; i++)
41  {
42  if ( (1<< i) & tdcmask ) n_tdcs++;
43  }
44 
45  // unsigned short *xx = (unsigned short *)&d[1];
46  // for ( i = 0; i < 300; i++)
47  // {
48  // cout << setw(5) << i << hex << setw(8) << ntohs(*xx++) << dec << endl;
49  // }
50  // cout << endl;
51 
52 
53  int length = ntohl ( d[1] );
54  spillinfo.spillwords = length; // in 16bit units
55 
56  //we now subtract 2 to remove the header length
57  length -= 2;
58 
59  // dlength is the remaining payload length without the
60  // length word in 16bit units - we subtract 8 bytes for the mask and length
61  int dlength = 2 * ( getLength()-getPadding() ) -4 ;
62 
63  // length is the length of the entire spill stucture without the length
64  // in 16bit words; we do a consistency check
65  if (length > dlength ) return 0;
66 
67  short *s = ( short *) &d[2];
68  int pos = 0;
69 
70  short v;
71 
72  spillinfo.spillcounter = ntohs ( s[pos++]);
73 
74  v = ntohs ( s[pos++]);
75  spillinfo.year = ( v>> 8 ) & 0xff;
76  spillinfo.month = v & 0xff;
77 
78  v = ntohs ( s[pos++]);
79  spillinfo.day = ( v>> 8 ) & 0xff;
80  spillinfo.hour = v & 0xff;
81 
82  v = ntohs ( s[pos++]);
83  spillinfo.minute = ( v>> 8 ) & 0xff;
84  spillinfo.second = v & 0xff;
85 
86  spillinfo.triggercount = ntohs ( s[pos++]);
87  spillinfo.TDC_Status_Bits = ntohs ( s[pos++]);
88  spillinfo.Spill_Link_Status_Bits = ntohs ( s[pos++]);
89 
90  // cout << " triggers = " << spillinfo.triggercount << endl;
91 
92  TDCEvent *te;
93 
94 
95  // we now push, up front, one event structure on the vector
96  // for each trigger so we know that we have one for each event
97  for ( i = 0; i< spillinfo.triggercount; i++)
98  {
99  te = new TDCEvent;
100  TDCEventVector.push_back ( te);
101  }
102 
103 
104  for ( i = 0; i< n_tdcs; i++)
105  {
106  tsh[i].spillwords = ntohs ( s[pos++]);
107  tsh[i].TDC = ntohs ( s[pos++]) -1;
108  tsh[i].spilltriggercount = ntohs ( s[pos++]);
109  tsh[i].spillstatus = ntohs ( s[pos++]);
110  }
111 
112  int old_trigger_number = -1;
113 
114 
115  while (pos < length)
116  {
117  short spillheaderlength = ntohs ( s[pos]);
118  short tdcindex = ntohs ( s[pos+1]) - 1; // the controller counts like fortran
119  if ( tdcindex >= MAXNROFTDCS ) // sanity check
120  {
121  cout << __LINE__ << " " << __FILE__
122  << " wrong TDC index " << tdcindex << " pos= " << pos << endl;
123  }
124 
125  // cout << __LINE__ << " " << __FILE__
126  // << " TDC Event header at pos " << pos << endl;
127 
128  // for ( i = 0 ; i < 8; i++)
129  // {
130  // cout << " " << i << " " << ntohs ( s[pos+i] ) << endl;
131  // }
132 
133  pos++;
134 
135  v = ntohs ( s[pos +2] ) -1;
136  // cout << " trigger number " << v << endl;
137 
138  if ( v <0 || v >= spillinfo.triggercount )
139  {
140  cout << __LINE__ << " " << __FILE__
141  << " wrong Trigger number " << v << " pos= " << pos << endl;
142  return 0;
143  }
144 
145 
146  // we are only interested in this TDC if it has data (the header length is 8)
147  // (and passes the sanity check)
148  if ( spillheaderlength > 8 && tdcindex < MAXNROFTDCS )
149  {
150  // we are lookin ahead two words to get the
151  // trigger number. If this is different from the one
152  // we had before, we are done with the old event, and start
153  // a new one. (intially we see -1, so it's always different).
154  // as a reminder - w.r.t. "pos":
155  // +0 TDC#
156  // +1 event status
157  // +2 "ordinal trigger number"
158  // +3 trigger type
159  // +4 800MHz event time stamp (12 bits)
160  // +5 event time stamp (100Mhz) upper 16
161  // +6 event time stamp (100Mhz) lower 16
162  // +7 here start the hits
163 
164  if ( v != old_trigger_number ) // ok, new event/trigger, so we get the next TDCEvent
165  {
166  old_trigger_number = v;
167  te = TDCEventVector[v];
168  te->trigger_nr = v;
169  te->evt_timestamp = ntohs (s[pos+4]);
170  te->local_ts_upper = ntohs (s[pos+5]);
171  te->local_ts_lower = ntohs (s[pos+6]);
172 
173  // quick sanity check: bits 3...11 of
174  // the timstamp must be equal to the
175  // 9 lsb's of te->local_ts_lower
176 
177  // cout << " time stamps " << hex
178  // << ( ( te->evt_timestamp>>3) &0x1ff ) << " "
179  // << ( te->local_ts_lower & 0x1ff) << dec << endl;
180 
181 
182  // now we construct the long 35 bit 800MHz time stamp
183  // cout << "time stamps " << hex
184  // << te->evt_timestamp << " "
185  // << te->local_ts_upper << " "
186  // << te->local_ts_lower << dec << endl;
187 
188  te->absolute_time = te->local_ts_upper;
189  te->absolute_time <<= 16;
190  te->absolute_time += te->local_ts_lower;
191  te->absolute_time <<= 3;
192  te->absolute_time += ( te->evt_timestamp &0x3);
193  // and we clear the TDCData structures
194  memset ( te->td, 0, MAXNROFTDCS * sizeof( TDCData) );
195 
196  // we are done with filling in the new event "header" structure
197  // now we fill in the TCDData structure. some of this
198  // is redundant to the header info, that's why we kept "pos" frozen
199  }
200 
201  te->td[tdcindex].words = spillheaderlength;
202  te->td[tdcindex].TDC = tdcindex;
203  te->td[tdcindex].EventStatus =ntohs (s[pos+1]);
204  te->td[tdcindex].triggertype =ntohs (s[pos+3]);
205 
206  // this may look redundant with the code above, but is actually
207  // per TDC info - the abve was per event. Should match, and we fill it in
208  // so the user can perform a sanity check
209  te->td[tdcindex].evt_timestamp = ntohs (s[pos+4]);
210  te->td[tdcindex].local_ts_upper = ntohs (s[pos+5]);
211  te->td[tdcindex].local_ts_lower = ntohs (s[pos+6]);
212 
213  // now we construct the long 35 bit 800MHz time stamp
214  te->td[tdcindex].absolute_time = te->td[tdcindex].local_ts_upper;
215  te->td[tdcindex].absolute_time <<= 16;
216  te->td[tdcindex].absolute_time += te->td[tdcindex].local_ts_lower;
217  te->td[tdcindex].absolute_time <<= 3;
218  te->td[tdcindex].absolute_time += ( te->td[tdcindex].evt_timestamp &0x7);
219 
220  // at long last, the business end of this TDC - the TDC hit
221  int xpos = pos+7; // that's where the hits start
222  for ( i = 0; i < te->td[tdcindex].words -8; i++) // so many hits, header is 8 long
223  {
224  te->td[tdcindex].hits++; // this is the same as the TDCHitlist.size()
225 
226  TDC_hit *th = new TDC_hit;
227  te->td[tdcindex].TDCHitlist.push_back ( th );
228 
229  short h = ntohs ( s[xpos+i]); // this is now the TDC word
230  th->wire = ( h >> 10) & 0x3f; // upper bits are "wire"
231  th->timestamp = h & 0x3ff; // lower 10 bits are "timestamp"
232 
233  }
234  pos += spillheaderlength-1; // -1 because we stepped "pos" one position in already
235  }
236  else
237  {
238  // short tdc = ntohs(s[pos]);
239  // cout << " skipping TDC " << tdc << " words = " << l << " pos = " << pos << endl;
240  pos+= 7;
241  }
242 
243 
244  }
245 
246  return 0;
247 }
248 
249 
250 int oncsSub_idfnalmwpc::iValue(const int ich,const char *what)
251 {
252 
253  decode (0);
254  if ( strcmp(what,"NTDCS") == 0 )
255  {
256  return n_tdcs;
257  }
258 
259  else if ( strcmp(what,"TRIGGERCOUNT") == 0 )
260  {
261  return spillinfo.triggercount;
262  }
263 
264  else if ( strcmp(what,"SPILLCOUNTER") == 0 )
265  {
266  return spillinfo.spillcounter;
267  }
268 
269  else if ( strcmp(what,"TDCSTATUSBITS") == 0 )
270  {
271  return spillinfo.TDC_Status_Bits;
272  }
273 
274  else if ( strcmp(what,"LINKSTATUSBITS") == 0 )
275  {
277  }
278 
279  else if ( strcmp(what,"MONTH") == 0 )
280  {
281  return spillinfo.month;
282  }
283 
284  else if ( strcmp(what,"DAY") == 0 )
285  {
286  return spillinfo.day;
287  }
288 
289  else if ( strcmp(what,"YEAR") == 0 )
290  {
291  return spillinfo.year;
292  }
293 
294  else if ( strcmp(what,"HOUR") == 0 )
295  {
296  return spillinfo.hour;
297  }
298 
299  else if ( strcmp(what,"MINUTE") == 0 )
300  {
301  return spillinfo.minute;
302  }
303 
304  else if ( strcmp(what,"SECOND") == 0 )
305  {
306  return spillinfo.second;
307  }
308 
309  return 0;
310 
311 }
312 
313 
314 int oncsSub_idfnalmwpc::iValue(const int trigger ,const int tdc, const int index)
315 {
316  decode (0);
317  if ( trigger < 0 || (unsigned int ) trigger >= TDCEventVector.size()) return 0;
318  if ( tdc < 0 || tdc >= n_tdcs) return 0;
319  if ( index < 0 || index >= TDCEventVector[trigger]->td[tdc].hits) return 0;
320 
321  return TDCEventVector[trigger]->td[tdc].TDCHitlist[index]->wire;
322 }
323 
324 int oncsSub_idfnalmwpc::iValue(const int trigger ,const int tdc, const char *what)
325 {
326  decode (0);
327  if ( trigger < 0 || (unsigned int )trigger >= TDCEventVector.size()) return 0;
328  if ( tdc < 0 || tdc >= n_tdcs) return 0;
329 
330 
331  if ( strcmp(what,"HITS") == 0 )
332  {
333  if ( (unsigned int ) trigger >= TDCEventVector.size() )
334  {
335  cout << __LINE__ << " " << __FILE__ << " wrong trigger " << trigger << " max " << TDCEventVector.size() << endl;
336  return 0;
337  }
338 
339  return TDCEventVector[trigger]->td[tdc].hits;
340  }
341  else if ( strcmp(what,"TDC") == 0 )
342  {
343  return TDCEventVector[trigger]->td[tdc].TDC;
344  }
345 
346  return 0;
347 }
348 
349 int oncsSub_idfnalmwpc::iValue(const int trigger ,const int tdc, const int index, const char *what)
350 {
351  decode (0);
352  if ( trigger < 0 || (unsigned int )trigger >= TDCEventVector.size()) return 0;
353  if ( tdc < 0 || tdc >= n_tdcs) return 0;
354  if ( index < 0 || index >= TDCEventVector[trigger]->td[tdc].hits) return 0;
355 
356 
357  if ( strcmp(what,"WIRE") == 0 )
358  {
359  return iValue(trigger, tdc, index);
360  }
361 
362  else if ( strcmp(what,"TIMESTAMP") == 0 )
363  {
364  return TDCEventVector[trigger]->td[tdc].TDCHitlist[index]->timestamp;
365  }
366 
367 
368  return 0;
369 }
370 
371 
372 
374 {
375 
376  decode (0);
377  identify(os);
378 
379  int j, k, l;
380 
381 
382  os << " Date " << iValue(0, "MONTH")
383  << "/" << iValue(0,"DAY")
384  << "/20" << iValue(0,"YEAR")
385  << " " << iValue(0,"HOUR")
386  << ":" << iValue(0,"MINUTE")
387  << ":" << iValue(0,"SECOND") << endl;
388 
389  os << " Spill Counter " << iValue(0,"SPILLCOUNTER") << endl;
390 
391  int tc = iValue(0,"TRIGGERCOUNT");
392 
393  os << " Trigger Count " << tc << endl;
394  os << " TDC Status Bits " << hex << iValue(0,"TDCSTATUSBITS") << dec << endl;
395  os << " Link Status bits " << hex << iValue(0,"LINKSTATUSBITS") << dec << endl;
396 
397  for ( k = 0; k < tc; k++)
398  {
399 
400  os << " new event "
401  << " trg# tdc hit wire timestamp" << endl;
402 
403  for ( l = 0; l < iValue(0,"NTDCS"); l++)
404  {
405  int hits =iValue ( k, l, "HITS");
406  if ( hits)
407  {
408  int tdc = iValue(k,l,"TDC");
409 
410  for ( j = 0; j < hits; j++)
411  {
412  os << " " << setw(6) << k
413  << setw(8) << tdc << setw(8) << j
414  << setw (8) << iValue(k,l,j)
415  << setw(8) << iValue(k,l,j,"TIMESTAMP") << endl;
416  }
417  }
418  }
419  }
420  os << endl;
421 
422 
423 
424 }
425 
427 {
428 
429 
430  int l;
431  unsigned int i,k;
432  TDCEvent *te;
433 
434  for ( k = 0; k< TDCEventVector.size() ; k++)
435  {
436  te = TDCEventVector[k];
437 
438  for ( l = 0; l < n_tdcs; l++)
439  {
440  for ( i = 0; i < te->td[l].TDCHitlist.size() ; i++)
441  {
442  delete te->td[l].TDCHitlist[i];
443  }
444  }
445  delete te;
446  }
447 }
448