StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
tpxCore.cxx
1 #include <stdio.h>
2 #include <math.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 
9 #include <rtsLog.h>
10 
11 #include <TPX/tpx_altro_to_pad.h>
12 #include <DAQ1000/ddl_struct.h>
13 #include <TPC/fee_readout.h>
14 
15 
16 #include "tpxCore.h"
17 #include "tpx_fee_position.h"
18 
19 // globally visible
20 struct tpx_rdo tpx_rdo[24][6] ;
21 struct tpx_rdo_dbg tpx_rdo_dbg[24][6] ;
22 int tpx_fee_check ;
23 
24 // statics...
25 u_int expected_usercode[5] = {
26 // 0x1a830000, // used in FY09
27  0x0c500000, // with the Xilinx disabled on powerup
28  0x0283c6b3, // FEE, 30Jan08
29  0x02b9ab26, // Bob, 02Jan08
30  0x18a9352d,
31 // 0x00acf6c3 //06Sep08
32 // 0x00ad0581 //07Sep08
33 // 0x00AD9A39 //15Apr09
34 // 0x00ACEB76 //05Oct09
35 // 0x00ABF590 //07Oct11, DAQ10k: some RDOs had ALTRO timeouts
36  0x00AD9D1D //09Oct11, DAQ10k: maybe 1 clock delayed...
37 } ;
38 
39 static inline u_int get10(u_int *l, u_int p) ;
40 static u_int *data_test(u_int *h, struct tpx_altro_struct *a, int log, u_int *first) ;
41 
42 //static int check_emul(u_int *a) ;
43 
44 static struct {
45  u_char altro ;
46  u_char ch ;
47  u_char rdo ; // from 1 !!!
48 } tpx_pad_to_altro[46][183] ;
49 
50 
51 
52 /*
53  sectors count 1..24
54  rows count 1..45 _but_ row 0 is reserved for non-connected channels
55  pads count 1..182 ; pad 0 is never present
56 
57 */
58 
59 /*
60  RDO counts from 1
61 */
62 void tpx_to_altro(int row, int pad, int &rdo, int &a, int &ch)
63 {
64  static int first ;
65  int ro, pa ;
66 
67 // LOG(DBG,"row %d, pad %d",row,pad) ;
68 
69  if(first == 0) {
70  for(int r=0;r<6;r++) {
71  for(int a=0;a<256;a++) {
72  for(int ch=0;ch<16;ch++) {
73  tpx_from_altro(r,a,ch,ro,pa) ;
74  if(ro > 45) continue ;
75 
76  tpx_pad_to_altro[ro][pa].altro = a ;
77  tpx_pad_to_altro[ro][pa].ch = ch ;
78  tpx_pad_to_altro[ro][pa].rdo = r+1 ; // rdo from 1
79  }
80  }
81  }
82  first = 1 ;
83  }
84 
85 // LOG(DBG,"row %d, pad %d",row,pad) ;
86 
87  rdo = tpx_pad_to_altro[row][pad].rdo ;
88  a = tpx_pad_to_altro[row][pad].altro ;
89  ch = tpx_pad_to_altro[row][pad].ch ;
90 
91 }
92 
93 int *tpx_altro_to_row_override = 0 ;
94 int tpx_rdo_override = 0 ;
95 int tpx_fy16_map = 0 ; // moved some FEEs from RDO1 to RDO2
96 int tpx_is_stgc = 0 ;
97 
98 /*
99  RDO counts from 0!
100 */
101 void tpx_from_altro(int rdo, int a, int ch, int &row, int &pad)
102 {
103 
104  if(rdo<0 || rdo>5) {
105  LOG(ERR,"RDO should count from 0") ;
106  row = 255 ;
107  pad = 255 ;
108  return ;
109  }
110 
111 //LOG(WARN,"Change for sTGC") ;
112 #if 1
113  if(tpx_fy16_map) {
114  int remap = 0 ;
115 
116  switch(a) {
117  case 52 :
118  case 53 :
119  case 54 :
120  case 55 :
121  case 56 :
122  case 57 :
123  case 58 :
124  case 59 :
125  case 60 :
126  case 61 :
127  case 66 :
128  case 67 :
129  remap = 1 ;
130  break ;
131  }
132 
133  if(remap) {
134  if(rdo==0) {
135  row = 255 ; // those guys don't exist in RDO1 anymore!
136  pad = 255 ;
137  return ;
138 
139  } else if(rdo==1) {
140  row = tpx_altro_to_pad[0][a][ch].row ;
141  pad = tpx_altro_to_pad[0][a][ch].pad ;
142  return ;
143 
144  }
145  }
146 
147  }
148  else {
149 // LOG(WARN,"Not FY16 Map????") ;
150  }
151 #endif
152 
153  row = tpx_altro_to_pad[rdo][a][ch].row ;
154  pad = tpx_altro_to_pad[rdo][a][ch].pad ;
155 
156  if(tpx_altro_to_row_override) {
157  if(tpx_rdo_override != (rdo+1)) {
158  row = 255 ;
159  pad = 255 ;
160  return ;
161  }
162 
163  row = tpx_altro_to_row_override[a&0xFE] ;
164 
165  if(a&1) pad = 1 + 16 + ch ;
166  else pad = 1 + ch ;
167 
168 
169 
170 // LOG(TERR,"A %d: row %d, pad %d",a,row,pad) ;
171 
172  if(row<=0) {
173  row = 255 ;
174  pad = 255 ;
175  }
176 
177  return ;
178  }
179 
180 
181 #ifdef ESB_TEST_ETTIE
182  // This is a hack for ETTIE's test!
183  // Should not happen for normal TPX data so I will leave it in the formal code.
184  if(rdo==1) {
185  //printf("RDO %d: ALTRO %d:%d, row:pad %d:%d\n",rdo+1,a,ch,row,pad) ;
186  if((a==252) || (a==253)) {
187  row = a - 210 ;
188  pad = ch + 1 ;
189  }
190  }
191 #endif
192 //#ifdef TEST_ETTIE
193 // row = a - 210 ;
194 // pad = ch + 1 ;
195 //#endif
196 
197 #ifdef TEST_RDO
198  if(rdo==5) { // only 6th RDO can be a test!
199  if((a>=50) && (a<=55)) {
200  row = 255 ;
201  pad = 255 ;
202  return ;
203  }
204  if((a>=250) && (a<=255)) {
205  a -= 200 ;
206 
207  row = tpx_altro_to_pad[rdo][a][ch].row ;
208  pad = tpx_altro_to_pad[rdo][a][ch].pad ;
209  return ;
210  }
211  }
212 #endif
213 
214  return ;
215 }
216 
217 //used in tpxGain solely!
218 int tpx_altro_to_fee(int rdo, int a)
219 {
220 // LOG(WARN,"tpx_altro_to_fee: %d %d (map %d)",rdo,a,tpx_fy16_map) ;
221 
222  rdo-- ; // to start from 0
223 
224  a &= 0xFE ; // make it even
225 
226  for(int i=0;i<36;i++) {
227  int fee, altro ;
228 
229  if(tpx_fy16_map) {
230  fee = tpx_fee_position[rdo][i] ;
231  }
232  else {
233  fee = fee_position[rdo][i] ;
234  }
235 
236  if(fee == 255) continue ;
237 
238  altro = (fee << 1) & 0xFF ;
239 
240  if(altro == a) return fee ;
241  }
242 
243  return -1 ;
244 }
245 
246 //used in tpxGain solely
247 u_char tpx_rdo_fees(int rdo, int cou)
248 {
249 // LOG(WARN,"tpx_rdo_fees: %d %d (map %d)",rdo,cou,tpx_fy16_map) ;
250 
251  if(cou >= 36) return 255 ;
252 
253  if(tpx_fy16_map) return tpx_fee_position[rdo-1][cou] ;
254  else return fee_position[rdo-1][cou] ;
255 }
256 
257 
258 #ifdef WHO_USUES_THIS
259 u_char tpx_altro_ch_to_fee(int a, int ch)
260 {
261  if(a & 1) ch += 16 ; // for odd altros, add 16
262 
263  for(int i=0;i<32;i++) {
264  if(tpx_old_to_new_ch[i] == ch) return i ;
265  }
266 
267  return 255 ;
268 
269 }
270 #endif
271 
272 
273 /*
274  Go through the event, check what you can
275  and return the token.
276  If we are called with do_log=1 _JUST_ do some
277  checks and return the token with logging. Made to work as "get_token"
278 */
279 int tpx_get_start(char *buff, u_int words, struct tpx_rdo_event *rdo, int do_log)
280 {
281  struct ddl_header *hdr ;
282  struct ddl_trailer *trl ;
283 
284 
285  u_int *l ; // temporary pointer...
286 
287 
288 
289  hdr = (struct ddl_header *) buff ;
290 
291  rdo->data_err = 0 ;
292  rdo->token = -ENOTSUP ; // start as if error
293  rdo->trg_cou = 0 ;
294  rdo->rdo = 6 ; // put bullshit values but not completelly bad!
295  rdo->sector = 24 ;
296 
297  // the event needs to have at least the header and trailer!
298  if(words < (2*sizeof(struct ddl_header))/4) {
299  if(do_log) {
300  LOG(ERR,"Event oddly small -- words %d",words) ;
301  }
302  return rdo->token ;
303  }
304 
305 
306  // get stuff from the header...
307  rdo->type = hdr->type & 0xF ; ;
308  rdo->subtype = (hdr->type >> 4) & 0xF ;
309  rdo->sector = (hdr->type >> 12) & 0x7F ; // last bit might indicate an error!
310  rdo->rdo = (hdr->type >> 8) & 0xF ;
311 
312 
313 
314  rdo->data_end = 0 ;
315  rdo->data_start = (u_int *)(buff + sizeof(struct ddl_header)) ; // skip the header...
316 
317  rdo->l2_cmd = 0 ;
318 
319  // now lets move to the end...
320  trl = (struct ddl_trailer *) (buff + 4*words - sizeof(struct ddl_trailer)) ;
321 
322  // NEW: for FY16 we moved some FEEs from RDO1 to RDO2
323 // LOG(TERR,"Type 0x%08X",hdr->type) ;
324  if((hdr->type != 0xFEED0301) && (hdr->type & 0x00100000)) {
325  trl->type |= 0x00100000 ;
326  tpx_fy16_map = 1 ; ;
327  //LOG(TERR,"Setting FY16 map") ;
328  }
329 
330 
331 // LOG(TERR,"Header 0x%08X 0x%08X: type %d, subtype %d, sector %d, rdo %d",
332 // hdr->type,hdr->ev_cou,
333 // rdo->type,rdo->subtype,rdo->sector,rdo->rdo) ;
334 
335 // for(u_int i=0;i<words+8;i++) {
336 // LOG(DBG,"%2d: 0x%08X",i,*((u_int *)buff + i)) ;
337 // }
338 
339 
340 
341  if(trl->type != hdr->type) {
342  if(hdr->type == 0xFEED0301) { // HACK! Old factory type!
343  if(do_log) LOG(WARN,"RDO %d: Old factory log?",rdo->rdo) ;
344  rdo->data_start = (u_int *)(buff + 12) ;
345  rdo->type = DDL_TYPE_LOG ;
346  }
347  else {
348  if(do_log) {
349  LOG(ERR,"RDO %d:%d: Header type 0x%08X and trailer type 0x%08X mismatch",rdo->sector,rdo->rdo,hdr->type,trl->type) ;
350 
351  u_int *d32 = (u_int *)(buff + 4*words) ;
352  d32 -= 5 ;
353 
354  for(int i=0;i<10;i++) {
355  LOG(WARN,"%d: 0x%08X",i,d32[i]) ;
356  }
357  }
358  rdo->token = -EBADF ;
359  return rdo->token ;
360  }
361  }
362 
363 
364 
365  switch(trl->fl_wc >> 28) {
366  case 0 : // all OK
367  rdo->data_err = 0 ;
368  break ;
369  default :
370 
371  if(do_log) rdo->data_err = 1 ; // HACK!
372  break ; // go on...
373  }
374 
375 
376  switch(rdo->type) {
377  case DDL_TYPE_LOG :
378  case DDL_TYPE_MSC :
379  rdo->token = 4096 ; // valid
380  return rdo->token ;
381  case DDL_TYPE_DTA :
382  break ; // later...
383  default :
384  if(do_log) {
385  LOG(WARN,"Hm,I haven't coded this type %d", rdo->type) ;
386  u_int *val = rdo->data_start ;
387  for(int i=0;i<10;i++) {
388  LOG(WARN,"\t%2d: 0x%08X [%u dec]",i,val[i],val[i]) ;
389  }
390  }
391  rdo->token = -ENOTSUP ;
392  return rdo->token ;
393 
394  break ;
395  }
396 
397 
398 
399  l = (u_int *) trl - 1 ; // move before the trailer...
400 
401  rdo->trg_cou = *l ; // get the trigger count
402 
403  if(rdo->trg_cou > 124) {
404  if(do_log) LOG(ERR,"Bad trg count %d>124, token %d",rdo->trg_cou, rdo->token) ;
405 // rdo->trg_cou = 0 ;
406 // rdo->token = -ENOTSUP ;
407 // return rdo->token ;
408  }
409 
410  // move to the start of trigger data
411  l -= rdo->trg_cou * (sizeof(struct trg_data)/4) ;
412 
413  if(l < rdo->data_start) {
414  if(do_log) LOG(ERR,"Bad trigger data!") ;
415  rdo->data_err = 1 ;
416  rdo->token = -EBADF ;
417  return rdo->token ;
418  }
419 
420  rdo->trg = (struct trg_data *) l ;
421 
422 
423  u_int rh ;
424  u_int rh_prompt = 0 ;
425  rdo->token = 4097 ; // in case I don't find a real token!
426 
427  for(u_int i=0;i<rdo->trg_cou;i++) {
428  int rh_delta ;
429 
430  // fish out the token...
431  switch(rdo->trg[i].csr & 0xFF000000) {
432  case 0xFF000000 : // fifo,skip
433  case 0xDD000000 : // FIFO, but selftrigger
434  rh = rdo->trg[i].rhic_counter ;
435  if(rh_prompt) {
436  rh_delta = rh - rh_prompt ;
437  }
438  else {
439  rh_delta = (rh - tpx_rdo_dbg[rdo->sector-1][rdo->rdo-1].old_rhic) ;
440  }
441  break ;
442  case 0xEE000000 : // emulated!
443  default : // real TCD prompt trigger
444  rh_prompt = rdo->trg[i].rhic_counter ;
445  rh_delta = rh_prompt - tpx_rdo_dbg[rdo->sector-1][rdo->rdo-1].old_rhic ;
446  rdo->token = rdo->trg[i].data & 0xFFF ;
447  break ;
448 
449  }
450 
451  if(do_log) {
452  if(rdo->rdo == 1) {
453  LOG(NOTE,"\tRDO %d: evt %d: trg %d: RHIC %u, CSR 0x%08X, data 0x%08X [t %d], bytes %u, delta %d",rdo->rdo,hdr->ev_cou,i,
454  rdo->trg[i].rhic_counter,
455  rdo->trg[i].csr,
456  rdo->trg[i].data,
457  rdo->trg[i].data&0xFFF,
458  words*4,
459  rh_delta) ;
460  }
461  }
462 
463  }
464 
465  if(do_log) {
466  if(rh_prompt) {
467  tpx_rdo_dbg[rdo->sector-1][rdo->rdo-1].delta = rh_prompt - tpx_rdo_dbg[rdo->sector-1][rdo->rdo-1].old_rhic ;
468  tpx_rdo_dbg[rdo->sector-1][rdo->rdo-1].old_rhic = rh_prompt ;
469  }
470  else {
471  tpx_rdo_dbg[rdo->sector-1][rdo->rdo-1].delta = 0 ;
472  // leave "old rhic" intact!
473 
474  }
475 
476  }
477 
478  if(do_log) LOG(DBG,"Event %d: sector %2d, rdo %d, type %d, subtype %d, token %d",
479  hdr->ev_cou,rdo->sector,rdo->rdo,rdo->type,rdo->subtype,rdo->token) ;
480 
481  l -= 2 ; // points to FEE mask, will go away eventually since I never use it...
482 
483  //fee_mask[0] = l[0] ;
484  //fee_mask[1] = l[1] ;
485 
486  if(do_log && (rdo->rdo==6)) {
487  LOG(NOTE,"\t evt %d: %u %u",hdr->ev_cou,l[0],l[1]) ;
488  }
489 
490  //
491  //if(rdo->subtype==DDL_DTA_EMUL) {
492  // check_emul(rdo->data_start) ;
493  // rdo->data_start = 0 ; // mark as non-physics...
494  //}
495 
496  if(rdo->data_err) LOG(ERR,"RDO %d: token %d, event %10u marked as in error [0x%X]",rdo->rdo,rdo->token,hdr->ev_cou,(trl->fl_wc >> 28)) ;
497 
498  if(do_log) LOG(DBG,"RDO %d: real data...",rdo->rdo) ;
499 
500  l-- ; // and now points to the last datum
501 
502  rdo->data_end = l ;
503 
504  if((rdo->data_end - rdo->data_start) <= 0) {
505  if(rdo->token != 4097) {
506  if(do_log) LOG(ERR,"Bad RDO data: start 0x%X, end 0x%X, delta %d, tokenn %d!",rdo->data_start,rdo->data_end,rdo->data_end-rdo->data_start,rdo->token) ;
507  rdo->token = -EBADF ;
508  }
509  }
510 
511  return rdo->token ;
512 }
513 
514 
515 
516 /*
517  This runs through the data pointer "now"
518  backwards (in the altro data manner), checks
519  for correctness.
520 
521  If the data is correct, unpacks it into
522  an altro_struct and returns the pointer
523  to the next altro in the data block.
524 
525  If the data is NOT correct, it scans
526  bacwards until it finds a correct bank
527  and repeats.
528 
529  If the "first" pointer is reached, it
530  returns NULL.
531 
532 */
533 u_int *tpx_scan_to_next(u_int *now, u_int *first, struct tpx_altro_struct *a_struct)
534 {
535  u_int *next_altro ;
536  u_int *store = now ;
537  int log_yes ;
538  int was_log_yes ;
539  int iter = 0 ;
540 
541  // I will log only if I'm told to
542  log_yes = was_log_yes = a_struct->log_err ;
543 
544  a_struct->err = 0 ; // clear error flag
545 
546 
547 
548  do {
549  iter++ ;
550  next_altro = data_test(now,a_struct,log_yes,first) ; // returns pointer to next altro!
551 
552  // logic to print out on first error only....
553  if(next_altro==0) { // error in the bank!
554  LOG(DBG,"Error in the bank at iter %d",iter) ;
555 
556  a_struct->err = 1 ;
557 
558  log_yes = 0 ; // switch off further logging
559 
560  now-- ; // decrement data buffer and try again...
561 
562  }
563  else { // data is OK
564 
565  if(was_log_yes && !log_yes) { // we lost something before, turn on WARN
566  LOG(NOTE," ...but found A%03d:%02d %d words earlier",a_struct->id,a_struct->ch,store-now) ;
567 
568  }
569 
570  if(((next_altro-first)<-1) || ((next_altro-first)>1000000)) {
571  // I wan't to see this...
572  LOG(ERR,"next_altro-first %d",next_altro-first) ;
573  }
574 
575 
576  //if(got_log && a_struct->log_err) {
577  // LOG(WARN,"Got it and now is: %d",a_struct->log_err) ;
578  //}
579 
580  return next_altro ; // pointer to next altro
581 
582  }
583 
584 
585  } while((now-first)>=1) ; // there must be at least 2 words!
586 
587  // can't be -- I wan't to see this
588  LOG(ERR,"At end %d: now 0x%08X, next_altro 0x%08X, now-first 0x%08X, next-first 0x%08X",iter,
589  now,next_altro,now-first,next_altro-first) ;
590 
591  return 0 ; // nothing found!
592 
593 }
594 
595 int tpx_use_rdo(char *rdobuff, int bytes, int (userfunc)(struct tpx_altro_struct *a, void *arg), void *arg)
596 {
597  int t ;
598  u_int *data_end ;
599  tpx_rdo_event rdo ;
600  tpx_altro_struct a ;
601  int ret ;
602 
603  ret = 0 ;
604 
605  t = tpx_get_start(rdobuff, bytes/4, &rdo, 0) ;
606  if(t<=0) {
607  LOG(NOTE,"token %d, rdo %d: not an altro event",t,rdo.rdo) ;
608  return ret ;
609  }
610 
611  if(rdo.data_err) {
612  LOG(ERR,"token %d, rdo %d: altro data error!",t,rdo.rdo) ;
613  return -1 ;
614  }
615 
616  a.what = TPX_ALTRO_DO_ADC ;
617  a.rdo = rdo.rdo - 1;
618  a.sector = rdo.sector ;
619  a.t = t ;
620  a.log_err = 0 ;
621 
622  LOG(DBG,"token %d, rdo %d: running through %d bytes...",t,rdo.rdo,bytes) ;
623 
624  data_end = rdo.data_end ;
625  do {
626 
627  data_end = tpx_scan_to_next(data_end, rdo.data_start, &a) ;
628 
629  ret |= userfunc(&a, arg) ;
630  } while((data_end > rdo.data_start) && data_end) ;
631 
632  return ret ;
633 }
634 
635 
636 /*
637  Scans and uses one altro channels worth of data...
638 
639  h points to where the data is
640  a->rb points to the input RB!
641 
642 */
643 static u_int *data_test(u_int *h, struct tpx_altro_struct *a, int log, u_int *first)
644 {
645  u_int hi, lo ;
646  int wc ;
647  int ret ;
648  int delta ;
649 // u_int *h_start = h ;
650 
651  ret = 0 ;
652 
653 // log = 1 ;
654 
655  a->count = 0 ;
656  a->row = 0 ; // unknown...
657  a->pad = 0 ;
658 
659  delta = h - first ;
660  if(delta < 1) {
661  //if(log) LOG(ERR,"Startup offset bad %d",delta) ;
662  return 0 ;
663  }
664 
665  lo = *h-- ;
666  hi = *h-- ;
667 
668 
669  if((lo & 0xCFF00000) || (hi & 0xCFF00000)) {
670  //if(log) LOG(WARN," Header words have junk: HI 0x%08X, LO 0x%08X",hi,lo) ;
671  ret = -1 ;
672  }
673 
674 
675  // standard tests of the last ALTRO word...
676  if((hi & 0xFFFC0) != 0xAAA80) {
677  //if(log) LOG(WARN," Error HI in last ALTRO word: 0x%08X 0x%08X",hi,lo) ;
678  ret = -2 ;
679 
680  }
681 
682  if((lo & 0x0F000) != 0x0A000) {
683  //if(log) LOG(WARN," Error LO in last ALTRO word: 0x%08X 0x%08X",hi,lo) ;
684  ret = -3 ;
685  }
686 
687 
688  wc = ((hi&0x3F)<<4) | ((lo&0xF0000)>>16) ; // altro's word count
689 
690 
691 
692  a->id = (lo & 0xFF0)>>4 ; // altro ID 0..255
693  a->ch = lo & 0xF ; // channel 0..15
694 
695 
696  if((wc > 529) || (wc<0)) { // for 512 tb + 15 pre + 2
697  //if(log) LOG(WARN," Error in last ALTRO word: 0x%08X 0x%08X; bad WC %d",hi,lo,wc) ;
698  ret = -4 ;
699  }
700 
701 // log = 1 ;
702 // if(log) {
703 // LOG(TERR,"A%d:%d wc %d (0x%08X 0x%08X)",a->id,a->ch,wc,hi,lo) ;
704 // }
705 
706  // we bomb out here if there was any error
707  if(ret) {
708  if(log) LOG(WARN,"RDO %d: T %d: A %d:%d(?) hdr[%d]",a->rdo+1,a->t,a->id,a->ch,ret) ;
709  return 0 ; // already error...
710  }
711 
712  int rrow, ppad ;
713 
714  // FY19: special treatment for
715  if(tpx_is_stgc) {
716  a->pad = a->ch ;
717  a->row = a->id ;
718 
719  goto real_tpx_skipped ;
720  }
721 
722 
723  for(int i=0;i<tpx_fee_override_cou;i++) {
724  //LOG(TERR,"Checking sector %d:%d, rdo %d:%d, id %d:%d",a->sector,tpx_fee_override[i].sector,a->rdo,tpx_fee_override[i].rdo,a->id,tpx_fee_override[i].curr_altro) ;
725  if(a->sector == tpx_fee_override[i].sector) {
726  if(a->rdo == (tpx_fee_override[i].rdo-1)) {
727  int fee = a->id & 0xFE ; // kill last bit
728  if(fee == tpx_fee_override[i].curr_altro) {
729  int should = tpx_fee_override[i].orig_altro ;
730 
731  if(a->id & 1) {
732  should = tpx_fee_override[i].orig_altro | 1 ;
733  }
734  else {
735  should = tpx_fee_override[i].orig_altro ;
736  }
737 
738  if(log) {
739  //LOG(NOTE,"Sector %2d, RDO %d override: altro in data %3d but should be %3d!",a->sector,a->rdo+1,a->id,should) ;
740  }
741 
742 
743  a->id = should ; // put the ID of the expected ALTRO!
744  }
745  }
746  }
747  }
748 
749 
750 
751 
752  // get the row and pad; this is why we needed the rdo...
753  tpx_from_altro(a->rdo, a->id, a->ch, rrow, ppad) ;
754 
755  a->row = rrow ;
756  a->pad = ppad ;
757 
758 
759  if((a->row > 45) || (a->pad > 182)) {
760  if(log) LOG(ERR,"row:pad %d:%d illegal for altro %d:%d",a->row,a->pad,a->id,a->ch) ;
761 //LOG(WARN,"Change for sTGC: altro %d",a->id) ;
762  if(tpx_rdo_override==0) return 0 ;
763  }
764 
765  real_tpx_skipped:;
766 
767 
768  if(wc == 0) return h ; // empty channel...
769 
770  int l10 = wc ;
771 
772  while(l10 % 4) l10++ ; // move until divisible by 4
773 
774  // l10 is minimally 4 for right now
775 
776  // sanity check
777  delta = (h - l10/2) - first ;
778  if(delta < -1) {
779  if(log) LOG(ERR,"AID %d:%d: Bad offset %d, wrong wc %d", a->id, a->ch, delta, wc) ;
780  return 0 ;
781  }
782 
783 
784  int p10 = 0 ; // backward counter of the 10bit contributions
785 
786  // now we move through the padding, depending on the wc's last 2 bits...
787  switch(wc&3) {
788  case 0 :
789  break ;
790 
791  case 1 :
792  if(get10(h,p10) != 0x2AA) {
793  //if(log) LOG(WARN," Bad 0x2AA 1:1") ;
794  ret = -5 ;
795  }
796  p10++ ;
797 
798  if(get10(h,p10) != 0x2AA) {
799  //if(log) LOG(WARN," Bad 0x2AA 1:2: 0x%X %d",get10(h,p10),wc) ;
800  ret = -6 ;
801  }
802  p10++ ;
803 
804  if(get10(h,p10) != 0x2AA) {
805  //if(log) LOG(WARN," Bad 0x2AA 1:3") ;
806  ret = -7 ;
807  }
808  p10++ ;
809 
810  break ;
811 
812  case 2 :
813  if(get10(h,p10) != 0x2AA) {
814  //if(log) LOG(WARN," Bad 0x2AA 2:1") ;
815  ret = -8 ;
816  }
817  p10++ ;
818 
819  if(get10(h,p10) != 0x2AA) {
820  //if(log) LOG(WARN," Bad 0x2AA 2:2") ;
821  ret = -9 ;
822  }
823  p10++ ;
824 
825  break ;
826 
827  case 3 :
828  if(get10(h,p10) != 0x2AA) {
829  //if(log) LOG(WARN," Bad 0x2AA 3:1") ;
830  ret = -10 ;
831  }
832  p10++ ;
833 
834  break ;
835  }
836 
837 
838 
839 
840 // LOG(TERR,"AID %d:%d, wc %d: p10 %d, l10 %d, delta %d, next at %d",a->id,a->ch,wc,
841 // p10,l10,h-first,(h-l10/2)-first) ;
842 
843 #ifdef VEERY_PARANOID
844  // check general form of _all_ the data -- nothing should be in the upper 12 bits
845  for(int i=0;i<l10/4;i++) {
846  if(h[-i] & 0xCFF00000) {
847  // should not happen -- I want to see this!
848  if(log) LOG(ERR," Bad form 0x%08X at %d",h[-i],i) ;
849  ret = -1 ;
850  break ;
851  }
852  }
853 #endif
854 
855  if(ret) {
856  if(log) LOG(WARN,"RDO %d: T %d: A %d:%d(?) hdr[%d]",a->rdo+1,a->t,a->id,a->ch,ret) ;
857  return 0 ; // already error...
858  }
859 
860 
861 
862 
863  // data check; we are in the data mode now...
864  int tb_prev = 512 ;
865 
866  u_short *p_adc = a->adc ;
867  u_short *p_tb = a->tb ;
868  int tb_all = 0 ;
869 
870  while(p10 < l10) {
871  int tb_cou = get10(h,p10++) ;
872  int tb_last = get10(h,p10++) ;
873  int tb_prev_last = tb_prev ;
874 
875  tb_cou -= 2 ; // tb_cou & tb_last are included in the count, get rid of them...
876 
877  /*
878  u_int tb_last
879  can't be greater than 511
880  can't be less than 0
881  can't be greater or equal to the end of the previous sequence
882 
883 
884  int tb_cou
885  can't be less than 0
886  can't be greater than 512
887  can't be greater than the total word count!
888 
889  */
890 
891  // do some sanity checks...
892  if((tb_cou > wc) || (tb_cou <= 0) || (tb_cou > 512)) {
893  //if(log) LOG(WARN," A%03d:%02d: Bad tb_cou %d > wc %d [tb_last %d]?",a->id,a->ch,tb_cou,wc,tb_last) ;
894  ret = -1 ;
895  }
896 
897  if((tb_last < 0) || (tb_last >= tb_prev)) {
898  //if(log) LOG(WARN," A%03d:%02d: Bad tb_last %d => tb_prev %d?",a->id,a->ch,tb_last,tb_prev) ;
899  ret = -2 ;
900  }
901 
902 
903  tb_all += tb_cou ;
904  if(tb_all >= 512) {
905  ret = -3 ;
906  //if(log) LOG(WARN,"RDO %d: token %d: Altro %03d:%02d (?) tb_all [1] %d",a->rdo+1,a->t,a->id,a->ch,tb_all) ;
907  }
908 
909 
910 
911  tb_prev = tb_last - tb_cou ;
912 
913  if(tb_prev < -1) {
914  ret = -4 ;
915  //if(log) LOG(WARN,"RDO %d: token %d: Altro %03d:%02d (?) tb_prev [2] %d",a->rdo+1,a->t,a->id,a->ch,tb_prev) ;
916  }
917 
918  if(ret) {
919  if(log) LOG(WARN,"RDO %d: T %d: A %d:%d(?) dta[%d]: pprev %d, prev %d, last %d, cou %d",a->rdo+1,a->t,a->id,a->ch,ret,
920  tb_prev_last,tb_prev,tb_last,tb_cou) ;
921  return 0 ;
922  }
923 
924 
925  if(a->what & TPX_ALTRO_DO_ADC) {
926  for(;tb_last > tb_prev; tb_last--) {
927  *p_adc++ = get10(h, p10++) ;
928  *p_tb++ = tb_last ;
929  }
930  }
931  else {
932  p10 += tb_cou ;
933  }
934 
935 
936 
937  }
938 
939 
940 
941 
942 
943  if(ret) {
944  if(log) LOG(ERR,"RDO %d: token %d: Altro %03d:%02d (?) data [2]",a->rdo+1,a->t,a->id,a->ch) ;
945  return 0 ; // already error...
946  }
947  else {
948  a->count = p_adc - a->adc ; // put count only if all OK
949  }
950 
951  l10 /= 2 ; // how many more words in this event...
952 
953  h -= l10 ; // point now to the start of next altro...
954 
955 
956 // LOG(TERR,"Returning delta %d",h-first) ;
957 // note that -1 is the last return!
958 
959  return h ; // return pointer to the start of the next altro!
960 }
961 
962 
963 
964 #if 0
965 static int check_emul(u_int *a)
966 {
967  int i ;
968  u_int dta, should ;
969  u_int errors ;
970 
971  errors = 0 ;
972  for(i=0;i<200000;i++) {
973  dta = *a++ ;
974 
975  should = ((i&0xFFFF)<<16)|(i&0xFFFF) ;
976 
977  if(dta != should) {
978  errors++ ;
979  LOG(ERR,"Mismatch %d: at %d: should 0x%08X, is 0x%08X",errors,i,should,dta) ;
980  if(errors > 3) break ;
981  }
982  }
983 
984  if(errors) {
985  return -1 ;
986  }
987 
988  LOG(NOTE,"Emul evt checks OK...") ;
989  return 0 ;
990 
991 }
992 #endif
993 
994 static inline u_int get10(u_int *l, u_int p)
995 {
996  u_int ret ;
997 
998  l -= 2*(p/4) ;
999 
1000  switch(p&3) {
1001  case 0 :
1002  ret = (l[-1] & 0xFFC00) >> 10 ;
1003  break ;
1004  case 1 :
1005  ret = (l[-1] & 0x3FF) ;
1006  break ;
1007  case 2 :
1008  ret = (l[0] & 0xFFC00) >> 10 ;
1009  break ;
1010  case 3 :
1011  default:
1012  ret = l[0] & 0x3FF ;
1013  break ;
1014  }
1015 
1016  //printf("P %d, data 0x%X\n",p,ret) ;
1017 
1018  return ret ;
1019 }
1020 
1021 
1022 void tpx_analyze_log(int sector,int rdo, char *buff)
1023 {
1024  int i ;
1025  char *start_ptr ;
1026  int len ;
1027 
1028  LOG(WARN,"tpx_analyze_log: deprecated!") ;
1029 
1030  len = strlen(buff) ;
1031  start_ptr = buff ;
1032 
1033 
1034 
1035  while(len) {
1036  for(i=0;i<len;i++) {
1037  if(start_ptr[i] == '\n') {
1038  start_ptr[i] = 0 ;
1039  if(strlen(start_ptr)) {
1040 
1041  LOG(INFO,"[Sec_%02d:RDO_%d] %s",sector,rdo,start_ptr) ;
1042  }
1043  start_ptr = start_ptr + i + 1 ;
1044  len = strlen(start_ptr) ;
1045  break ;
1046  }
1047  }
1048  }
1049 
1050  return ;
1051 
1052 }
1053 
1054 int tpx_show_status(int sector, int rb_mask, int *altro_list)
1055 {
1056  struct tpx_rdo *rdo ;
1057  u_char altro[256] ;
1058  int err ;
1059  int rb ;
1060 
1061  err = 0 ;
1062 
1063  for(rb=0;rb<6;rb++) {
1064 
1065  if((1<<rb) & rb_mask) ;
1066  else continue ;
1067 
1068  rdo = &(tpx_rdo[sector-1][rb]) ;
1069 
1070  if(rdo->sector != sector || (rb+1) != rdo->rdo) {
1071  LOG(WARN,"msc: config for RDO %d: sector %d, rdo %d claims error",rb+1,rdo->sector & 0x7F,rdo->rdo) ;
1072  //err |= 1 ;
1073  }
1074  else {
1075  LOG(NOTE,"msc: config for RDO %d: sector %d, rdo %d",rb+1,rdo->sector,rdo->rdo) ;
1076  }
1077 
1078  LOG(NOTE,"msc: Remote %d, temp rdo %d, temp stratix %d",rdo->remote,rdo->temp_rdo,rdo->temp_stratix) ;
1079  LOG(NOTE,"msc: Compiled on %s",rdo->compilation_date) ;
1080 
1081  LOG(NOTE,"\t FPGAs: 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X",
1082  rdo->fpga_usercode[0],
1083  rdo->fpga_usercode[1],
1084  rdo->fpga_usercode[2],
1085  rdo->fpga_usercode[3],
1086  rdo->fpga_usercode[4]
1087  ) ;
1088 
1089  for(int i=0;i<5;i++) {
1090  if((expected_usercode[i] != rdo->fpga_usercode[i]) && (rdo->fpga_usercode[i] != (u_int)(i+1))) {
1091  LOG(WARN,"msc: RDO %d: FPGA %d usercode is 0x%08X, expect 0x%08X!?",rdo->rdo,i,rdo->fpga_usercode[i],expected_usercode[i]) ;
1092  }
1093  }
1094 
1095  if(rdo->status_xilinx) {
1096  LOG(ERR,"msc: RDO %d: xilinx status: 0x%02X",rdo->rdo,rdo->status_xilinx) ;
1097  err |= 1 ;
1098  }
1099  else {
1100  LOG(NOTE,"RDO %d: xilinx status: 0x%02X",rdo->rdo,rdo->status_xilinx) ;
1101  }
1102  if(rdo->status_cpld) {
1103  LOG(ERR,"msc: RDO %d: CPLD status: 0x%02X",rdo->rdo,rdo->status_cpld) ;
1104  err |= 1 ;
1105  }
1106  else {
1107  LOG(NOTE,"RDO %d: CPLD status: 0x%02X",rdo->rdo,rdo->status_cpld) ;
1108  }
1109 
1110 
1111  memset(altro,0,sizeof(altro)) ;
1112 
1113  if(altro_list) {
1114  for(int a=0;a<256;a++) {
1115  altro[a] = altro_list[a] ;
1116  }
1117  }
1118  else {
1119  for(int a=0;a<256;a++) {
1120  for(int c=0;c<16;c++) {
1121  int row, pad ;
1122 
1123  tpx_from_altro(rb,a,c,row,pad) ;
1124 
1125  if(row <= 45) {
1126  altro[a] |= 0x1 ; // need!
1127  }
1128  }
1129  }
1130  }
1131 
1132  // get list of bad FEEs and clear the "need" flag
1133  for(int i=0;i<tpx_odd_fee_count;i++) {
1134  if((tpx_odd_fee[i].sector != sector) || (tpx_odd_fee[i].rdo != (rb+1))) continue ;
1135  for(int j=0;j<2;j++) {
1136  for(int a=0;a<256;a++) {
1137  if(!altro[a]) continue ;
1138 
1139  if((tpx_odd_fee[i].altro_id_padplane + j) == a) {
1140  altro[a] = 0 ;
1141  LOG(WARN,"Marking ALTRO %3d (FEE %03d) as unneeded because it is marked bad in the gain file...",
1142  a,tpx_odd_fee[i].tpc_fee_padplane) ;
1143  }
1144  }
1145  }
1146 
1147  }
1148 
1149  // get list of potentially overriden altros for this sector & rdo
1150  LOG(NOTE,"Checking override map [%d]",tpx_fee_override_cou) ;
1151  int over = 0 ;
1152  int in_fee[32], should_be[32] ;
1153 
1154  for(int i=0;i<tpx_fee_override_cou;i++) {
1155  LOG(NOTE,"Checking sector %d:%d, rdo %d:%d, id %d:%d",sector,tpx_fee_override[i].sector,rb+1,tpx_fee_override[i].rdo,
1156  tpx_fee_override[i].orig_altro,tpx_fee_override[i].curr_altro) ;
1157 
1158  if(sector == tpx_fee_override[i].sector) {
1159  if((rb+1) == tpx_fee_override[i].rdo) {
1160  in_fee[over] = tpx_fee_override[i].curr_altro ;
1161  should_be[over] = tpx_fee_override[i].orig_altro ;
1162  over++ ;
1163  LOG(WARN,"Expect to override wrong altro %3d with correct altro %3d!",tpx_fee_override[i].curr_altro,tpx_fee_override[i].orig_altro) ;
1164 
1165 
1166  }
1167  }
1168 
1169  }
1170 
1171  //new: check for the actual, correct, FEE complement
1172  int fcou ;
1173 
1174  fcou = 0 ;
1175  for(int b=0;b<3;b++) {
1176  for(int c=0;c<12;c++) {
1177  int altro = rdo->fee[b][c].id ;
1178 
1179 // LOG(TERR,"RDO %d: %2d: altro %3d, status %d",rdo->rdo,fcou,altro,rdo->fee[b][c].fee_status) ;
1180 
1181 
1182  //is the altro overriden?
1183  for(u_int i=0;i<sizeof(tpx_fee_override)/sizeof(tpx_fee_override[0]);i++) {
1184  int r = tpx_fee_override[i].rdo ;
1185  int s = tpx_fee_override[i].sector ;
1186 
1187  if(r==rdo->rdo && s==rdo->sector) ;
1188  else continue ;
1189 
1190  if(altro==tpx_fee_override[i].curr_altro) {
1191  altro = tpx_fee_override[i].orig_altro ;
1192  break ;
1193  }
1194  }
1195 
1196  //special cases
1197  if(rdo->sector==6 && rdo->rdo==3) {
1198  if(altro==200 || altro==214) {
1199  fcou++ ;
1200  continue ;
1201  }
1202  }
1203 
1204 
1205  int fee_expect = tpx_rdo_fees(rdo->rdo, fcou) ;
1206  int altro_expect = -1 ;
1207 
1208  if(fee_expect != 255) {
1209  altro_expect = (fee_expect << 1) & 0xFF ;
1210  }
1211 
1212  if(rdo->fee[b][c].fee_status) {
1213  if(altro_expect != altro) {
1214  LOG(WARN,"RDO %d: at %d:%d: expect %d, got %d",rdo->rdo,b,c,altro_expect,altro) ;
1215  }
1216 
1217  }
1218  else {
1219  if(altro_expect != -1) {
1220  LOG(WARN,"RDO %d: at %d:%d: expect %d, got %d",rdo->rdo,b,c,altro_expect,altro) ;
1221  }
1222  }
1223 
1224 
1225  fcou++ ;
1226  }
1227  }
1228 
1229 
1230  fcou = 1 ;
1231  for(int b=0;b<3;b++) {
1232  for(int c=0;c<12;c++) {
1233  int ix = rdo->fee[b][c].id ; // altro id!
1234 
1235  if((altro[ix] & 2)) {
1236  LOG(ERR,"Duplicate ALTRO %d status 0x%X at %d:%d",ix,altro[ix],b,c) ;
1237  }
1238 
1239  if(rdo->fee[b][c].fee_status) { // found in the scan..
1240 
1241  altro[ix] |= 0x2 ; // found
1242  altro[ix+1] |= 0x2 ;
1243 
1244  if(rdo->fee[b][c].jumpers != 3) {
1245  altro[ix] |= 4 ;
1246  altro[ix+1] |= 4 ;
1247  }
1248 
1249  if(rdo->fee[b][c].fee_status == 1) { // normal; scan OK
1250 
1251  }
1252  else {
1253  altro[ix] |= 0x8 ; // err!
1254  altro[ix+1] |= 0x8 ;
1255 
1256  }
1257 
1258  if(altro[ix] != 3) { // somehing is not right so let's look at the possibilites...
1259 
1260  // is it overriden (jumpers should be non-3
1261 
1262  int overriden = 0 ;
1263  for(int i=0;i<over;i++) {
1264  if((in_fee[i] == ix) || ((in_fee[i]+1)==ix)) {
1265  LOG(WARN,"Sector %2d, RDO %d: %2d: FEE %3d (A%3d,%d) [port %d:%d:%d] = 0x%X, 0x%X -- overriden, should be A%3d",sector,rdo->rdo,fcou,
1266  rdo->fee[b][c].pad_id,
1267  rdo->fee[b][c].id,
1268  rdo->fee[b][c].jumpers,
1269  b,
1270  rdo->fee[b][c].x_s>>4,
1271  rdo->fee[b][c].x_s&1,
1272  rdo->fee[b][c].fee_status,
1273  altro[ix],
1274  should_be[i]
1275  ) ;
1276  overriden = 1 ; // override error
1277  break ;
1278  }
1279  }
1280 
1281  // was it marked bad in the gain file?
1282  for(int i=0;i<tpx_odd_fee_count;i++) {
1283  if((tpx_odd_fee[i].altro_id_padplane == ix) || ((tpx_odd_fee[i].altro_id_padplane+1) == ix)) {
1284 
1285  LOG(WARN,"msc: Sector %2d, RDO %d: %2d: FEE %3d (A%3d,%d) [port %d:%d:%d] = 0x%X, 0x%X -- marked bad in gain file",sector,rdo->rdo,fcou,
1286  rdo->fee[b][c].pad_id,
1287  rdo->fee[b][c].id,
1288  rdo->fee[b][c].jumpers,
1289  b,
1290  rdo->fee[b][c].x_s>>4,
1291  rdo->fee[b][c].x_s&1,
1292  rdo->fee[b][c].fee_status,
1293  altro[ix]
1294  ) ;
1295 
1296  overriden = 1 ;
1297  break ;
1298  }
1299  }
1300 
1301  if(overriden) ;
1302  else {
1303  LOG(ERR,"msc: Sector %2d, RDO %d: %2d: FEE %3d (A%3d,%d) [port %d:%d:%d] = 0x%X, 0x%X",
1304  sector,rdo->rdo,fcou,
1305  rdo->fee[b][c].pad_id,
1306  rdo->fee[b][c].id,
1307  rdo->fee[b][c].jumpers,
1308  b,
1309  rdo->fee[b][c].x_s>>4,
1310  rdo->fee[b][c].x_s&1,
1311  rdo->fee[b][c].fee_status,
1312  altro[ix]
1313  ) ;
1314  }
1315  }
1316 
1317 
1318  fcou++ ;
1319  }
1320  }
1321  }
1322 
1323 
1324  // now find missing ALTROs
1325  for(int a=0;a<256;a++) {
1326  if(altro[a] == 0) continue ; // skip unneeded and not found...
1327  if(altro[a] == 3) continue ; // needed and found; all ok...
1328 
1329  //I want the FEE for easier entry into the bad log...
1330  int fee = tpx_altro_to_fee(rb+1,a) ;
1331 
1332  if(altro[a] == 1) { // needed but missing
1333  int overriden = 0 ;
1334 
1335  for(int i=0;i<over;i++) {
1336  if((a == should_be[i]) || (a == (should_be[i]+1))) {
1337  LOG(WARN,"Sector %2d, RDO %d: ALTRO %3d missing but was overriden: status 0x%X",sector,rb+1,a,altro[a]) ;
1338  overriden = 1 ;
1339  break ;
1340  }
1341  }
1342 
1343  if(overriden) continue ;
1344 
1345 
1346  LOG(ERR,"msc: Sector %2d, RDO %d: ALTRO %3d [FEE %3d] missing: status 0x%X",sector,rb+1,a,fee,altro[a]) ;
1347 
1348  err |= 2 ;
1349  }
1350  else {
1351  LOG(WARN,"msc: Sector %2d, RDO %d: ALTRO %3d [FEE %3d] odd status: status 0x%X",sector,rb+1,a,fee,altro[a]) ;
1352  if((altro[a] & 0xB)==0xB) { // needed, found & error
1353  err |= 2 ;
1354  }
1355  }
1356  }
1357 
1358 
1359  }
1360 
1361 /*
1362  if(err == 2) {
1363  LOG(ERR,"Overriding FEE ID errors return until I fix this!!!") ;
1364  return 0 ;
1365  }
1366 */
1367  return err ;
1368 }
1369 
1370 
1371 // this is the real sector and real RDO (from 0)!
1372 int tpx_analyze_msc(int sector,int rb, char *buff, int *altro_list)
1373 {
1374 // struct tpx_rdo *rdo ;
1375 // rdo = (struct tpx_rdo *) buff ;
1376 
1377  memcpy(&(tpx_rdo[sector-1][rb]),buff,sizeof(struct tpx_rdo)) ;
1378 
1379 
1380  LOG(NOTE,"RDO %d: msc event, should be %d bytes",rb+1,sizeof(struct tpx_rdo)) ;
1381 
1382  return tpx_show_status(sector,1<<rb,altro_list) ;
1383 }
Definition: rb.hh:21
Definition: tpx_rdo.h:4