StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
itpc23.cxx
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <pthread.h>
6 
7 #include <rtsLog.h>
8 #include <rts.h>
9 #include <rtsSystems.h>
10 
11 #include <DAQ_READER/daq_dta.h>
12 
13 #include <DAQ_ITPC/itpcCore.h>
14 #include <DAQ_ITPC/itpc_rowlen.h>
15 #include <DAQ_ITPC/itpcPed.h>
16 
17 #include "itpc23.h"
18 
19 //================================================================================
20 //============= iTPC Data Support Routines for the NEW (FY23) version!!! =========
21 //================================================================================
22 
23 tpc23_base::row_pad_t (*itpc23::rp_gain_itpc)[ROW_MAX+1][PAD_MAX+1] ;
24 
25 
26 static const char *hwicap_version(u_int v) ;
27 static u_int get_ifee_mask(int sec1, int rdo1) ;
28 
29 
30 static inline u_int sw16(u_int d)
31 {
32  d = ((d>>16)&0xFFFF)|(d<<16) ;
33 
34  return d ;
35 }
36 
37 inline u_int itpc23::set_rdo(int sec, int rdo)
38 {
39 // LOG(TERR,"set_rdo %d: S%02d:%d",id,sec,rdo) ;
40 
41  sector1 = sec ;
42  rdo1 = rdo ;
43 
44  fee_mask = get_ifee_mask(sector1,rdo1) ;
45 
46  return fee_mask ;
47 } ;
48 
49 // Change the data format from the old FY22 version to the new
50 // FY23 version. Store data back into the original storage.
51 int itpc23::from22to23(char *c_dta, int words)
52 {
53  int n_words = words ;
54  u_int *data = (u_int *)c_dta ;
55 
56  u_int *d_use = (u_int *)malloc(words*4+1024) ; // allocate sotrage
57 
58  u_int *data_end = data + words ;
59  u_int *data_start = data ;
60 
61  err = 0 ; // in class
62 
63  // this is wrong! I need to get it from the data!!
64  fee_mask = get_ifee_mask(sector1,rdo1) ;
65 
66 // LOG(TERR,"iS%02d:%d fee_mask 0x%04X",sector1,rdo1,fee_mask) ;
67 
68  int w_cou = (words<16)?words:16 ;
69 
70  for(int i=0;i<w_cou;i++) {
71  if((data[i]==0xCCCC001C)||(data[i]==0x001CCCCC)) {
72  data = data + i ;
73  break ;
74  }
75  }
76 
77  w_cou = data_end - data ;
78 
79  int need_swapping = 0 ;
80  if(data[0]==0xCCCC001C) {
81 // LOG(WARN,"Need swapping!") ;
82  need_swapping = 1 ;
83  for(int i=0;i<w_cou;i++) {
84  data[i] = sw16(data[i]) ;
85  }
86  }
87  data += 1 ; // skip start comma
88 
89 // data += 5 ; // at start comma
90 
91  // data[0] = 0x9800.... ;
92  // data[1] = trigger word
93 
94 
95  if((data[0]&0xFFFF000F) != 0x98000004) {
96  run_errors++ ;
97  if(mode || (online && run_errors<10)) {
98  LOG(ERR,"start 0 0x98 = 0x%08X",data[0]) ;
99  }
100  err |= 0x10000000 ;
101  }
102 
103 // LOG(TERR,"wds 0x%08X 0x%08X; data end 0x%08X",data[0],data[1],data_end[0]) ;
104 // for(int i=0;i>-15;i--) {
105 // LOG(TERR," end %d = 0x%08X",i,data_end[i]) ;
106 // }
107 
108  // data[3] is 0x80310010...???
109 
110 
111  // go to the end...
112 
113 
114  int found ;
115 
116 #if 0
117  data_end = data_end - 1 - 2 - 1 - 6 - 1 ;
118 
119  // hm, live data seems to need -10 and not -11???
120  if(need_swapping) {
121 // LOG(WARN,"adjusting data end") ;
122  data_end++ ;
123  }
124 
125  //data_end[0] is 0x5800...
126  if((data_end[0]&0xFF000000) != 0x58000000) {
127  LOG(ERR,"data_end 0 0x58 = 0x%08X",data_end[0]) ;
128  }
129 #else
130  // find it going backwwards
131 
132  found = 0 ;
133  for(int i=0;i<16;i++) {
134 // LOG(TERR,"%d: 0x%08X",-i,data_end[-1]) ;
135 
136  if((data_end[-i]&0xFF000000)==0x58000000) {
137  data_end = data_end - i ;
138  found=1 ;
139  break ;
140  }
141  }
142 
143  if(!found) {
144  run_errors++ ;
145  err |= 0x20000000 ;
146  if(mode || (online && run_errors<10)) LOG(ERR,"%d: can't find data_end!",rdo1) ;
147  }
148 
149 #endif
150 
151 // LOG(TERR,"data_end 0x%08X",data_end[0]) ;
152 
153  found = 0 ;
154  while(data_end>data) {
155  if((*data_end & 0xFF000000)==0x98000000) {
156  found = 1 ;
157  break ;
158  }
159  data_end-- ;
160  }
161 
162  // data_end[0] is 0x9800.... : trigger header
163 
164  if(!found) {
165  run_errors++ ;
166  err |= 0x20000000 ;
167  if(mode || (online && (run_errors<10))) {
168  LOG(ERR,"%d: data_end 0x98 not found = 0x%08X",rdo1,data_end[0]) ;
169  }
170  }
171 
172  n_words = data_end - data ;
173 
174  u_int *d = data + 2 ; // now at 0x8.....
175 
176 
177 
178  int fee_cou = 0 ;
179  u_int *fee_p[16] ;
180  int l_fee_mask = 0 ;
181 
182  memset(fee_p,0,sizeof(fee_p)) ;
183 
184  while(d<data_end) {
185 // if((d-data)<16) LOG(TERR,"... %d 0x%08X",d-data,d[0]) ;
186 
187  if((d[0]&0xFF000000)==0x80000000) { // FEE start
188  int port = d[4]&0xF ;
189  fee_cou++ ;
190 
191  l_fee_mask |= (1<<port) ;
192  fee_p[port] = d ;
193 
194 // LOG(TERR,"FEE cou %d: port %d: fee_mask 0x%04X at %d",fee_cou,port,l_fee_mask,d-data) ;
195 
196 
197  }
198  d++ ;
199  }
200 
201  if(online) {
202  if(l_fee_mask != fee_mask) {
203  err |= 0x40000000 ;
204  run_errors++ ;
205  if(online && run_errors<10) LOG(ERR,"%d: FEE mask 0x%X, expect 0x%X, words %d/%d",rdo1,l_fee_mask,fee_mask,words,n_words) ;
206  free(d_use) ;
207  return 0 ;
208  }
209  }
210 
211 
212  fee_mask = l_fee_mask ; // NOTE the re-write!
213 
214 // fee_mask = get_ifee_mask(sector1,rdo1) ;
215 
216  for(int i=0;i<5;i++) d_use[i] = data_start[i] ;
217 
218  d_use[5] = 0x20000000 ; // 1:
219  d_use[6] = data[1] ; // 2:trigger
220  d_use[7] = 0 ; // 3: MHZ start
221  d_use[8] = fee_mask<<16 ; // 4: fee_synced,overrun
222  d_use[9] = 0 ; // 5: fee_xoff,rdo_stuff
223  d_use[10] = 0 ; // 6: fee_emtpy
224  d_use[11] = 0xF0000000 | fee_mask ; // 7: sig
225 
226  u_int *d_fee = d_use + 12 ;
227 
228  int ix = 0 ;
229  for(int i=0;i<16;i++) {
230  u_int *p = fee_p[i] ;
231 
232  if(p==0) continue ;
233 
234  d_fee[ix] = p[0] & 0xFFFF0000 ;
235  d_fee[ix] |= 0xF0 ; // even-type
236 
237  ix++ ;
238 
239  // find 0xB....
240  while((p[0]&0xF0000000)!=0xB0000000) {
241  p++ ;
242  }
243 
244  d_fee[ix] = p[0] ;
245  ix++ ;
246  p++ ;
247 
248  int no_cpy = 0 ;
249  while((p[0]&0xF0000000)!=0x40000000) {
250  if((p[0]&0xF0000000)==0xA0000000) {
251  no_cpy = 1 ;
252  }
253 
254  if(no_cpy==0) {
255  d_fee[ix] = p[0] ;
256  ix++ ;
257 
258  if(ix>(n_words)) {
259  run_errors++ ;
260  err |= 0x80000000 ;
261  if(mode || (online && run_errors<10)) LOG(ERR,"%d: words %d, ix %d",rdo1,n_words,ix) ;
262  free(d_use) ;
263  return 0 ;
264  }
265  }
266 
267  p++ ;
268  }
269 
270  d_fee[ix] = p[0] ;
271  ix++ ;
272 
273  if(ix>(n_words)) {
274  run_errors++ ;
275  if(mode || (online && run_errors<10)) LOG(ERR,"%d: words %d, ix %d",rdo1,n_words,ix) ;
276  err |= 0x80000000 ;
277  free(d_use) ;
278  return 0 ;
279  }
280  }
281 
282  if(n_words<12) {
283  run_errors++ ;
284  if(mode || (online && run_errors<10)) LOG(ERR,"%d: n_words %d",rdo1,n_words) ;
285  err |= 0x80000000 ;
286  free(d_use) ;
287  return 0 ;
288  }
289 
290  // trailer
291  d_use[n_words-1] = 0xDEADC0DE ;
292  d_use[n_words-2] = 0xFEEDC0FE ;
293  d_use[n_words-3] = 0x0 ; // trl1: mhz_end
294  d_use[n_words-4] = 0xFFFFFFFF ; // trl0: evt_status ;
295 
296 // LOG(TERR,"words %d, n_words %d",words,n_words) ; // n_words is 20 less than words
297 
298  // and now FEE data???
299 
300  // finalize
301 
302  memcpy(c_dta,d_use,n_words*4) ;
303 
304  free(d_use) ;
305 
306 // LOG(TERR,"from22to23: done") ;
307 
308  return n_words ;
309 }
310 
311 
312 
313 
314 int itpc23::init(daq_dta *gain)
315 {
316  if(gain==0) return -1 ;
317 
318  while(gain->iterate()) {
319  int s = gain->sec ;
320  int r = gain->row ;
321 
322  daq_det_gain *gp = (daq_det_gain *) gain->Void ;
323 
324  for(u_int p=0;p<gain->ncontent;p++) {
325  if(p==0) continue ;
326 
327  //gain row,pad is gp[p].gain, gp[p].t0 ;
328  LOG(TERR,"gains: S%02d, rp %d:%d = %.1f",s,r,p,gp[p].gain) ;
329  }
330 
331  }
332 
333  return 9 ;
334 }
335 
336 // We are at the SAMPA(fee_ix):channel header
337 u_int *itpc23::ch_scan(u_int *start)
338 {
339  u_short w[6] ;
340  u_int *d = start ;
341  int row, pad ;
342  int is_error = 0 ;
343 
344  // we are at the SAMPA header
345  retry_fix:;
346 
347  w[0] = (d[0]>>20)&0x3FF ;
348  w[1] = (d[0]>>10)&0x3FF ;
349  w[2] = (d[0]>>00)&0x3FF ;
350 
351  w[3] = (d[1]>>20)&0x3FF ;
352  w[4] = (d[1]>>10)&0x3FF ;
353  w[5] = (d[1]>>00)&0x3FF ; // what do I have here?
354 
355  int pkt = (w[0]>>7)&0x7 ;
356  int sampa_ch = (w[2]>>4)&0x1F ;
357  int sampa_id = w[2]&0xF ;
358 
359  int words10 = w[1] ;
360 
361  // I need to get to row,pad here!
362  if(log_level>=1) LOG(TERR,"%d: words10 %d:%d (SAMPA %d,%d): words10 %d",rdo1,fee_ix,ch_ix,sampa_id,sampa_ch,words10) ;
363 
364  if(unlikely(words10==1023)) { // channel skipped because of prog-full!
365  prog_fulls++ ;
366  if(mode || (online && run_errors<10)) LOG(ERR,"%d: ch_scan %d:%d: SAMPA%d:%d -- prog-full",rdo1,fee_ix,ch_ix,sampa_id,sampa_ch) ;
367  words10 = 0 ;
368  }
369 
370 // LOG(WARN,"pkt %d: sampa_id %d, sampa_ch %d, words10 %d",pkt,sampa_id,sampa_ch,words10) ;
371 
372  if(unlikely(pkt!=4 || sampa_ch>31 || words10>512)) {
373  err |= 0x1000000 ;
374  is_error = 1 ;
375  run_errors++ ;
376  if(mode || (online && run_errors<20)) {
377  LOG(ERR,"%d: T %d: ch_scan %d:%d:%d: pkt %d, sampa %d:%d, words10 %d [0x%08X: 0x%08X 0x%08X], err 0x%X",
378  rdo1,token,fee_ix,lane_ix,
379  ch_ix,
380  pkt,sampa_id,sampa_ch,words10,
381  d[0],d[-1],d[1],err) ;
382 
383 // LOG(ERR,"err 0x%08X",err) ;
384 
385  //int ppk[2] ;
386 
387  //ppk[0] = (((d[-1]>>20)&0x3FF)>>7)&0x7 ;
388  //ppk[1] = (((d[1]>>20)&0x3FF)>>7)&0x7 ;
389 
390  //LOG(ERR,"%d %d",ppk[0],ppk[1]) ;
391  //d++ ;
392  //goto retry_fix ;
393 
394  }
395  if(d<trl) {
396  d++ ;
397  goto retry_fix ;
398  }
399  else {
400  if(mode || online) LOG(ERR,"Can't fix -- giving up") ;
401 // return 0 ;
402  }
403  }
404  else if(is_error) {
405  if(mode || (online && run_errors<20)) LOG(WARN,"Recovered %d:%d, words10 %d",sampa_id,sampa_ch,words10) ;
406  //err ^= 0x1000000 ;
407  is_error = 0 ;
408  }
409 
410  int bx = ((w[4]&0x1FF)<<17)|(w[3]<<1)|((w[2]>>9)&1) ;
411 
412  if(unlikely(bx_count<0)) { // first channel of the FEE
413  bx_count = bx ;
414  }
415  else {
416  if(unlikely(bx != bx_count)) {
417  if(abs(bx-bx_count)>1) {
418  err |= 0x2000000 ;
419  run_errors++ ;
420  if(mode || (online && run_errors<10)) {
421  LOG(ERR,"%d: T %d: ch_scan %d:%d:%d bx %d, expect %d",rdo1,token,fee_ix,lane_ix,ch_ix,bx,bx_count) ;
422  }
423  }
424  }
425  }
426 
427 
428  int words10_start = words10 ; // remember
429 
430  while(words10%3) words10++ ; // align on 32bit word
431 
432  int words = words10/3 ; // and then count them...
433 
434  d += 2 ; // move from channel header...
435 
436  int ix = 0 ;
437  int a_ix = 0 ;
438  int tb_cou = 0 ;
439  int tb_start = 0 ;
440  int tb_last = -1 ;
441  int w10 = 0 ;
442 
443  u_short *d_start = s1_dta + last_ix ;
444  struct seq_t *seq = 0 ;
445  u_short *dd = s1_dta + last_ix ;
446  u_short *dd_save = dd ;
447 
448  int seq_ix = 0 ;
449 
450  // craft id
451  int id = (fee_pp<<1)|(sampa_id&1) ;
452  int flags = flags_row_pad(id, sampa_ch, row, pad) ; // also gets row,pad from id sampa_ch
453 
454  if(log_level>=2) {
455  LOG(TERR,"... %d: fee_ix %d, fee_pp %d: sampa_id %d, sampa_ch %d: row %d, pad %d, flags 0x%X",rdo1,fee_ix,fee_pp,
456  sampa_id,sampa_ch,row,pad,flags) ;
457  }
458 
459 
460 // printf("... evt %d: DDDD %d: fee_ix %d, fee_pp %d, ch_ix %d: sampa_id %d, sampa_ch %d: row %d, pad %d, flags 0x%X\n",evt,rdo1,fee_ix,fee_pp,ch_ix,
461 // sampa_id,sampa_ch,row,pad,flags) ;
462 
463 
464  // skip non-wanted rows and pads
465  if(flags==0xFF) {
466  goto done_ch ;
467  }
468 
469  seq = s1[row][pad].seq ;
470 
471  if(log_level>=2) LOG(TERR,"Here %p, words %d, %p",seq,words,dd) ;
472 
473  // now dump the data out...
474 
475  for(int i=0;likely(i<words);i++) {
476  w[0] = (d[i]>>20)&0x3FF ;
477  w[1] = (d[i]>>10)&0x3FF ;
478  w[2] = (d[i]>>00)&0x3FF ;
479 
480  // it goes
481  // tb_cou, tb_start, adc, adc, adc x tb_cou times
482  // from low tb_start to high
483  if(unlikely(d[i]&0xC0000000)) {
484  run_errors++ ;
485  if(mode || (online && run_errors<10)) {
486  LOG(ERR,"%d: ch_scan %d:%d: SAMPA %d:%d: bad word 0x%08X",rdo1,fee_ix,ch_ix,
487  sampa_id,sampa_ch,d[i]) ;
488  }
489  }
490 
491  if(log_level>=2) LOG(TERR,"FEE %d:%d -- %d = 0x%08X",fee_ix,ch_ix,i,d[i]) ;
492 
493 
494  for(int j=0;likely(j<3);j++) {
495  w10++ ;
496 
497  switch(ix) {
498  case 0 :
499  tb_cou = w[j] ; // actual count of ADCs
500 
501  if(log_level>=100) LOG(TERR," tb_cou %d %p",tb_cou,dd) ;
502 
503  *dd++ = tb_cou ;
504 
505  if(log_level>=100) LOG(TERR," tb_cou %d",tb_cou) ;
506 
507  if(unlikely(tb_cou>500)) {
508  run_errors++ ;
509  if(mode || (online && run_errors<10)) {
510  LOG(ERR,"%d: rp %d:%d: tb_cou %d [0x%08X,%d]",rdo1,row,pad,tb_cou,d[i],i) ;
511  }
512  }
513  ix = 1 ;
514  break ;
515  case 1 :
516  tb_start = w[j] ; // which is tb_lo
517  *dd++ = tb_start ;
518 
519  if(seq_ix>=(SEQ_MAX-1)) {
520  if(mode || online) LOG(ERR,"too many seqs %d",seq_ix) ;
521  goto done_ch ;
522  }
523 
524  //printf("seq_ix %d: %d %d = %d %d\n",seq_ix,row,pad,tb_start,tb_cou) ;
525 
526 
527  //LOG(TERR,"DDD %d %d %d",tb_start,tb_cou,tb_start+tb_cou-1) ;
528 
529  seq[seq_ix].t_lo = tb_start ;
530  seq[seq_ix].t_hi = tb_start + tb_cou - 1 ;
531  seq[seq_ix].dta_p = (dd-d_start) ; // where is this sequence...
532  seq[seq_ix].blob_id = 0 ;
533  //seq_ix++ ;
534 
535  //dd += tb_cou ; // this doesn't sound correct!!!
536 
537  if(unlikely(log_level>=100)) LOG(TERR," tb_start %d",tb_start) ;
538 
539  if(unlikely(tb_start<=tb_last)) {
540  run_errors++ ;
541  if(mode || (online && run_errors<10))LOG(ERR,"%d: rp %d:%d: tb_start %d, tb_last %d",rdo1,row,pad,tb_start,tb_last) ;
542 
543  seq[seq_ix].t_lo = 400 ;
544  seq[seq_ix].t_hi = 401 ;
545 
546  }
547 
548 
549 
550  tb_last = tb_start + tb_cou ;
551  if(unlikely(tb_last>500)) {
552  run_errors++ ;
553  if(mode || (online && run_errors<10)) LOG(ERR,"%d: rp %d:%d: tb_last %d [0x%08X,%d]",rdo1,row,pad,tb_last,d[i],i) ;
554 
555  seq[seq_ix].t_lo = 400 ;
556  seq[seq_ix].t_hi = 401 ;
557  }
558 
559  seq_ix++ ;
560 
561  ix = 2 ;
562  break ;
563  default :
564  //adc[a_ix] = w[j] ;
565  if(log_level>=100) LOG(TERR," adc %d, %d",w[j],a_ix) ;
566  a_ix++ ;
567  *dd++ = w[j] ; // store ADC
568 
569 
570  //printf(" a_ix %d, adc %d\n",a_ix,w[j]) ;
571 
572  if(unlikely(a_ix==tb_cou)) { // sequence done!
573  tb_last = -1 ;
574  ix = 0 ;
575  a_ix = 0 ;
576  if(w10==words10_start) goto done_ch ;
577  }
578  break ;
579  }
580  }
581 
582  if(log_level>=2) LOG(TERR,"Here %d",__LINE__) ;
583 
584 // printf("%d:%d %d: %d %d %d\n",fee_ix,ch_ix,i,w[0],w[1],w[2]) ;
585 
586  }
587 
588  done_ch :;
589 
590  if(seq) {
591  sequence_cou += seq_ix ;
592  seq[seq_ix].t_hi = -1 ;
593  s1[row][pad].ix = last_ix ;
594 
595 
596  // data_c will exist in either: pedestal/pulser runs OR in the daqReader
597 
598  if(data_c) {
599  u_short *dd = dd_save ;
600 
601  int ii = lane_ix/2 ;
602  int ch = ii*32 + sampa_ch ;
603 
604  if(log_level>=2) {
605  LOG(TERR,"fee_pp %d, fee_ix %d, lane_ix %d, sampa_ch %d, ch %d",
606  fee_pp,fee_ix,lane_ix,sampa_ch,ch) ;
607  }
608 
609 
610 
611  data_c->sector = sector1 -1 ;
612  data_c->rdo = rdo1-1 ;
613  data_c->port = fee_ix ;
614  data_c->fee_id = fee_pp ;
615 
616  data_c->ch_start(ch) ;
617 
618 
619  for(int i=0;i<seq_ix;i++) {
620  dd += 2 ;
621  int t_len = seq[i].t_hi - seq[i].t_lo + 1 ;
622 
623 // printf(" t_start %d, len %d\n",seq[i].t_lo,t_len) ;
624 
625  int ii = 0 ;
626  for(int j=0;j<t_len;j++) {
627  int adc = *dd++ ;
628  int tb = seq[i].t_lo + ii ;
629  //adc = (fee_ix+1)+100 ;
630  data_c->accum(sector1-1,rdo1-1,fee_ix,fee_pp,ch,tb,adc) ;
631  ii++ ;
632  }
633  }
634 
635  data_c->ch_done(0) ;
636  }
637 #if 0
638  {
639  u_short *dd = dd_save ;
640  for(int i=0;i<seq_ix;i++) {
641  dd += 2 ;
642  int t_len = seq[i].t_hi - seq[i].t_lo + 1 ;
643 
644  printf("RP %d:%d, seq %d: t_lo %d, t_hi %d\n",row,pad,i,seq[i].t_lo,seq[i].t_hi) ;
645 
646  int ii = 0 ;
647  for(int j=0;j<t_len;j++) {
648  int adc = *dd++ ;
649  int tb = seq[i].t_lo + ii ;
650 
651  printf(" tb %3d = %3d ADC\n",tb,adc);
652 
653  ii++ ;
654  }
655  }
656  }
657 #endif
658 
659  }
660 
661  last_ix += dd-d_start ;
662 
663  d += words ;
664 
665 
666 
667  return d ;
668 }
669 
670 u_int *itpc23::lane_scan(u_int *start)
671 {
672  u_int *d = start ;
673 
674  retry_fix:;
675 
676  if(log_level>=1) LOG(TERR,"%d: lane scan %d: 0x%08X",rdo1,lane_ix,d[0]) ;
677 
678  // should be at start of lane 0xB....
679  if((d[0]&0xF0000000)!=0xB0000000) { // start of lane
680  if((online && run_errors<10) || mode) {
681  LOG(ERR,"%d: T %d: lane_scan %d:%d: unknown start 0x%08X [0x%08X 0x%08X]",rdo1,token,fee_ix,lane_ix,d[0],d[-1],d[1]) ;
682  }
683 
684  if(d[0]==d[-1]) {
685  if(mode || (online && run_errors<10)) {
686  LOG(WARN,"%d: lane_scan %d:%d: retrying fix",rdo1,fee_ix,lane_ix) ;
687  }
688  d++ ;
689  goto retry_fix ;
690  }
691  else {
692  err |= 0x100000 ;
693  }
694 
695  }
696  else if((d[0]>>26)&0x3) { // SAMPA FIFOs overwritten!
697  err |= 0x200000 ;
698  if(online || mode) LOG(ERR,"%d: lane_scan %d:%d: SAMPA FIFO overwritten 0x%08X",rdo1,fee_ix,lane_ix,d[0]) ;
699  }
700 
701  d++ ; // skip 0xB....
702 
703  if(log_level>=1) LOG(TERR,"%d: lane scan %d: 0x%08X",rdo1,lane_ix,d[0]) ;
704 
705  for(int i=0;i<16;i++) {
706  ch_ix = i ;
707  d = ch_scan(d) ;
708  }
709 
710  // should be at end of lane 0x7....
711  if((d[0]&0xF0000000)!=0x70000000) { // end of lane
712  err |= 0x400000 ;
713  run_errors++ ;
714  if((online && run_errors<20)|| mode) LOG(ERR,"%d: T %d: lane_scan %d:%d: unknown end 0x%08X",rdo1,token,fee_ix,lane_ix,d[0]) ;
715  }
716 
717  d++ ; // skip 0x7...
718 
719  return d ;
720 }
721 
722 u_int *itpc23::fee_non_trgd(u_int *start)
723 {
724  u_int *d = start ;
725 
726  int fee_words = 0 ;
727 
728  if(fee_evt_type != 0x02) { // no clue
729  if(online || mode) LOG(ERR,"%d: T %d: fee_non_trgd %d: evt_type 0x%02X",rdo1,token,fee_ix,fee_evt_type) ;
730 
731 
732  while(d<trl) {
733  if((d[0]&0xF0000000)==0x40000000) {
734  break ;
735  }
736  d++ ;
737  fee_words++ ;
738  }
739  }
740  else {
741  LOG(NOTE,"fee_scan %d: evt_type 0x%02X, words %d",fee_ix,fee_evt_type,fee_words) ;
742 
743  // I am now at 0x6...
744  for(int i=0;i<16;i++) {
745  LOG(NOTE,"%d = 0x%08X",i,d[i]) ;
746  }
747 
748  d++ ; // I am now at 0xA...
749 
750 
751  d++ ; // I am now at data
752 
753  //0: shorts config version
754  //1: shorts rdo_port
755  //2: shorts fee_id
756  //3: shorts for_me(WTF)
757  int rdo_port = d[1]&0xFFFF ;
758  int fee_id = d[2]&0xFFFF ;
759 
760  d += 4 ; // skip blabbler
761 
762  u_short sampa_stat[2] ;
763 
764  sampa_stat[0] = d[0]&0xFFFF ;
765  sampa_stat[1] = d[1]&0xFFFF ;
766 
767  d += 2 ;
768 
769  d += 16 ; // zeros
770 
771  d += 2 ; // something
772 
773  u_int v_all = d[0]&0xFFFF ;
774  v_all |= (d[1]&0xFFFF)<<16 ;
775 
776  u_int v_bit = d[2]&0xFFFF ;
777  v_bit |= (d[3]&0xFFFF)<<16 ;
778 
779  unsigned long wire1 = d[4]&0xFFFF ;
780  wire1 |= (long)(d[5]&0xFFFF)<<16 ;
781  wire1 |= (long)(d[6]&0xFFFF)<<32 ;
782  wire1 |= (long)(d[7]&0xFFFF)<<48 ;
783 
784  wire1 >>= 8 ;
785  wire1 &= 0xFFFFFFFF ;
786 
787  u_int temp = d[8]&0xFFFF ;
788  temp |= (d[9]&0xFFFF)<<16 ;
789 
790  u_int reg[2] ;
791 
792  reg[0] = d[10]&0xFFFF ;
793  reg[0] |= (d[11]&0xFFFF)<<16 ;
794  reg[1] = d[12]&0xFFFF ;
795  reg[1] |= (d[13]&0xFFFF)<<16 ;
796 
797  char s_all[64] ;
798  strcpy(s_all,hwicap_version(v_all)) ;
799 
800  LOG(INFO,"%d: FEE %2d[%02d,%d]: v_all 0x%08X[%s], v_bit 0x%08X[%s], wire1 0x%08llX, padplane %02d",rdo1,fee_ix,rdo_port,fee_id,
801  v_all,s_all,v_bit,hwicap_version(v_bit),wire1,fee_pp) ;
802 
803 
804  if(fee_ix!=rdo_port || fee_pp!=fee_id) {
805  LOG(ERR,"%d: fee_ix %d but read %d (fee_pp expect %d, read %d)",rdo1,fee_ix,rdo_port,fee_pp,fee_id) ;
806  }
807 
808  LOG(NOTE," regs 0x%08X 0x%08X",reg[0],reg[1]) ; // don't care that much
809 
810  if(sampa_stat[0]||sampa_stat[1]) {
811  LOG(ERR," SAMPA stat: 0x%04X 0x%04X",sampa_stat[0],sampa_stat[1]) ;
812  }
813 
814  // advance to the end, ignore ASCII stuff, who cares...
815  while(d<trl) {
816  if((d[0]&0xF0000000)==0x40000000) break ;
817  d++ ;
818  }
819 
820  }
821 
822  return d ; // leave at 0x4.....
823 }
824 
825 
826 u_int *itpc23::fee_scan(u_int *start)
827 {
828  u_int *d = start ;
829  u_int *d_save = start ;
830 
831  bx_count = -1 ;
832 
833  fee_evt_type = 0 ;
834  fee_pp = 0 ;
835 
836  if(d_save>=trl) return start ; // we are done -- don't move the return pointer
837 
838  // we must be at 0x8....
839  if((d[0]&0xF0000000)!=0x80000000) { // start of fee
840  err |= 0x10000 ; // oopsy -- what now!?
841  if(online || mode) LOG(ERR,"%d: T %d: fee_scan %d: not start-of-FEE 0x%08X",rdo1,token,fee_ix,d[0]) ;
842  }
843  else {
844  if(d[0]&0x00800000) { // from real FEE
845  err |= 0x20000 ;
846  if(online || mode) LOG(ERR,"%d: fee_scan %d: SAMPA overrun 0x%08X",rdo1,fee_ix,d[0]) ;
847  }
848  if(d[0]&0x00400000) { // from real FEE: xoff was on
849  //LOG(WARN,"fee_scan %d: XOFF on 0x%08X",fee_ix,d[0]) ;
850  }
851  }
852 
853  fee_evt_type = d[0] & 0xFF ;
854  fee_pp = (d[0]>>16)&0xFF ; // padplane id; aka fee_id
855 
856  LOG(DBG,"FEE %d = 0x%08X",fee_ix,d[0]) ;
857 
858  if(log_level>=2) LOG(TERR,"%d: FEE %d (0x%08X) fee_padplane %d, fee_evt_type 0x%02X",rdo1,fee_ix,d[0],fee_pp,fee_evt_type) ;
859 
860  d++ ; // done with header
861 
862 
863  if(fee_evt_type==0xF0) { // physics trigger, have sampa
864  for(int i=0;i<4;i++) {
865  lane_ix = i ;
866  d = lane_scan(d) ;
867  }
868  }
869  else { // non-physics trigger... typically send_config stuff
870  LOG(WARN,"%d: T %d: non-physics fee_ix %d, padplane %d",rdo1,token,fee_ix,fee_pp) ;
871  d = fee_non_trgd(d) ;
872  }
873 
874 
875  if((d[0]&0xF0000000)!=0x40000000) {
876  err |= 0x40000 ; // oopsy -- what now!?
877  if(online || mode) LOG(ERR,"%d: T %d: fee_scan %d: not end-of-FEE 0x%08X",rdo1,token,fee_ix,d[0]) ;
878  }
879  else {
880  if(d[0]&0x00800000) {
881  err |= 0x80000 ;
882  if(online || mode) LOG(ERR,"fee_scan %d: SAMPA overrun 0x%08X",fee_ix,d[0]) ;
883  }
884  if(d[0]&0x00400000) {
885  //LOG(WARN,"fee_scan %d: XOFF on 0x%08X",fee_ix,d[0]) ;
886  }
887  }
888 
889  d++ ;
890 
891 #if 0
892  if(fee_errs) {
893  for(int i=0;i<(d-d_save);i++) {
894  printf("fee_ix %2d: %d = 0x%08X\n",fee_ix,i,d_save[i]) ;
895  }
896  }
897 #endif
898 
899  return d ;
900 }
901 
902 int itpc23::rdo_scan(char *c_addr, int iwords)
903 {
904  u_int l_fee_mask ;
905 
906  words = iwords ;
907 
908  u_int *d = (u_int *)c_addr ;
909 
910  trl = d + words ;
911 
912  // skip TEF header
913  d += 4 ;
914  d_start = d ; // remember
915 
916  err = 0 ; // clear class error
917  //evt++ ;
918 
919  fee_ix = 0 ;
920  prog_fulls = 0 ;
921 
922  // now at 0xCCCC001C
923  // if 0xCCCC001C -- FY23 format
924  // if 0x001CCCCC -- FY22 format
925  if(d[0]==0xCCCC001C || d[0]==0x001CCCCC) ; // ALL ok
926  else {
927  LOG(ERR,"%d: evt %d: bad header 0x%08X, words %d",rdo1,evt,d[0],words) ;
928  for(int i=-4;i<=2;i++) {
929  LOG(ERR," %d = 0x%08X",i,d[i]) ;
930  }
931 
932  err |= 0x1 ;
933  }
934 
935  //1: event type, version, sector-id
936  //2: trigger
937  //3: event start 1 MHz counter
938  //4: FEE status: synced|overrun
939  //5: some status: prog_full|misc_busy_stuff
940  //6: another status: 0|fee_empty
941 
942  trg_cmd = (d[2]>>0)&0xF ;
943  daq_cmd = (d[2]>>4)&0xF ;
944 
945 
946  // unwrap token
947  {
948  u_short t_hi = (d[2]>>8)&0xF ;
949  u_short t_mid = (d[2]>>12)&0xF ;
950  u_short t_lo = (d[2]>>16)&0xF ;
951 
952  token = (t_hi<<8)|(t_mid<<4)|t_lo ;
953  }
954 
955 
956  if(log_level>=1) LOG(TERR,"%d: T %d(%d,%d)",rdo1,token,trg_cmd,daq_cmd) ;
957 
958  if(log_level>=10) {
959  for(int i=0;i<8;i++) {
960  LOG(TERR,"rdo_scan %d/%d = 0x%08X",i,words,d[i]) ;
961  }
962  }
963 
964  u_int mhz_start = d[3] ;
965  u_int fee_synced = d[4]>>16 ;
966  u_int fee_overrun = d[4]&0xFFFF ;
967  u_int fee_xoff = d[5]>>16 ; // actually prog_full
968  u_int rdo_stuff = d[5]&0xFFFF ;
969  u_int fee_empty = d[6]&0xFFFF ;
970 
971 
972  l_fee_mask = 0 ;
973  for(int i=7;i<15;i++) {
974  if((d[i]&0xFFFF0000)==0xF0000000) {
975  l_fee_mask = d[i]&0xFFFF ;
976  break;
977  }
978  }
979 
980  if(l_fee_mask==0) {
981  LOG(ERR,"%d: no local FEE mask, expecting 0x%04X",rdo1,fee_mask) ;
982  }
983  else {
984 // LOG(TERR,"%d: local FEE mask 0x%04X, expect 0x%04X",rdo1,l_fee_mask,fee_mask) ;
985 // fee_mask = l_fee_mask ;
986  }
987 
988  // I need a special hack here when running in Offline (from a file)
989  // because I might have a FEE masked in online...
990  if(!online) {
991 // fee_mask = fee_synced ;
992  fee_mask = l_fee_mask ;
993  }
994 
995 // LOG(TERR,"fee_mask 0x%X, fee_synced 0x%X, fee_overrun 0x%X, fee_xoff 0x%X, rdo_stuff 0x%X, fee_empty 0x%X, sig 0x%X",
996 // fee_mask,fee_synced,fee_overrun,fee_xoff,rdo_stuff,fee_empty,sig) ;
997 
998  if((fee_synced&fee_mask)!=fee_mask) {
999  if(mode || (online)) LOG(ERR,"%d: evt %d: fee sync error 0x%04X, expect 0x%04X",rdo1,evt,fee_synced,fee_mask) ;
1000  // STOP: auto-recovery
1001  err |= 0x10 ;
1002  }
1003 
1004  if(fee_overrun&fee_mask) {
1005  if(mode || online) {
1006  LOG(ERR,"%d: %d: RDOs fee FIFO overrun 0x%04X: words %d: 0x%04X 0x%04X 0x%04X 0x%04X",
1007  rdo1,evt,fee_overrun&fee_mask,words,
1008  fee_mask,l_fee_mask,fee_xoff,fee_empty) ;
1009  }
1010  // STOP: auto-recovery
1011  err |= 0x10 ;
1012  }
1013 
1014  if((fee_xoff&fee_mask) != 0) {
1015  //LOG(WARN,"fee_xoff 0x%04X",fee_xoff&fee_mask) ;
1016  // note as interesting
1017  }
1018 
1019  if(rdo_stuff & 0xF000) { // revisit this... what is it?
1020  LOG(NOTE,"%d: rdo_stuff 0x%04X",rdo1,rdo_stuff) ;
1021  }
1022 
1023 
1024  // revisit this...
1025  if((fee_empty&fee_mask)==fee_mask) ; // I expect it to be empty
1026  else {
1027  //if(!fee_words) LOG(WARN,"fee_empty 0x%04X",fee_empty&fee_mask) ;
1028  }
1029 
1030 
1031  // go to the end
1032  int got_it = 0 ;
1033  for(int i=0;i>-35;i--) {
1034 // LOG(TERR," %d = 0x%08X",i,trl[i]) ;
1035 
1036  if(trl[i]==0xDEADC0DE) got_it |=1 ;
1037  else if(got_it && (trl[i]==0xFEEDC0FE)) {
1038  got_it |= 2 ;
1039  trl += i - 1 ; // at the last datum
1040  break ;
1041  }
1042  }
1043 
1044  if(got_it != 3) {
1045  if(mode || online) {
1046  LOG(ERR,"%d: evt %d: no trailer (0x%08X), %d, words %d",rdo1,evt,trl[0],got_it,words) ;
1047 // LOG(ERR," 0x%X 0x%X 0x%X",trl[1],trl[2],trl[3]) ;
1048  }
1049  // STOP: auto-recovery
1050  err |= 0x2 ;
1051 
1052 // for(int i=(words-100);i<(words+100);i++) {
1053 // LOG(ERR," %d = 0x%08X",i,d_start[i]) ;
1054 // }
1055  }
1056 
1057  trl -= 1 ;
1058  u_int evt_status = trl[0] ;
1059  u_int mhz_end = trl[1] ;
1060 
1061 
1062  // happens, why?
1063  if(evt_status==0x0EEDC0DE) {
1064  for(int i=-8;i<=8;i++) {
1065  if(online || mode) LOG(ERR,"%d: %d = 0x%08X",rdo1,i,trl[i]) ;
1066  }
1067  }
1068 
1069 // LOG(TERR,"trl0 0x%08X, trl1 0x%08X",trl[0],trl[1]) ;
1070 
1071  u_int evt_type = (d[1]>>28)&0xF ;
1072 
1073 
1074  int trg_cou = 0 ;
1075  int loc_err_cou = 0 ;
1076 
1077  switch(evt_type) {
1078  case 1 : // timer
1079  token = 4096 ;
1080  trg_cmd = 0 ;
1081  daq_cmd = 0 ;
1082  goto done ;
1083  case 2 : // trigger!
1084  evt_trgd++ ;
1085  f_stat.evt_cou++ ;
1086  break ;
1087  default :
1088  LOG(ERR,"%d: %d: unknown event type %d: 0x%08X",rdo1,evt,evt_type,d[1]) ;
1089  err |= 0x4 ;
1090  goto done ;
1091  break ;
1092  }
1093 
1094 
1095 
1096  for(int i=0;i<16;i++) {
1097  if(fee_mask & (1<<i)) ;
1098  else continue ;
1099 
1100  u_int st = (evt_status>>(i*2)) & 0x3 ;
1101 
1102  if(st != 3) {
1103  err |= 0x1000 ;
1104  if(mode || (online && run_errors<10)) LOG(ERR,"%d: %d: FEE %2d: timeout 0x%X [0x%08X]",rdo1,evt,i,st,evt_status) ;
1105  }
1106  }
1107 
1108  // continue with data
1109  d += 7 ; // should be at the trigger FIFO
1110  while((*d>>28)==0x4) { // skip data from Trigger FIFO because we don't care much
1111  trg_cou++ ;
1112  d++ ;
1113  }
1114 
1115  if(trg_cou>8) {
1116  LOG(WARN,"Lots of triggers %d",trg_cou) ;
1117  }
1118 
1119  if(log_level>=1) LOG(TERR,"%d: evt %d: fee_mask expected 0x%04X",rdo1,evt,fee_mask) ;
1120 
1121  // should be at the FEE start: 0xF000_mmmm
1122  // THIS IS THE CANONICAL MASK AS SET BY THE RDO DURING RUNNING
1123  // AND SHOULD BE USED OFFLINE
1124  if(((*d>>28)!=0xF)||((*d&0xFFFF)!=fee_mask)) {
1125  if(mode || (online && run_errors<10)) LOG(ERR,"%d: evt %d: Bad FEE_START 0x%08X, expect 0x%08X",rdo1,evt,*d,0xF0000000|fee_mask) ;
1126  err |= 0x20 ;
1127  goto done ;
1128  }
1129 
1130 
1131  d++ ; // move to start-of-FEE bank
1132 
1133 
1134  if(fee_words) goto done ; // emulation: skip scans
1135 
1136 #if 0
1137  printf("==== trg_evts %d\n",trgd_evt) ;
1138  for(int i=0;i<(trl-d);i++) {
1139  printf("%d = 0x%08X\n",i,d[i]) ;
1140  }
1141  fflush(stdout) ;
1142 #endif
1143 
1144 // if(run_type==1 || run_type==5) {
1145 // pthread_mutex_lock(&peds_mutex) ;
1146 // }
1147 
1148  if(log_level>=2) LOG(TERR,"here") ;
1149 
1150 // LOG(TERR,"%d: fee_mask 0x%08X",rdo1,fee_mask) ;
1151 
1152 
1153  if(err) {
1154  if(mode || online) {
1155  LOG(ERR,"%d: T %d: error 0x%X before fee_scan??",rdo1,token,err) ;
1156  }
1157  }
1158 
1159 
1160 
1161  for(int i=0;i<16;i++) {
1162  if(fee_mask & (1<<i)) ;
1163  else continue ;
1164 
1165  fee_ix = i ;
1166  d = fee_scan(d) ;
1167  if(err) {
1168  // LOG first FEE which failed
1169  if(loc_err_cou==0) {
1170  if(mode || online) {
1171  LOG(ERR,"%d: T %d: error at FEE #%d (0x%X)",rdo1,token,i+1,err) ;
1172  }
1173  }
1174  loc_err_cou++ ;
1175  }
1176  if(d>=trl) break ;
1177  }
1178 
1179  if(log_level>=2) LOG(TERR,"here2") ;
1180 
1181 // if(run_type==1 || run_type==5) {
1182 // pthread_mutex_unlock(&peds_mutex) ;
1183 // }
1184 
1185 
1186 
1187  done:;
1188 
1189 
1190 
1191  if(err||prog_fulls) {
1192  if(online || mode) LOG(ERR,"%d: evt %d/%d: T %d,%d,%d: error 0x%08X, prog_fulls %d: words %d, %d us",rdo1,evt_trgd,evt,
1193  token,trg_cmd,daq_cmd,
1194  err,
1195  prog_fulls,
1196  words,mhz_end-mhz_start) ;
1197  }
1198  else if(token==4096) {
1199  LOG(DBG,"%d/%d: T %d,%d,%d: error 0x%06X, prog_fulls %d, rdo_stuff 0x%04X: words %d, %d us",evt_trgd,evt,
1200  token,trg_cmd,daq_cmd,
1201  err,
1202  prog_fulls,rdo_stuff,
1203  words,mhz_end-mhz_start) ;
1204  }
1205  else if((evt_trgd%1000)==1) {
1206  if(log_level>=1) {
1207  LOG(TERR,"%d/%d: T %d,%d,%d: error 0x%06X, prog_fulls %d, rdo_stuff 0x%04X: words %d, %d us",evt_trgd,evt,
1208  token,trg_cmd,daq_cmd,
1209  err,
1210  prog_fulls,rdo_stuff,
1211  words,mhz_end-mhz_start) ;
1212  }
1213 
1214  }
1215  else {
1216  LOG(NOTE,"%d/%d: T %d,%d,%d: error 0x%06X, prog_fulls %d, rdo_stuff 0x%04X: words %d, %d us",evt_trgd,evt,
1217  token,trg_cmd,daq_cmd,
1218  err,
1219  prog_fulls,rdo_stuff,
1220  words,mhz_end-mhz_start) ;
1221 
1222  }
1223 
1224  return err ; // 0 is no error
1225 }
1226 
1227 
1228 
1229 
1230 u_int itpc23::get_token_s(char *c_addr, int words)
1231 {
1232  u_int *d = (u_int *)c_addr ;
1233  int t, trg, daq ;
1234 
1235  t = 4097 ;
1236  trg = 0 ;
1237  daq = 0 ;
1238 
1239 // for(int i=0;i<32;i++) {
1240 // LOG(TERR,"get_token_s: %d/%d = 0x%08X",i,words,d[i]) ;
1241 // }
1242 
1243 
1244  u_int sig, trg_w,sub ;
1245  u_int fmt23 ;
1246 // if(d[4]==0xCCCC001C) {
1247  if(d[4]==0xCCCC001C && fmt<23) {
1248  sig = sw16(d[5]) ;
1249  trg_w = sw16(d[6]) ;
1250  sub = sw16(d[7]) ;
1251  }
1252  else {
1253  sig = d[5] ;
1254  trg_w = d[6] ;
1255  sub = d[7] ;
1256  }
1257 
1258 // LOG(TERR,"0x%08X: 0x%08X 0x%08X 0x%08X",d[4],sig,trg_w,sub) ;
1259 
1260  if((sig&0xFF000000)==0x98000000) {
1261  fmt23 = 0 ;
1262  }
1263  else {
1264  fmt23 = 23 ;
1265  }
1266 
1267  if(fmt23>22) {
1268  int evt_type ;
1269 
1270  // unwrap token
1271  t = 0xFFF ;
1272  {
1273  u_short t_hi = (trg_w>>8)&0xF ;
1274  u_short t_mid = (trg_w>>12)&0xF ;
1275  u_short t_lo = (trg_w>>16)&0xF ;
1276 
1277  t = (t_hi<<8)|(t_mid<<4)|t_lo ;
1278  }
1279 
1280  trg = (trg_w>>0)&0xF ;
1281  daq = (trg_w>>4)&0xF ;
1282 
1283  evt_type = (sig>>28)&0xF ;
1284 
1285  if(evt_type==1) { // timer
1286  t = 4096 ;
1287  trg = 0 ;
1288  daq = 1 ;
1289  }
1290 
1291  }
1292  else {
1293 
1294 #if 0
1295  d += 4 ; // skip header
1296  words -= 4 ;
1297 
1298  for(int i=0;i<16;i++) {
1299  if(d[i] == 0xCCCC001C || d[i]==0x001CCCCC) {
1300  d = d + i ;
1301  words-- ;
1302  break ;
1303  }
1304  }
1305 #endif
1306 
1307 
1308 // for(int i=0;i<32;i++) {
1309 // LOG(TERR,"%d/%d = 0x%08X",i,words,d[i]) ;
1310 // }
1311 
1312 
1313  int rdo_version = 0 ;
1314 
1315  if(sig==0x98000004) rdo_version = 0 ;
1316  else if((sig&0xFF00000F)==0x98000004) rdo_version = (sig>>4)&0xFF ;
1317  else {
1318  LOG(WARN,"%d: fmt 22: not triggered: ds 0x%08X, words",rdo1,sig,words) ;
1319  t = 4096 ;
1320  goto done ;
1321  }
1322 
1323 
1324 
1325 
1326 // if(trg_w==0) {
1327 // if(rdo_version==1) {
1328 // if(sub==0x980000FC) {
1329 // LOG(WARN,"%d: RDO_mon, words %d",rdo1,words) ;
1330 // }
1331 // }
1332 // }
1333 
1334 
1335  t = ((trg_w>>8)&0xF)<<8 ;
1336  t |= ((trg_w>>12)&0xF) << 4 ;
1337  t |= ((trg_w>>16)&0xF) ;
1338 
1339  trg = trg_w & 0xF ;
1340  daq = (trg_w>>4) & 0xF ;
1341 
1342 // LOG(TERR,"%d: rdo_version %d, trg_fired 0x%08X: T %d, trg %d:%d",rdo1,rdo_version,trg_fired,t,trg,daq) ;
1343 
1344  if(trg_w==0) {
1345  t = 4097 ;
1346  trg = 0 ;
1347  daq = 0 ;
1348  goto done ;
1349  }
1350 
1351 
1352  }
1353 
1354  done:;
1355 
1356 // LOG(TERR,"T %d, trg %d:%d",t,trg,daq) ;
1357 
1358 
1359 
1360  return (trg<<16)|(daq<<12)|t ;
1361 }
1362 
1363 
1364 itpc23::itpc23()
1365 {
1366 // LOG(TERR,"%s",__PRETTY_FUNCTION__) ;
1367 
1368  rts_id = ITPC_ID ;
1369 
1370  if(rp_gain_itpc==0) {
1371  rp_gain_itpc = (row_pad_t (*)[ROW_MAX+1][PAD_MAX+1]) malloc(sizeof(row_pad_t)*24*(ROW_MAX+1)*(PAD_MAX+1)) ;
1372 
1373  // inititalize here!
1374  // initialize here!
1375  for(int s=0;s<24;s++) {
1376  for(int r=0;r<=ROW_MAX;r++) {
1377  for(int p=0;p<=PAD_MAX;p++) {
1378  rp_gain_itpc[s][r][p].gain = 1.0 ;
1379  rp_gain_itpc[s][r][p].t0 = 0.0 ;
1380  rp_gain_itpc[s][r][p].flags = 0 ;
1381  }}}
1382 
1383 
1384  }
1385 
1386  rp_gain = rp_gain_itpc ;
1387 
1388 // if(rp_gain==0) {
1389 // rp_gain = (row_pad_t (*)[ROW_MAX+1][PAD_MAX+1]) malloc(sizeof(row_pad_t)*24*(ROW_MAX+1)*(PAD_MAX+1)) ;
1390 // }
1391 
1392  row_min = 1 ;
1393  row_max = 40 ;
1394 
1395  for(int row=1;row<=40;row++) rowlen[row] = itpc_rowlen[row] ;
1396 
1397  data_c = 0 ;
1398 
1399  fmt = 0 ;
1400 
1401  fee_words = 0 ;
1402 
1403 }
1404 
1405 
1406 itpc23::~itpc23()
1407 {
1408 // LOG(TERR,"%s",__PRETTY_FUNCTION__) ;
1409 
1410  return ;
1411 }
1412 
1413 u_char itpc23::flags_row_pad(int asic, int channel, int &row, int &pad)
1414 {
1415  int id, sampa ;
1416 
1417  id = asic>>1 ; // FEE padplane id
1418  sampa = asic & 1 ;
1419 
1420  itpc_sampa_to_rowpad(id,sampa,channel,row,pad) ;
1421  if(row==0 || row==255) return 0xFF ;
1422  if(pad==0 || pad==255) return 0xFF ;
1423 
1424 
1425  return rp_gain[sector1-1][row][pad].flags ;
1426 }
1427 
1428 
1429 static const char *hwicap_version(u_int v)
1430 {
1431  static char ascii[64] ;
1432 
1433  int s = v & 0x3F ;
1434  int m = (v>>6)&0x3F ;
1435  int h = (v>>12)&0x1F ;
1436  int y = ((v>>17)&0x3F) ;
1437  int mo = (v>>23)&0xF ;
1438  int d = (v>>27)&0x1F ;
1439 
1440 
1441  sprintf(ascii,"%02d-%02d-%02d %02d:%02d:%02d",
1442  mo,d,y,h,m,s) ;
1443 
1444  return ascii ;
1445 }
1446 
1447 
1448 //static const int itpc_fee_map[24][4][16] = {
1449 static int itpc_fee_map[24][4][16] = {
1450 {//S1 checked
1451  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1452  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35}, //ok
1453  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1454  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1455 },
1456 {//S2 checked
1457  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1458  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1459 //usual { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1460 // { 7, 1,17,12,24, 0,13, 8,28, 2,19,20,29,25,21, 3}, // moved #6 to #11
1461  { 7, 1, 0,12,24,17,13, 8,28, 2,19,20,29,25,21, 3}, // moved #6 to #11; and #3 to #6
1462  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1463 },
1464 {//S3 checked
1465  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1466  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1467  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1468  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1469 
1470 },
1471 {//S4 checked
1472  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1473  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1474  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1475  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1476 
1477 },
1478 {//S5 checked
1479  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1480  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1481  { 7, 1,17,12,24,19,13, 8,28, 2, 3,20,29,25,21, 0}, // 17May23: moved 16 to 11
1482  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1483 
1484 },
1485 {//S6 checked
1486  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1487  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1488  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1489  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1490 
1491 },
1492 {//S7 checked
1493  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1494  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1495  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1496  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1497 
1498 },
1499 {//S8 mess with mapping
1500  {49,52,46, 0, 0, 54,0,47, 0,50,48,55, 0, 0,51,53}, //FY21: bad port #13 on RDO ID 0x0052ED7C moved to #11
1501  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1502  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1503  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1504 
1505 },
1506 {//S9 mess with mapping
1507  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1508  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1509  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1510  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1511 
1512 },
1513 {//S10 checked
1514  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1515  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1516  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1517  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1518 
1519 },
1520 {//S11
1521 // {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53}, // usual
1522  {49,52,46,47, 0, 54,0, 0, 0,50, 0,55,48, 0,51,53}, // new: bad port #8 on RDO ID 0x0052F5EA, moved to #4
1523  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1524  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1525  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1526 
1527 },
1528 {//S12
1529  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1530  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1531  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1532  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1533 
1534 },
1535 {//S13
1536  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1537  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1538  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1539  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1540 },
1541 {//S14
1542  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1543  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1544  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1545  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1546 },
1547 {//S15
1548  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1549  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1550  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1551  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1552 },
1553 {//S16
1554  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1555  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1556  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1557  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1558 },
1559 {//S17
1560 // {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53}, // 29Mar03: bad port 3 moved to good port 5
1561  {49,52, 0, 0,46, 54,0,47, 0,50, 0,55,48, 0,51,53},
1562  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1563  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1564  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1565 },
1566 {//S18
1567  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1568  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1569  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1570  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1571 },
1572 {//S19
1573  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1574  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1575  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1576  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1577 },
1578 {//S20
1579  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1580  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1581  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1582  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1583 },
1584 {//S21
1585 // {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1586  {49,52,46, 0, 0,54,47, 0, 0,50, 0,55,48, 0,51,53}, // moved #8 to #7
1587  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1588  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1589  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1590 },
1591 {//S22
1592  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1593  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1594  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1595  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1596 },
1597 {//S23
1598  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1599  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1600  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1601  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1602 },
1603 {//S24
1604  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1605  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1606  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1607  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1608 },
1609 } ;
1610 
1611 
1612 // I could optimize this into an array on the first call
1613 static u_int get_ifee_mask(int sec1, int rdo1)
1614 {
1615  u_int mask = 0 ;
1616 
1617  for(int i=0;i<16;i++) {
1618  if(itpc_fee_map[sec1-1][rdo1-1][i]) mask |= (1<<i) ;
1619  }
1620 
1621  return mask ;
1622 }
1623 
1624 void itpc23::itpc_fee_kill(int s0, int r0, int p0)
1625 {
1626  itpc_fee_map[s0][r0][p0] = 0 ;
1627 }