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: ch_scan %d:%d:%d: pkt %d, sampa %d:%d, words10 %d [0x%08X: 0x%08X 0x%08X], err 0x%X",rdo1,fee_ix,lane_ix,
378  ch_ix,
379  pkt,sampa_id,sampa_ch,words10,
380  d[0],d[-1],d[1],err) ;
381 
382 // LOG(ERR,"err 0x%08X",err) ;
383 
384  //int ppk[2] ;
385 
386  //ppk[0] = (((d[-1]>>20)&0x3FF)>>7)&0x7 ;
387  //ppk[1] = (((d[1]>>20)&0x3FF)>>7)&0x7 ;
388 
389  //LOG(ERR,"%d %d",ppk[0],ppk[1]) ;
390  //d++ ;
391  //goto retry_fix ;
392 
393  }
394  if(d<trl) {
395  d++ ;
396  goto retry_fix ;
397  }
398  else {
399  if(mode || online) LOG(ERR,"Can't fix -- giving up") ;
400 // return 0 ;
401  }
402  }
403  else if(is_error) {
404  if(mode || (online && run_errors<20)) LOG(WARN,"Recovered %d:%d, words10 %d",sampa_id,sampa_ch,words10) ;
405  //err ^= 0x1000000 ;
406  is_error = 0 ;
407  }
408 
409  int bx = ((w[4]&0x1FF)<<17)|(w[3]<<1)|((w[2]>>9)&1) ;
410 
411  if(unlikely(bx_count<0)) { // first channel of the FEE
412  bx_count = bx ;
413  }
414  else {
415  if(unlikely(bx != bx_count)) {
416  if(abs(bx-bx_count)>1) {
417  err |= 0x2000000 ;
418  run_errors++ ;
419  if(mode || (online && run_errors<10)) {
420  LOG(ERR,"%d: ch_scan %d:%d: bx %d, expect %d",rdo1,fee_ix,ch_ix,bx,bx_count) ;
421  }
422  }
423  }
424  }
425 
426 
427  int words10_start = words10 ; // remember
428 
429  while(words10%3) words10++ ; // align on 32bit word
430 
431  int words = words10/3 ; // and then count them...
432 
433  d += 2 ; // move from channel header...
434 
435  int ix = 0 ;
436  int a_ix = 0 ;
437  int tb_cou = 0 ;
438  int tb_start = 0 ;
439  int tb_last = -1 ;
440  int w10 = 0 ;
441 
442  u_short *d_start = s1_dta + last_ix ;
443  struct seq_t *seq = 0 ;
444  u_short *dd = s1_dta + last_ix ;
445  u_short *dd_save = dd ;
446 
447  int seq_ix = 0 ;
448 
449  // craft id
450  int id = (fee_pp<<1)|(sampa_id&1) ;
451  int flags = flags_row_pad(id, sampa_ch, row, pad) ; // also gets row,pad from id sampa_ch
452 
453  if(log_level>=2) {
454  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,
455  sampa_id,sampa_ch,row,pad,flags) ;
456  }
457 
458 
459 // 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,
460 // sampa_id,sampa_ch,row,pad,flags) ;
461 
462 
463  // skip non-wanted rows and pads
464  if(flags==0xFF) {
465  goto done_ch ;
466  }
467 
468  seq = s1[row][pad].seq ;
469 
470  if(log_level>=2) LOG(TERR,"Here %p, words %d, %p",seq,words,dd) ;
471 
472  // now dump the data out...
473 
474  for(int i=0;likely(i<words);i++) {
475  w[0] = (d[i]>>20)&0x3FF ;
476  w[1] = (d[i]>>10)&0x3FF ;
477  w[2] = (d[i]>>00)&0x3FF ;
478 
479  // it goes
480  // tb_cou, tb_start, adc, adc, adc x tb_cou times
481  // from low tb_start to high
482  if(unlikely(d[i]&0xC0000000)) {
483  run_errors++ ;
484  if(mode || (online && run_errors<10)) {
485  LOG(ERR,"%d: ch_scan %d:%d: SAMPA %d:%d: bad word 0x%08X",rdo1,fee_ix,ch_ix,
486  sampa_id,sampa_ch,d[i]) ;
487  }
488  }
489 
490  if(log_level>=2) LOG(TERR,"FEE %d:%d -- %d = 0x%08X",fee_ix,ch_ix,i,d[i]) ;
491 
492 
493  for(int j=0;likely(j<3);j++) {
494  w10++ ;
495 
496  switch(ix) {
497  case 0 :
498  tb_cou = w[j] ; // actual count of ADCs
499 
500  if(log_level>=100) LOG(TERR," tb_cou %d %p",tb_cou,dd) ;
501 
502  *dd++ = tb_cou ;
503 
504  if(log_level>=100) LOG(TERR," tb_cou %d",tb_cou) ;
505 
506  if(unlikely(tb_cou>500)) {
507  run_errors++ ;
508  if(mode || (online && run_errors<10)) {
509  LOG(ERR,"%d: rp %d:%d: tb_cou %d [0x%08X,%d]",rdo1,row,pad,tb_cou,d[i],i) ;
510  }
511  }
512  ix = 1 ;
513  break ;
514  case 1 :
515  tb_start = w[j] ; // which is tb_lo
516  *dd++ = tb_start ;
517 
518  if(seq_ix>=(SEQ_MAX-1)) {
519  if(mode || online) LOG(ERR,"too many seqs %d",seq_ix) ;
520  goto done_ch ;
521  }
522 
523  //printf("seq_ix %d: %d %d = %d %d\n",seq_ix,row,pad,tb_start,tb_cou) ;
524 
525 
526  //LOG(TERR,"DDD %d %d %d",tb_start,tb_cou,tb_start+tb_cou-1) ;
527 
528  seq[seq_ix].t_lo = tb_start ;
529  seq[seq_ix].t_hi = tb_start + tb_cou - 1 ;
530  seq[seq_ix].dta_p = (dd-d_start) ; // where is this sequence...
531  seq[seq_ix].blob_id = 0 ;
532  seq_ix++ ;
533 
534  //dd += tb_cou ; // this doesn't sound correct!!!
535 
536  if(unlikely(log_level>=100)) LOG(TERR," tb_start %d",tb_start) ;
537 
538  if(unlikely(tb_start<=tb_last)) {
539  run_errors++ ;
540  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) ;
541  }
542 
543 
544 
545  tb_last = tb_start + tb_cou ;
546  if(unlikely(tb_last>500)) {
547  run_errors++ ;
548  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) ;
549  }
550 
551 
552 
553  ix = 2 ;
554  break ;
555  default :
556  //adc[a_ix] = w[j] ;
557  if(log_level>=100) LOG(TERR," adc %d, %d",w[j],a_ix) ;
558  a_ix++ ;
559  *dd++ = w[j] ; // store ADC
560 
561 
562  //printf(" a_ix %d, adc %d\n",a_ix,w[j]) ;
563 
564  if(unlikely(a_ix==tb_cou)) { // sequence done!
565  tb_last = -1 ;
566  ix = 0 ;
567  a_ix = 0 ;
568  if(w10==words10_start) goto done_ch ;
569  }
570  break ;
571  }
572  }
573 
574  if(log_level>=2) LOG(TERR,"Here %d",__LINE__) ;
575 
576 // printf("%d:%d %d: %d %d %d\n",fee_ix,ch_ix,i,w[0],w[1],w[2]) ;
577 
578  }
579 
580  done_ch :;
581 
582  if(seq) {
583  sequence_cou += seq_ix ;
584  seq[seq_ix].t_hi = -1 ;
585  s1[row][pad].ix = last_ix ;
586 
587 
588  // data_c will exist in either: pedestal/pulser runs OR in the daqReader
589 
590  if(data_c) {
591  u_short *dd = dd_save ;
592 
593  int ii = lane_ix/2 ;
594  int ch = ii*32 + sampa_ch ;
595 
596  if(log_level>=2) {
597  LOG(TERR,"fee_pp %d, fee_ix %d, lane_ix %d, sampa_ch %d, ch %d",
598  fee_pp,fee_ix,lane_ix,sampa_ch,ch) ;
599  }
600 
601 
602 
603  data_c->sector = sector1 -1 ;
604  data_c->rdo = rdo1-1 ;
605  data_c->port = fee_ix ;
606  data_c->fee_id = fee_pp ;
607 
608  data_c->ch_start(ch) ;
609 
610 
611  for(int i=0;i<seq_ix;i++) {
612  dd += 2 ;
613  int t_len = seq[i].t_hi - seq[i].t_lo + 1 ;
614 
615 // printf(" t_start %d, len %d\n",seq[i].t_lo,t_len) ;
616 
617  int ii = 0 ;
618  for(int j=0;j<t_len;j++) {
619  int adc = *dd++ ;
620  int tb = seq[i].t_lo + ii ;
621  //adc = (fee_ix+1)+100 ;
622  data_c->accum(sector1-1,rdo1-1,fee_ix,fee_pp,ch,tb,adc) ;
623  ii++ ;
624  }
625  }
626 
627  data_c->ch_done(0) ;
628  }
629 #if 0
630  {
631  u_short *dd = dd_save ;
632  for(int i=0;i<seq_ix;i++) {
633  dd += 2 ;
634  int t_len = seq[i].t_hi - seq[i].t_lo + 1 ;
635 
636  printf("RP %d:%d, seq %d: t_lo %d, t_hi %d\n",row,pad,i,seq[i].t_lo,seq[i].t_hi) ;
637 
638  int ii = 0 ;
639  for(int j=0;j<t_len;j++) {
640  int adc = *dd++ ;
641  int tb = seq[i].t_lo + ii ;
642 
643  printf(" tb %3d = %3d ADC\n",tb,adc);
644 
645  ii++ ;
646  }
647  }
648  }
649 #endif
650 
651  }
652 
653  last_ix += dd-d_start ;
654 
655  d += words ;
656 
657 
658 
659  return d ;
660 }
661 
662 u_int *itpc23::lane_scan(u_int *start)
663 {
664  u_int *d = start ;
665 
666  retry_fix:;
667 
668  if(log_level>=1) LOG(TERR,"%d: lane scan %d: 0x%08X",rdo1,lane_ix,d[0]) ;
669 
670  // should be at start of lane 0xB....
671  if((d[0]&0xF0000000)!=0xB0000000) { // start of lane
672  if((online && run_errors<10) || mode) {
673  LOG(ERR,"%d: lane_scan %d:%d: unknown start 0x%08X [0x%08X 0x%08X]",rdo1,fee_ix,lane_ix,d[0],d[-1],d[1]) ;
674  }
675 
676  if(d[0]==d[-1]) {
677  if(mode || (online && run_errors<10)) {
678  LOG(WARN,"%d: lane_scan %d:%d: retrying fix",rdo1,fee_ix,lane_ix) ;
679  }
680  d++ ;
681  goto retry_fix ;
682  }
683  else {
684  err |= 0x100000 ;
685  }
686 
687  }
688  else if((d[0]>>26)&0x3) { // SAMPA FIFOs overwritten!
689  err |= 0x200000 ;
690  if(online || mode) LOG(ERR,"%d: lane_scan %d:%d: SAMPA FIFO overwritten 0x%08X",rdo1,fee_ix,lane_ix,d[0]) ;
691  }
692 
693  d++ ; // skip 0xB....
694 
695  if(log_level>=1) LOG(TERR,"%d: lane scan %d: 0x%08X",rdo1,lane_ix,d[0]) ;
696 
697  for(int i=0;i<16;i++) {
698  ch_ix = i ;
699  d = ch_scan(d) ;
700  }
701 
702  // should be at end of lane 0x7....
703  if((d[0]&0xF0000000)!=0x70000000) { // end of lane
704  err |= 0x400000 ;
705  run_errors++ ;
706  if((online && run_errors<20)|| mode) LOG(ERR,"%d: lane_scan %d:%d: unknown end 0x%08X",rdo1,fee_ix,lane_ix,d[0]) ;
707  }
708 
709  d++ ; // skip 0x7...
710 
711  return d ;
712 }
713 
714 u_int *itpc23::fee_non_trgd(u_int *start)
715 {
716  u_int *d = start ;
717 
718  int fee_words = 0 ;
719 
720  if(fee_evt_type != 0x02) { // no clue
721  if(online || mode) LOG(ERR,"%d: fee_non_trgd %d: evt_type 0x%02X",rdo1,fee_ix,fee_evt_type) ;
722 
723 
724  while(d<trl) {
725  if((d[0]&0xF0000000)==0x40000000) {
726  break ;
727  }
728  d++ ;
729  fee_words++ ;
730  }
731  }
732  else {
733  LOG(NOTE,"fee_scan %d: evt_type 0x%02X, words %d",fee_ix,fee_evt_type,fee_words) ;
734 
735  // I am now at 0x6...
736  for(int i=0;i<16;i++) {
737  LOG(NOTE,"%d = 0x%08X",i,d[i]) ;
738  }
739 
740  d++ ; // I am now at 0xA...
741 
742 
743  d++ ; // I am now at data
744 
745  //0: shorts config version
746  //1: shorts rdo_port
747  //2: shorts fee_id
748  //3: shorts for_me(WTF)
749  int rdo_port = d[1]&0xFFFF ;
750  int fee_id = d[2]&0xFFFF ;
751 
752  d += 4 ; // skip blabbler
753 
754  u_short sampa_stat[2] ;
755 
756  sampa_stat[0] = d[0]&0xFFFF ;
757  sampa_stat[1] = d[1]&0xFFFF ;
758 
759  d += 2 ;
760 
761  d += 16 ; // zeros
762 
763  d += 2 ; // something
764 
765  u_int v_all = d[0]&0xFFFF ;
766  v_all |= (d[1]&0xFFFF)<<16 ;
767 
768  u_int v_bit = d[2]&0xFFFF ;
769  v_bit |= (d[3]&0xFFFF)<<16 ;
770 
771  unsigned long wire1 = d[4]&0xFFFF ;
772  wire1 |= (long)(d[5]&0xFFFF)<<16 ;
773  wire1 |= (long)(d[6]&0xFFFF)<<32 ;
774  wire1 |= (long)(d[7]&0xFFFF)<<48 ;
775 
776  wire1 >>= 8 ;
777  wire1 &= 0xFFFFFFFF ;
778 
779  u_int temp = d[8]&0xFFFF ;
780  temp |= (d[9]&0xFFFF)<<16 ;
781 
782  u_int reg[2] ;
783 
784  reg[0] = d[10]&0xFFFF ;
785  reg[0] |= (d[11]&0xFFFF)<<16 ;
786  reg[1] = d[12]&0xFFFF ;
787  reg[1] |= (d[13]&0xFFFF)<<16 ;
788 
789  char s_all[64] ;
790  strcpy(s_all,hwicap_version(v_all)) ;
791 
792  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,
793  v_all,s_all,v_bit,hwicap_version(v_bit),wire1,fee_pp) ;
794 
795 
796  if(fee_ix!=rdo_port || fee_pp!=fee_id) {
797  LOG(ERR,"%d: fee_ix %d but read %d (fee_pp expect %d, read %d)",rdo1,fee_ix,rdo_port,fee_pp,fee_id) ;
798  }
799 
800  LOG(NOTE," regs 0x%08X 0x%08X",reg[0],reg[1]) ; // don't care that much
801 
802  if(sampa_stat[0]||sampa_stat[1]) {
803  LOG(ERR," SAMPA stat: 0x%04X 0x%04X",sampa_stat[0],sampa_stat[1]) ;
804  }
805 
806  // advance to the end, ignore ASCII stuff, who cares...
807  while(d<trl) {
808  if((d[0]&0xF0000000)==0x40000000) break ;
809  d++ ;
810  }
811 
812  }
813 
814  return d ; // leave at 0x4.....
815 }
816 
817 
818 u_int *itpc23::fee_scan(u_int *start)
819 {
820  u_int *d = start ;
821  u_int *d_save = start ;
822 
823  bx_count = -1 ;
824 
825  fee_evt_type = 0 ;
826  fee_pp = 0 ;
827 
828  if(d_save>=trl) return start ; // we are done -- don't move the return pointer
829 
830  // we must be at 0x8....
831  if((d[0]&0xF0000000)!=0x80000000) { // start of fee
832  err |= 0x10000 ; // oopsy -- what now!?
833  if(online || mode) LOG(ERR,"%d: fee_scan %d: not start-of-FEE 0x%08X",rdo1,fee_ix,d[0]) ;
834  }
835  else {
836  if(d[0]&0x00800000) { // from real FEE
837  err |= 0x20000 ;
838  if(online || mode) LOG(ERR,"%d: fee_scan %d: SAMPA overrun 0x%08X",rdo1,fee_ix,d[0]) ;
839  }
840  if(d[0]&0x00400000) { // from real FEE: xoff was on
841  //LOG(WARN,"fee_scan %d: XOFF on 0x%08X",fee_ix,d[0]) ;
842  }
843  }
844 
845  fee_evt_type = d[0] & 0xFF ;
846  fee_pp = (d[0]>>16)&0xFF ; // padplane id; aka fee_id
847 
848  LOG(DBG,"FEE %d = 0x%08X",fee_ix,d[0]) ;
849 
850  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) ;
851 
852  d++ ; // done with header
853 
854 
855  if(fee_evt_type==0xF0) { // physics trigger, have sampa
856  for(int i=0;i<4;i++) {
857  lane_ix = i ;
858  d = lane_scan(d) ;
859  }
860  }
861  else { // non-physics trigger... typically send_config stuff
862  LOG(WARN,"%d: non-physics fee_ix %d, padplane %d",rdo1,fee_ix,fee_pp) ;
863  d = fee_non_trgd(d) ;
864  }
865 
866 
867  if((d[0]&0xF0000000)!=0x40000000) {
868  err |= 0x40000 ; // oopsy -- what now!?
869  if(online || mode) LOG(ERR,"%d: fee_scan %d: not end-of-FEE 0x%08X",rdo1,fee_ix,d[0]) ;
870  }
871  else {
872  if(d[0]&0x00800000) {
873  err |= 0x80000 ;
874  if(online || mode) LOG(ERR,"fee_scan %d: SAMPA overrun 0x%08X",fee_ix,d[0]) ;
875  }
876  if(d[0]&0x00400000) {
877  //LOG(WARN,"fee_scan %d: XOFF on 0x%08X",fee_ix,d[0]) ;
878  }
879  }
880 
881  d++ ;
882 
883 #if 0
884  if(fee_errs) {
885  for(int i=0;i<(d-d_save);i++) {
886  printf("fee_ix %2d: %d = 0x%08X\n",fee_ix,i,d_save[i]) ;
887  }
888  }
889 #endif
890 
891  return d ;
892 }
893 
894 int itpc23::rdo_scan(char *c_addr, int iwords)
895 {
896  u_int l_fee_mask ;
897 
898  words = iwords ;
899 
900  u_int *d = (u_int *)c_addr ;
901 
902  trl = d + words ;
903 
904  // skip TEF header
905  d += 4 ;
906  d_start = d ; // remember
907 
908  err = 0 ; // clear class error
909  //evt++ ;
910 
911  fee_ix = 0 ;
912  prog_fulls = 0 ;
913 
914  // now at 0xCCCC001C
915  // if 0xCCCC001C -- FY23 format
916  // if 0x001CCCCC -- FY22 format
917  if(d[0]==0xCCCC001C || d[0]==0x001CCCCC) ; // ALL ok
918  else {
919  LOG(ERR,"%d: evt %d: bad header 0x%08X, words %d",rdo1,evt,d[0],words) ;
920  for(int i=-4;i<=2;i++) {
921  LOG(ERR," %d = 0x%08X",i,d[i]) ;
922  }
923 
924  err |= 0x1 ;
925  }
926 
927  //1: event type, version, sector-id
928  //2: trigger
929  //3: event start 1 MHz counter
930  //4: FEE status: synced|overrun
931  //5: some status: prog_full|misc_busy_stuff
932  //6: another status: 0|fee_empty
933 
934  trg_cmd = (d[2]>>0)&0xF ;
935  daq_cmd = (d[2]>>4)&0xF ;
936 
937 
938  // unwrap token
939  {
940  u_short t_hi = (d[2]>>8)&0xF ;
941  u_short t_mid = (d[2]>>12)&0xF ;
942  u_short t_lo = (d[2]>>16)&0xF ;
943 
944  token = (t_hi<<8)|(t_mid<<4)|t_lo ;
945  }
946 
947 
948  if(log_level>=1) LOG(TERR,"%d: T %d(%d,%d)",rdo1,token,trg_cmd,daq_cmd) ;
949 
950  if(log_level>=10) {
951  for(int i=0;i<8;i++) {
952  LOG(TERR,"rdo_scan %d/%d = 0x%08X",i,words,d[i]) ;
953  }
954  }
955 
956  u_int mhz_start = d[3] ;
957  u_int fee_synced = d[4]>>16 ;
958  u_int fee_overrun = d[4]&0xFFFF ;
959  u_int fee_xoff = d[5]>>16 ; // actually prog_full
960  u_int rdo_stuff = d[5]&0xFFFF ;
961  u_int fee_empty = d[6]&0xFFFF ;
962 
963 
964  l_fee_mask = 0 ;
965  for(int i=7;i<15;i++) {
966  if((d[i]&0xFFFF0000)==0xF0000000) {
967  l_fee_mask = d[i]&0xFFFF ;
968  break;
969  }
970  }
971 
972  if(l_fee_mask==0) {
973  LOG(ERR,"%d: no local FEE mask, expecting 0x%04X",rdo1,fee_mask) ;
974  }
975  else {
976 // LOG(TERR,"%d: local FEE mask 0x%04X, expect 0x%04X",rdo1,l_fee_mask,fee_mask) ;
977 // fee_mask = l_fee_mask ;
978  }
979 
980  // I need a special hack here when running in Offline (from a file)
981  // because I might have a FEE masked in online...
982  if(!online) {
983 // fee_mask = fee_synced ;
984  fee_mask = l_fee_mask ;
985  }
986 
987 // 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",
988 // fee_mask,fee_synced,fee_overrun,fee_xoff,rdo_stuff,fee_empty,sig) ;
989 
990  if((fee_synced&fee_mask)!=fee_mask) {
991  if(mode || (online)) LOG(ERR,"%d: evt %d: fee sync error 0x%04X, expect 0x%04X",rdo1,evt,fee_synced,fee_mask) ;
992  // STOP: auto-recovery
993  err |= 0x10 ;
994  }
995 
996  if(fee_overrun&fee_mask) {
997  if(mode || online) {
998  LOG(ERR,"%d: %d: RDOs fee FIFO overrun 0x%04X: words %d: 0x%04X 0x%04X 0x%04X 0x%04X",
999  rdo1,evt,fee_overrun&fee_mask,words,
1000  fee_mask,l_fee_mask,fee_xoff,fee_empty) ;
1001  }
1002  // STOP: auto-recovery
1003  err |= 0x10 ;
1004  }
1005 
1006  if((fee_xoff&fee_mask) != 0) {
1007  //LOG(WARN,"fee_xoff 0x%04X",fee_xoff&fee_mask) ;
1008  // note as interesting
1009  }
1010 
1011  if(rdo_stuff & 0xF000) { // revisit this... what is it?
1012  LOG(NOTE,"%d: rdo_stuff 0x%04X",rdo1,rdo_stuff) ;
1013  }
1014 
1015 
1016  // revisit this...
1017  if((fee_empty&fee_mask)==fee_mask) ; // I expect it to be empty
1018  else {
1019  //if(!fee_words) LOG(WARN,"fee_empty 0x%04X",fee_empty&fee_mask) ;
1020  }
1021 
1022 
1023  // go to the end
1024  int got_it = 0 ;
1025  for(int i=0;i>-35;i--) {
1026 // LOG(TERR," %d = 0x%08X",i,trl[i]) ;
1027 
1028  if(trl[i]==0xDEADC0DE) got_it |=1 ;
1029  else if(got_it && (trl[i]==0xFEEDC0FE)) {
1030  got_it |= 2 ;
1031  trl += i - 1 ; // at the last datum
1032  break ;
1033  }
1034  }
1035 
1036  if(got_it != 3) {
1037  if(mode || online) {
1038  LOG(ERR,"%d: evt %d: no trailer (0x%08X), %d, words %d",rdo1,evt,trl[0],got_it,words) ;
1039 // LOG(ERR," 0x%X 0x%X 0x%X",trl[1],trl[2],trl[3]) ;
1040  }
1041  // STOP: auto-recovery
1042  err |= 0x2 ;
1043 
1044 // for(int i=(words-100);i<(words+100);i++) {
1045 // LOG(ERR," %d = 0x%08X",i,d_start[i]) ;
1046 // }
1047  }
1048 
1049  trl -= 1 ;
1050  u_int evt_status = trl[0] ;
1051  u_int mhz_end = trl[1] ;
1052 
1053 
1054  // happens, why?
1055  if(evt_status==0x0EEDC0DE) {
1056  for(int i=-8;i<=8;i++) {
1057  if(online || mode) LOG(ERR,"%d: %d = 0x%08X",rdo1,i,trl[i]) ;
1058  }
1059  }
1060 
1061 // LOG(TERR,"trl0 0x%08X, trl1 0x%08X",trl[0],trl[1]) ;
1062 
1063  u_int evt_type = (d[1]>>28)&0xF ;
1064 
1065 
1066  int trg_cou = 0 ;
1067 
1068 
1069  switch(evt_type) {
1070  case 1 : // timer
1071  token = 4096 ;
1072  trg_cmd = 0 ;
1073  daq_cmd = 0 ;
1074  goto done ;
1075  case 2 : // trigger!
1076  evt_trgd++ ;
1077  break ;
1078  default :
1079  LOG(ERR,"%d: %d: unknown event type %d: 0x%08X",rdo1,evt,evt_type,d[1]) ;
1080  err |= 0x4 ;
1081  goto done ;
1082  break ;
1083  }
1084 
1085 
1086 
1087  for(int i=0;i<16;i++) {
1088  if(fee_mask & (1<<i)) ;
1089  else continue ;
1090 
1091  u_int st = (evt_status>>(i*2)) & 0x3 ;
1092 
1093  if(st != 3) {
1094  err |= 0x1000 ;
1095  if(mode || (online && run_errors<10)) LOG(ERR,"%d: %d: FEE %2d: timeout 0x%X [0x%08X]",rdo1,evt,i,st,evt_status) ;
1096  }
1097  }
1098 
1099  // continue with data
1100  d += 7 ; // should be at the trigger FIFO
1101  while((*d>>28)==0x4) { // skip data from Trigger FIFO because we don't care much
1102  trg_cou++ ;
1103  d++ ;
1104  }
1105 
1106  if(trg_cou>8) {
1107  LOG(WARN,"Lots of triggers %d",trg_cou) ;
1108  }
1109 
1110  if(log_level>=1) LOG(TERR,"%d: evt %d: fee_mask expected 0x%04X",rdo1,evt,fee_mask) ;
1111 
1112  // should be at the FEE start: 0xF000_mmmm
1113  // THIS IS THE CANONICAL MASK AS SET BY THE RDO DURING RUNNING
1114  // AND SHOULD BE USED OFFLINE
1115  if(((*d>>28)!=0xF)||((*d&0xFFFF)!=fee_mask)) {
1116  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) ;
1117  err |= 0x20 ;
1118  goto done ;
1119  }
1120 
1121 
1122  d++ ; // move to start-of-FEE bank
1123 
1124 
1125  if(fee_words) goto done ; // emulation: skip scans
1126 
1127 #if 0
1128  printf("==== trg_evts %d\n",trgd_evt) ;
1129  for(int i=0;i<(trl-d);i++) {
1130  printf("%d = 0x%08X\n",i,d[i]) ;
1131  }
1132  fflush(stdout) ;
1133 #endif
1134 
1135 // if(run_type==1 || run_type==5) {
1136 // pthread_mutex_lock(&peds_mutex) ;
1137 // }
1138 
1139  if(log_level>=2) LOG(TERR,"here") ;
1140 
1141 // LOG(TERR,"%d: fee_mask 0x%08X",rdo1,fee_mask) ;
1142 
1143  for(int i=0;i<16;i++) {
1144  if(fee_mask & (1<<i)) ;
1145  else continue ;
1146 
1147  fee_ix = i ;
1148  d = fee_scan(d) ;
1149  if(d>=trl) break ;
1150  }
1151 
1152  if(log_level>=2) LOG(TERR,"here2") ;
1153 
1154 // if(run_type==1 || run_type==5) {
1155 // pthread_mutex_unlock(&peds_mutex) ;
1156 // }
1157 
1158 
1159 
1160  done:;
1161 
1162 
1163 
1164  if(err||prog_fulls) {
1165  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,
1166  token,trg_cmd,daq_cmd,
1167  err,
1168  prog_fulls,
1169  words,mhz_end-mhz_start) ;
1170  }
1171  else if(token==4096) {
1172  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,
1173  token,trg_cmd,daq_cmd,
1174  err,
1175  prog_fulls,rdo_stuff,
1176  words,mhz_end-mhz_start) ;
1177  }
1178  else if((evt_trgd%1000)==1) {
1179  if(log_level>=1) {
1180  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,
1181  token,trg_cmd,daq_cmd,
1182  err,
1183  prog_fulls,rdo_stuff,
1184  words,mhz_end-mhz_start) ;
1185  }
1186 
1187  }
1188  else {
1189  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,
1190  token,trg_cmd,daq_cmd,
1191  err,
1192  prog_fulls,rdo_stuff,
1193  words,mhz_end-mhz_start) ;
1194 
1195  }
1196 
1197  return err ; // 0 is no error
1198 }
1199 
1200 
1201 
1202 
1203 u_int itpc23::get_token_s(char *c_addr, int words)
1204 {
1205  u_int *d = (u_int *)c_addr ;
1206  int t, trg, daq ;
1207 
1208  t = 4097 ;
1209  trg = 0 ;
1210  daq = 0 ;
1211 
1212 // for(int i=0;i<32;i++) {
1213 // LOG(TERR,"get_token_s: %d/%d = 0x%08X",i,words,d[i]) ;
1214 // }
1215 
1216 
1217  u_int sig, trg_w,sub ;
1218  u_int fmt23 ;
1219 // if(d[4]==0xCCCC001C) {
1220  if(d[4]==0xCCCC001C && fmt<23) {
1221  sig = sw16(d[5]) ;
1222  trg_w = sw16(d[6]) ;
1223  sub = sw16(d[7]) ;
1224  }
1225  else {
1226  sig = d[5] ;
1227  trg_w = d[6] ;
1228  sub = d[7] ;
1229  }
1230 
1231 // LOG(TERR,"0x%08X: 0x%08X 0x%08X 0x%08X",d[4],sig,trg_w,sub) ;
1232 
1233  if((sig&0xFF000000)==0x98000000) {
1234  fmt23 = 0 ;
1235  }
1236  else {
1237  fmt23 = 23 ;
1238  }
1239 
1240  if(fmt23>22) {
1241  int evt_type ;
1242 
1243  // unwrap token
1244  t = 0xFFF ;
1245  {
1246  u_short t_hi = (trg_w>>8)&0xF ;
1247  u_short t_mid = (trg_w>>12)&0xF ;
1248  u_short t_lo = (trg_w>>16)&0xF ;
1249 
1250  t = (t_hi<<8)|(t_mid<<4)|t_lo ;
1251  }
1252 
1253  trg = (trg_w>>0)&0xF ;
1254  daq = (trg_w>>4)&0xF ;
1255 
1256  evt_type = (sig>>28)&0xF ;
1257 
1258  if(evt_type==1) { // timer
1259  t = 4096 ;
1260  trg = 0 ;
1261  daq = 1 ;
1262  }
1263 
1264  }
1265  else {
1266 
1267 #if 0
1268  d += 4 ; // skip header
1269  words -= 4 ;
1270 
1271  for(int i=0;i<16;i++) {
1272  if(d[i] == 0xCCCC001C || d[i]==0x001CCCCC) {
1273  d = d + i ;
1274  words-- ;
1275  break ;
1276  }
1277  }
1278 #endif
1279 
1280 
1281 // for(int i=0;i<32;i++) {
1282 // LOG(TERR,"%d/%d = 0x%08X",i,words,d[i]) ;
1283 // }
1284 
1285 
1286  int rdo_version = 0 ;
1287 
1288  if(sig==0x98000004) rdo_version = 0 ;
1289  else if((sig&0xFF00000F)==0x98000004) rdo_version = (sig>>4)&0xFF ;
1290  else {
1291  LOG(WARN,"%d: fmt 22: not triggered: ds 0x%08X, words",rdo1,sig,words) ;
1292  t = 4096 ;
1293  goto done ;
1294  }
1295 
1296 
1297 
1298 
1299 // if(trg_w==0) {
1300 // if(rdo_version==1) {
1301 // if(sub==0x980000FC) {
1302 // LOG(WARN,"%d: RDO_mon, words %d",rdo1,words) ;
1303 // }
1304 // }
1305 // }
1306 
1307 
1308  t = ((trg_w>>8)&0xF)<<8 ;
1309  t |= ((trg_w>>12)&0xF) << 4 ;
1310  t |= ((trg_w>>16)&0xF) ;
1311 
1312  trg = trg_w & 0xF ;
1313  daq = (trg_w>>4) & 0xF ;
1314 
1315 // LOG(TERR,"%d: rdo_version %d, trg_fired 0x%08X: T %d, trg %d:%d",rdo1,rdo_version,trg_fired,t,trg,daq) ;
1316 
1317  if(trg_w==0) {
1318  t = 4097 ;
1319  trg = 0 ;
1320  daq = 0 ;
1321  goto done ;
1322  }
1323 
1324 
1325  }
1326 
1327  done:;
1328 
1329 // LOG(TERR,"T %d, trg %d:%d",t,trg,daq) ;
1330 
1331 
1332 
1333  return (trg<<16)|(daq<<12)|t ;
1334 }
1335 
1336 
1337 itpc23::itpc23()
1338 {
1339 // LOG(TERR,"%s",__PRETTY_FUNCTION__) ;
1340 
1341  rts_id = ITPC_ID ;
1342 
1343  if(rp_gain_itpc==0) {
1344  rp_gain_itpc = (row_pad_t (*)[ROW_MAX+1][PAD_MAX+1]) malloc(sizeof(row_pad_t)*24*(ROW_MAX+1)*(PAD_MAX+1)) ;
1345 
1346  // inititalize here!
1347  // initialize here!
1348  for(int s=0;s<24;s++) {
1349  for(int r=0;r<=ROW_MAX;r++) {
1350  for(int p=0;p<=PAD_MAX;p++) {
1351  rp_gain_itpc[s][r][p].gain = 1.0 ;
1352  rp_gain_itpc[s][r][p].t0 = 0.0 ;
1353  rp_gain_itpc[s][r][p].flags = 0 ;
1354  }}}
1355 
1356 
1357  }
1358 
1359  rp_gain = rp_gain_itpc ;
1360 
1361 // if(rp_gain==0) {
1362 // rp_gain = (row_pad_t (*)[ROW_MAX+1][PAD_MAX+1]) malloc(sizeof(row_pad_t)*24*(ROW_MAX+1)*(PAD_MAX+1)) ;
1363 // }
1364 
1365  row_min = 1 ;
1366  row_max = 40 ;
1367 
1368  for(int row=1;row<=40;row++) rowlen[row] = itpc_rowlen[row] ;
1369 
1370  data_c = 0 ;
1371 
1372  fmt = 0 ;
1373 
1374 }
1375 
1376 
1377 itpc23::~itpc23()
1378 {
1379 // LOG(TERR,"%s",__PRETTY_FUNCTION__) ;
1380 
1381  return ;
1382 }
1383 
1384 u_char itpc23::flags_row_pad(int asic, int channel, int &row, int &pad)
1385 {
1386  int id, sampa ;
1387 
1388  id = asic>>1 ; // FEE padplane id
1389  sampa = asic & 1 ;
1390 
1391  itpc_sampa_to_rowpad(id,sampa,channel,row,pad) ;
1392  if(row==0 || row==255) return 0xFF ;
1393  if(pad==0 || pad==255) return 0xFF ;
1394 
1395 
1396  return rp_gain[sector1-1][row][pad].flags ;
1397 }
1398 
1399 
1400 static const char *hwicap_version(u_int v)
1401 {
1402  static char ascii[64] ;
1403 
1404  int s = v & 0x3F ;
1405  int m = (v>>6)&0x3F ;
1406  int h = (v>>12)&0x1F ;
1407  int y = ((v>>17)&0x3F) ;
1408  int mo = (v>>23)&0xF ;
1409  int d = (v>>27)&0x1F ;
1410 
1411 
1412  sprintf(ascii,"%02d-%02d-%02d %02d:%02d:%02d",
1413  mo,d,y,h,m,s) ;
1414 
1415  return ascii ;
1416 }
1417 
1418 
1419 //static const int itpc_fee_map[24][4][16] = {
1420 static int itpc_fee_map[24][4][16] = {
1421 {//S1 checked
1422  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1423  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35}, //ok
1424  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1425  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1426 },
1427 {//S2 checked
1428  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1429  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1430 //usual { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1431 // { 7, 1,17,12,24, 0,13, 8,28, 2,19,20,29,25,21, 3}, // moved #6 to #11
1432  { 7, 1, 0,12,24,17,13, 8,28, 2,19,20,29,25,21, 3}, // moved #6 to #11; and #3 to #6
1433  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1434 },
1435 {//S3 checked
1436  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1437  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1438  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1439  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1440 
1441 },
1442 {//S4 checked
1443  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1444  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1445  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1446  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1447 
1448 },
1449 {//S5 checked
1450  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1451  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1452  { 7, 1,17,12,24,19,13, 8,28, 2, 3,20,29,25,21, 0}, // 17May23: moved 16 to 11
1453  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1454 
1455 },
1456 {//S6 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  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1460  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1461 
1462 },
1463 {//S7 checked
1464  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1465  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1466  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1467  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1468 
1469 },
1470 {//S8 mess with mapping
1471  {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
1472  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1473  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1474  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1475 
1476 },
1477 {//S9 mess with mapping
1478  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1479  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1480  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1481  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1482 
1483 },
1484 {//S10 checked
1485  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1486  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1487  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1488  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1489 
1490 },
1491 {//S11
1492 // {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53}, // usual
1493  {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
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 {//S12
1500  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
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 {//S13
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 {//S14
1513  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1514  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1515  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1516  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1517 },
1518 {//S15
1519  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1520  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1521  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1522  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1523 },
1524 {//S16
1525  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1526  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1527  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1528  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1529 },
1530 {//S17
1531 // {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
1532  {49,52, 0, 0,46, 54,0,47, 0,50, 0,55,48, 0,51,53},
1533  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1534  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1535  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1536 },
1537 {//S18
1538  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1539  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1540  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1541  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1542 },
1543 {//S19
1544  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1545  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1546  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1547  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1548 },
1549 {//S20
1550  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1551  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1552  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1553  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1554 },
1555 {//S21
1556 // {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1557  {49,52,46, 0, 0,54,47, 0, 0,50, 0,55,48, 0,51,53}, // moved #8 to #7
1558  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1559  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1560  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1561 },
1562 {//S22
1563  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1564  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1565  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1566  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1567 },
1568 {//S23
1569  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1570  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1571  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1572  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1573 },
1574 {//S24
1575  {49,52,46, 0, 0, 54,0,47, 0,50, 0,55,48, 0,51,53},
1576  {36,32,40,43,37,33, 0,41, 0,44,38,34,42,45,39,35},
1577  { 7, 1,17,12,24,19,13, 8,28, 2, 0,20,29,25,21, 3},
1578  { 9, 4,26,14,15,10,30,22,27, 5,31,23,18,16,11, 6}
1579 },
1580 } ;
1581 
1582 
1583 // I could optimize this into an array on the first call
1584 static u_int get_ifee_mask(int sec1, int rdo1)
1585 {
1586  u_int mask = 0 ;
1587 
1588  for(int i=0;i<16;i++) {
1589  if(itpc_fee_map[sec1-1][rdo1-1][i]) mask |= (1<<i) ;
1590  }
1591 
1592  return mask ;
1593 }
1594 
1595 void itpc23::itpc_fee_kill(int s0, int r0, int p0)
1596 {
1597  itpc_fee_map[s0][r0][p0] = 0 ;
1598 }