StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
daq_fgt.cxx
1 #include <sys/types.h>
2 #include <errno.h>
3 #include <assert.h>
4 #include <stdlib.h>
5 
6 #include <rtsLog.h>
7 #include <rtsSystems.h>
8 
9 
10 
11 #include <SFS/sfs_index.h>
12 #include <DAQ_READER/daqReader.h>
13 #include <DAQ_READER/daq_dta.h>
14 
15 
16 #include "daq_fgt.h"
17 
18 
19 const char *daq_fgt::help_string = "FGT\n\
20 adc returns fgt_t;\n\
21 raw returns raw data\n" ;
22 
23 // for FGT proper
25 {
26 public:
28  daq_det_factory::det_factories[FGT_ID] = this ;
29  }
30 
31  daq_det *create() {
32  return new daq_fgt ;
33  }
34 } ;
35 
36 static daq_det_fgt_factory fgt_factory ;
37 
38 
39 // for IST
41 {
42 public:
44  daq_det_factory::det_factories[IST_ID] = this ;
45  }
46 
47  daq_det *create() {
48  daq_det *dd = new daq_fgt ;
49 
50  ((daq_fgt *)dd)->set_flavor(IST_ID) ;
51 
52  return dd ;
53  }
54 } ;
55 
56 static daq_det_ist_factory ist_factory ;
57 
58 // for FST
60 {
61 public:
63  daq_det_factory::det_factories[FST_ID] = this ;
64  }
65 
66  daq_det *create() {
67  daq_det *dd = new daq_fgt ;
68 
69  ((daq_fgt *)dd)->set_flavor(FST_ID) ;
70 
71  return dd ;
72  }
73 } ;
74 
75 static daq_det_fst_factory fst_factory ;
76 
77 // for GMT
79 {
80 public:
82  daq_det_factory::det_factories[GMT_ID] = this ;
83  }
84 
85  daq_det *create() {
86  daq_det *dd = new daq_fgt ;
87 
88  ((daq_fgt *)dd)->set_flavor(GMT_ID) ;
89 
90  return dd ;
91  }
92 } ;
93 
94 static daq_det_gmt_factory gmt_factory ;
95 
96 
97 
98 void daq_fgt::set_flavor(int id)
99 {
100  switch(id) {
101  case IST_ID :
102  rts_id = id ;
103  name = rts2name(rts_id) ;
104  sfs_name = "ist" ;
105  break ;
106  case FST_ID :
107  rts_id = id ;
108  name = rts2name(rts_id) ;
109  sfs_name = "fst" ;
110  break ;
111  case GMT_ID :
112  rts_id = id ;
113  name = rts2name(rts_id) ;
114  sfs_name = "gmt" ;
115  break ;
116  default :
117  rts_id = FGT_ID ;
118  name = rts2name(rts_id) ;
119  sfs_name = "fgt" ;
120  break ;
121  }
122 
123  LOG(DBG,"set_flavor %d [%s]",id,name) ;
124 
125  return ;
126 } ;
127 
128 daq_fgt::daq_fgt(daqReader *rts_caller)
129 {
130  rts_id = FGT_ID ;
131  name = rts2name(rts_id) ;
132  sfs_name = "fgt" ;
133  caller = rts_caller ;
134 
135  if(caller) caller->insert(this, rts_id) ;
136 
137  raw = new daq_dta ;
138  adc = new daq_dta ;
139  zs = new daq_dta ;
140  ped = new daq_dta ;
141 
142 
143  adc->meta = (void *) &apv_meta ; // meta exists for adc data only!
144  zs->meta = (void *) &apv_meta ;
145 
146  LOG(DBG,"%s: constructor: caller %p",name,rts_caller) ;
147  return ;
148 }
149 
150 daq_fgt::~daq_fgt()
151 {
152  LOG(DBG,"%s: DEstructor",name) ;
153 
154  delete raw ;
155  delete adc ;
156  delete zs ;
157  delete ped ;
158 
159  return ;
160 }
161 
162 
163 
164 daq_dta *daq_fgt::get(const char *bank, int sec, int rdo, int pad, void *p1, void *p2)
165 {
166 
167  Make() ;
168 
169  if(present == 0) return 0 ;
170 
171 
172  zs->meta = 0 ;
173  adc->meta = 0 ;
174 
175  if(strcasecmp(bank,"raw")==0) {
176  return handle_raw(sec,rdo) ;
177  }
178  else if(strcasecmp(bank,"adc")==0) {
179  return handle_adc(sec,rdo,0) ;
180  }
181  else if(strcasecmp(bank,"pedrms")==0) {
182  return handle_ped(sec,rdo) ;
183  }
184  else if(strcasecmp(bank,"zs")==0) {
185  return handle_zs(sec,rdo) ;
186  }
187 
188 
189  LOG(ERR,"%s: unknown bank type \"%s\"",name,bank) ;
190  return 0 ;
191 }
192 
193 
194 
195 daq_dta *daq_fgt::handle_raw(int sec, int rdo)
196 {
197  char *st ;
198  int r_start, r_stop ;
199  int bytes ;
200  int s_start, s_stop ;
201 
202  assert(caller) ; // sanity...
203 
204  if(!present) {
205  return 0 ;
206  }
207  else {
208  LOG(DBG,"%s: present %d",name,present) ;
209  }
210 
211  char str[256] ;
212  char *full_name ;
213 
214 
215  if(rdo<=0) {
216  r_start = 1 ;
217  r_stop = 6 ;
218  }
219  else {
220  r_start = r_stop = rdo ;
221  }
222 
223  if(sec<=0) {
224  s_start = 1 ;
225  s_stop = 2 ;
226  }
227  else if(sec>3) {
228  s_start = 1 ;
229  s_stop = 2 ;
230  }
231  else {
232  s_start = s_stop = sec ;
233  }
234 
235 
236  raw->create(8*1024,"fgt_raw",rts_id,DAQ_DTA_STRUCT(char)) ;
237 
238  for(int s=s_start;s<=s_stop;s++) {
239  for(int r=r_start;r<=r_stop;r++) {
240  sprintf(str,"%s/sec%02d/rb%02d/raw",sfs_name, s, r) ;
241  full_name = caller->get_sfs_name(str) ;
242 
243  if(!full_name) continue ;
244  bytes = caller->sfs->fileSize(full_name) ; // this is bytes
245 
246 
247  st = (char *) raw->request(bytes) ;
248 
249  int ret = caller->sfs->read(str, st, bytes) ;
250  if(ret != bytes) {
251  LOG(ERR,"ret is %d") ;
252  }
253 
254 
255  raw->finalize(bytes,s,r,0) ; // sector 0;
256  }
257  }
258 
259  raw->rewind() ;
260 
261  return raw ;
262 
263 }
264 
265 
266 daq_dta *daq_fgt::handle_zs(int sec, int rdo, char *rdobuff, int inbytes)
267 {
268  int r_start, r_stop ;
269 // int s = 1 ; // for now...
270 
271  zs->create(1000,"fgt_zs",rts_id,DAQ_DTA_STRUCT(fgt_adc_t)) ;
272 
273  LOG(NOTE,"FGT: doing ZS") ;
274  memset(&apv_meta,0,sizeof(apv_meta)) ;
275 
276  if((rdo <= 0) || (rdo > FGT_RDO_COU)){
277  r_start = 1 ;
278  r_stop = FGT_RDO_COU ;
279  }
280  else {
281  r_start = r_stop = rdo ;
282  }
283 
284  int found_some = 0 ;
285 
286  for(int s=1;s<=2;s++) {
287  for(int r=r_start;r<=r_stop;r++) {
288  u_short *d ;
289  int bytes ;
290 
291  if(rdobuff == 0) {
292  char str[128] ;
293  char *full_name ;
294 
295  sprintf(str,"%s/sec%02d/rb%02d/zs",sfs_name, s, r) ;
296  full_name = caller->get_sfs_name(str) ;
297 
298  if(!full_name) continue ;
299  bytes = caller->sfs->fileSize(full_name) ; // this is bytes
300 
301  d = (u_short *) malloc(bytes) ;
302 
303  int ret = caller->sfs->read(str, (char *)d, bytes) ;
304  if(ret != bytes) {
305  LOG(ERR,"ret is %d") ;
306  }
307 
308  }
309  else {
310  d = (u_short *) rdobuff ;
311  bytes = inbytes ;
312  }
313 
314  if(d == 0) continue ;
315 
316 
317  int *d32 = (int *) d ;
318 
319  if(d32[0] != (int)0xFEEDBEEF) {
320  LOG(ERR,"Bad signature 0x%04X",d32[0]) ;
321  continue ;
322  }
323 
324 
325  switch(d32[1]) {
326  case META_ZS_VERSION :
327  case META_PED_ZS_VERSION :
328  break ;
329  default :
330  LOG(ERR,"Unknown version 0x%04X",d32[1]) ;
331  continue ;
332  }
333 
334  found_some = 1 ;
335 
336  bytes = d32[2] ;
337 
338  int meta_bytes = d32[3] ;
339 
340 
341 
342  // grab the count of dumped channels from the trailer
343  int dumped_chs = d[bytes/2-1] ;
344  int got_chs = 0 ;
345 
346 
347  // do meta...
348  apv_meta_zs_t *meta_zs = (apv_meta_zs_t *) (d32+4) ;
349 
350 
351  for(int arm=0;arm<FGT_ARM_COU;arm++) {
352  for(int apv=0;apv<FGT_APV_COU;apv++) {
353  if(meta_zs->status[arm][apv]) {
354  apv_meta.arc[r].arm[arm].present = 1 ;
355  apv_meta.arc[r].present = 1 ;
356 
357  apv_meta.arc[r].arm[arm].apv[apv].present = 1 ;
358  apv_meta.arc[r].arm[arm].apv[apv].ntim = meta_zs->tb_cou ;
359 
360  if(meta_zs->status[arm][apv] != 1) {
361  apv_meta.arc[r].arm[arm].apv[apv].error = 1 ;
362  }
363  }
364 
365  }}
366 
367 
368  LOG(NOTE,"Expect %d dumped CHs in %d bytes, meta_bytes %d, tb_cou %d",dumped_chs,bytes,meta_bytes,meta_zs->tb_cou) ;
369 
370 // for(int i=0;i<100;i++) {
371 // LOG(TERR,"%d: 0x%04X",i,d[i]) ;
372 // }
373 
374  int ix = 2*4 + meta_bytes/2 ;
375 
376  bytes -= 4*4 ; // 3 header d-words...
377  bytes -= meta_bytes ; // apv_meta_zs_t ;
378  bytes -= 1*2 ; // 1 trailer s_word
379 
380 // LOG(TERR,"ix %d, bytes left %d",ix,bytes) ;
381 
382  int arc = 0 ;
383  int arm = 0 ;
384  int apv = 0 ;
385 
386  int cou = 0 ;
387 
388  fgt_adc_t *fgt_d = 0 ;
389 
390  while(bytes>0) {
391 
392 
393  while((d[ix] & 0xFF00) == 0xAB00) {
394  //LOG(TERR,"%d %d %d %d",cou,arm,arc,apv) ;
395 
396  if(cou) {
397  //LOG(TERR,"finalize: %d %d %d %d",cou,arm,arc,apv) ;
398  zs->finalize(cou,arm,arc,apv) ;
399  }
400  cou = 0 ;
401 
402  arc = d[ix] & 0xFF ;
403  ix++ ;
404 
405  arm = d[ix] >> 8 ;
406  apv = d[ix] & 0xFF ;
407  ix++ ;
408 
409  bytes -= 4 ;
410 
411  }
412 
413 
414  if(bytes <= 0) continue ;
415 
416  //LOG(TERR,"r: %d %d %d (%d)",arc,arm,apv,cou) ;
417 
418  if(cou==0) {
419  //LOG(TERR,"request: %d %d %d %d",cou,arm,arc,apv) ;
420  fgt_d = (fgt_adc_t *) zs->request(FGT_CH_COU*FGT_TB_COU) ;
421  }
422 
423  int ch = d[ix] & 0xFF ;
424  int tb_cou = d[ix] >> 8 ;
425  ix++ ;
426 
427  got_chs++ ;
428 
429 
430  bytes -= 2*(1+tb_cou) ;
431  for(int i=0;i<tb_cou;i++) {
432  fgt_d[cou].ch = ch ;
433  fgt_d[cou].tb = i ;
434  fgt_d[cou].adc = d[ix] & 0xFFF ; // new: 13 bits
435  fgt_d[cou].flags = d[ix]>>12 ; // new: upper 3 are flags
436  cou++ ;
437 
438  //printf("ZS: %d %d %d %d %d = %d\n",arc,arm,apv,ch,i,d[ix]) ;
439 
440 
441  ix++ ;
442  }
443  }
444 
445  if(cou) {
446  zs->finalize(cou,arm,arc,apv) ;
447 
448  }
449 
450  if(got_chs != dumped_chs) {
451  LOG(ERR,"Mismatch: got %d, expect %d",got_chs,dumped_chs) ;
452  }
453 
454  if(rdobuff == 0) free(d) ;
455 
456  }
457  }
458 
459  zs->rewind() ;
460 
461  if(found_some) {
462  zs->meta = (void *) &apv_meta ;
463  }
464  else {
465  return 0 ;
466  }
467 
468  return zs ;
469 }
470 
471 
472 daq_dta *daq_fgt::handle_adc(int sec, int rdo, char *rdobuff)
473 {
474  int r_start, r_stop ;
475  int s_start, s_stop ;
476 
477  adc->create(1000,"fgt_adc",rts_id,DAQ_DTA_STRUCT(fgt_adc_t)) ;
478 
479  memset(&apv_meta,0,sizeof(apv_meta)) ;
480 
481  LOG(NOTE,"FGT: doing ADC") ;
482 
483  if((rdo <= 0) || (rdo > FGT_RDO_COU)){
484  r_start = 1 ;
485  r_stop = FGT_RDO_COU ;
486  }
487  else {
488  r_start = r_stop = rdo ;
489  }
490 
491  if(sec<=0) {
492  s_start = 1 ;
493  s_stop = 2 ;
494  }
495  else if(sec>3) {
496  s_start = 1 ;
497  s_stop = 2 ;
498  }
499  else {
500  s_start = s_stop = sec ;
501  }
502 
503  int found_some = 0 ;
504 
505  for(int s=s_start;s<=s_stop;s++) {
506  for(int r=r_start;r<=r_stop;r++) {
507  u_int *d ;
508 
509  if(rdobuff == 0) {
510  daq_dta *dd = handle_raw(s,r) ;
511  if(dd == 0) continue ;
512 
513  if(dd->iterate() == 0) continue ;
514 
515  d = (u_int *) dd->Void ;
516  int words = dd->ncontent/4 ;
517 
518  if(words <= 0) continue ;
519 
520  }
521  else {
522  d = (u_int *) rdobuff ;
523  }
524 
525 
526  found_some = 1 ;
527 
528  int format_code = (d[2] >> 8) & 0xFF ;
529  // 0: normal code
530  // 1: test
531  // 2: null
532 
533  int arm_mask = (d[3] >> 8) & 0x3F ;
534  LOG(NOTE,"[evt %d]: RDO %d: ARC Header: format %d, ARM mask 0x%02x",get_global_event_num(),r,format_code,arm_mask);
535 
536  apv_meta.arc[r].present = 1 ;
537  apv_meta.arc[r].format_code = format_code ;
538  apv_meta.arc[r].arm_mask = arm_mask ;
539 
540 
541  u_int *dta = d + 6 ; // start at the 6th word
542 
543  for(int arm=0;arm<FGT_ARM_COU;arm++) {
544  if(arm_mask & (1<<arm)) ;
545  else continue ;
546 
547  LOG(NOTE,"[evt %d]: RDO %d: Handling ARM %d",get_global_event_num(),r,arm) ;
548 
549  // digest the ARM header, word 0
550  int arm_id = *dta & 0x7 ;
551  int arm_seq = (*dta >> 20) & 0xfff;
552  int arm_err = (*dta >>16) & 0xf;
553  dta++ ;
554  // word 1
555  u_int apv_mask = *dta & 0x00FFFFFF ;
556  dta++ ;
557  // word 2, would get monitor register values from this word (not implemented yet, still need to skip over of course)
558  dta++ ;
559 
560  apv_meta.arc[r].arm[arm].present = 1 ;
561  apv_meta.arc[r].arm[arm].arm_id = arm_id ;
562  apv_meta.arc[r].arm[arm].arm_seq = arm_seq ;
563  apv_meta.arc[r].arm[arm].arm_err = arm_err ;
564  apv_meta.arc[r].arm[arm].apv_mask = apv_mask ;
565 
566  LOG(NOTE,"[evt %d]: ARM_ID %d SEQ %d ERR %1x APV_MASK %06x",get_global_event_num(),
567  arm_id,arm_seq,arm_err,apv_mask);
568 
569  if(arm_id != arm) {
570  apv_meta.arc[r].arm[arm].error = 1 ;
571  LOG(ERR,"[evt %d]: RDO %d ARM %d: Bad ARM ID is %d",get_global_event_num(),r,arm,arm_id) ;
572  goto unrecoverable_error ;
573  }
574 
575  if(arm_err != 0) {
576  apv_meta.arc[r].arm[arm].error = 1 ;
577  LOG(ERR,"[evt %d]: RDO %d ARM %d: Error code 0x%x",get_global_event_num(),r,arm,arm_err) ;
578  continue ; // I think we can leave this as a 'recoverable' error for now ??
579  }
580 
581 
582  for(int apv=0;apv<FGT_APV_COU;apv++) {
583  if(apv_mask & (1<<apv)) ;
584  else continue ;
585 
586  LOG(NOTE,"[evt %d]: Handling APV %d",get_global_event_num(),apv) ;
587 
588  int apv_id = *dta & 0x1F ;
589  int fmt = (*dta >> 16) & 0xf ; // promoted to 4 bits on 1/26/2012 (take over reserved=0 bit)
590  int length;
591  if ((fmt==1)||(fmt==2)) // old formats used in run 12 FGT, retired 11/2012
592  length = (*dta >> 5) & 0x3FF ;
593  else
594  length = (*dta >> 5) & 0x7ff ;
595 
596  int seq = (*dta >> 20) & 0xfff;
597 
598  dta++ ;
599 
600  LOG(NOTE," ID %d, length %d, fmt %d",apv_id,length,fmt) ;
601 
602  int capid = *dta & 0xFF ;
603  int nhits = (*dta >> 8) & 0x7F ;
604  int is_error = (*dta >> 15) & 1 ;
605 
606  int refadc,ntim,is_0;
607  if ((fmt==1)||(fmt==2)) { // old formats used in run 12 FGT, retired 11/2012
608  refadc = (*dta >> 16) & 0xFFF ;
609  ntim = (*dta >> 28) & 0x7 ;
610  is_0 = *dta & 0x80000000 ;
611  }
612  else {
613  refadc = (*dta >> 16) & 0x7FF ;
614  ntim = (*dta >> 27) & 0x1f ;
615  is_0 = 0 ;
616  }
617 
618 
619  dta++ ;
620 
621  nhits = ( ntim>0 ? nhits+1 : 0 ); // nhits (range 0-128) is encoded like this in 7-bit nhits field and ntim field
622 
623  LOG(NOTE," capid %d, nhits %d, is_error 0x%X, refadc %d, ntim %d, is_0 0x%X",
624  capid, nhits, is_error, refadc, ntim, is_0) ;
625 
626  apv_meta.arc[r].arm[arm].apv[apv].present = 1 ;
627 
628  apv_meta.arc[r].arm[arm].apv[apv].apv_id = apv_id ;
629  apv_meta.arc[r].arm[arm].apv[apv].fmt = fmt ;
630  apv_meta.arc[r].arm[arm].apv[apv].length = length ;
631  apv_meta.arc[r].arm[arm].apv[apv].seq = seq ;
632  apv_meta.arc[r].arm[arm].apv[apv].capid = capid ;
633  apv_meta.arc[r].arm[arm].apv[apv].nhits = nhits ;
634  apv_meta.arc[r].arm[arm].apv[apv].is_error = is_error ;
635  apv_meta.arc[r].arm[arm].apv[apv].refadc = refadc ;
636  apv_meta.arc[r].arm[arm].apv[apv].ntim = ntim ;
637 
638  // sanity checks
639  if(apv != apv_id) {
640  apv_meta.arc[r].arm[arm].apv[apv].error = 1 ;
641  LOG(ERR,"[evt %d]: RDO %d ARM %d APV %d: Bad APV ID, got %d",get_global_event_num(),r,arm,apv,apv_id) ;
642  goto unrecoverable_error ;
643  }
644 
645  if(seq != arm_seq) {
646  // In old test stand data (before ARM firmware r67) we have wrong sequence numbers
647 #if 0
648  LOG(WARN,"[evt %d]: RDO %d ARM %d APV %d: Sequence number mismatch, expect %d have %d",get_global_event_num(),r,arm,apv,arm_seq,seq);
649 #else
650  apv_meta.arc[r].arm[arm].apv[apv].error = 1 ;
651  LOG(ERR,"[evt %d]: RDO %d ARM %d APV %d: Sequence number mismatch, expect %d have %d",get_global_event_num(),r,arm,apv,arm_seq,seq);
652  goto unrecoverable_error ;
653 #endif
654  }
655 
656  if((ntim < 0) || (ntim > 31)) { // 0 is a valid value (used to encode NHITS=0)
657  apv_meta.arc[r].arm[arm].apv[apv].error = 1 ;
658  LOG(ERR,"Ntim %d ?!",ntim) ;
659  continue ;
660  }
661  if((fmt != 1)&&(fmt != 2)&&(fmt != 3)) {
662  apv_meta.arc[r].arm[arm].apv[apv].error = 1 ;
663  LOG(ERR,"Invalid FMT %d (evt %d)",fmt,get_global_event_num()) ;
664  continue ;
665  }
666 
667 
668  // set of Gerard's hadrcoded hacks...
669  if (fmt==1) { // applies ONLY in fmt 1, which is retired 7/23/2012 [was used for all run 12 operations]
670  // [Gerard]: Modified "my" hardcoded hacks so it would work regardless of which APV's (except #23) are used, despite that the length code is not properly filled in.
671  // This is necessary to support present cosmic ray test setup at STAR, original plan was no good (I forgot we would need different APV channels to support the other half of quadrant readout).
672  // This here remains still quite a hack, I must fix the length code but that is slightly nontrivial for today
673  // This will fail perhaps very occasionally if the data word is just exactly right to make it fail... pretty unlikely I hope!
674  // It also fails if ever APV #23 is recognized / non-truncated. That shouldn't happen, of course (in FGT! not IST!)
675  if (length==2) // i.e. nothing but 2 header words in this record
676  continue; //here paving the way for the length hack to be removed, this should remain working, for non-ZS data at least
677  if (apv==23) {
678  dta += 3;
679  continue;
680  }
681  u_long expect0 = *(dta-2);
682  expect0 = (expect0 & 0xffffffe0)|((expect0+1) & 0x0000001f); // increment just the APV id
683  u_long expect1 = *(dta-1);
684  // look for the signature of a skipped APV -- the expected header for next APV found at dta+3 !!
685  // of course, it could be a fluke, then we will mess up, accept that risk
686  if((*(dta+3)==expect0) && (*(dta+4)==expect1)) {
687  dta += 3 ;
688  continue ;
689  }
690  }
691  // END of the hacks to deal with skipped APV's
692 
693  fgt_adc_t *fgt_d = (fgt_adc_t *) adc->request(FGT_TB_COU*FGT_CH_COU) ;
694  int cou = 0 ;
695 
696  // extract data here...
697 
698  u_short *d16 = (u_short *) dta ;
699 
700  u_short wfm[((2047-2)/3)*8] ; // worst case wfm length (from header max length value 2047)
701  int i = 0 ;
702 
703  // it is important to note, this is specifically for the non-ZS formats, and the length will always be of form 2+3*n
704  for(int j=0;j<((length-2)/3)*2;j++) {
705  u_short wtmp ;
706 
707  wfm[4*j] = 0x0fff & d16[i] ;
708 
709  wtmp = 0x000f & (d16[i++] >> 12) ;
710 
711  wfm[4*j + 1] = (0x0ff0 & (d16[i]<<4)) | wtmp ;
712 
713  wtmp = 0x00ff & (d16[i++] >> 8) ;
714 
715  wfm[4*j+2] = (0x0f00 & (d16[i]<<8)) | wtmp ;
716  wfm[4*j+3] = 0x0fff & (d16[i++]>>4) ;
717  }
718 
719  dta += (length - 2) ; // skip "length" words - 2 for the header
720 
721  /*
722  u_int *o_dta = dta ;
723  dta = (u_int *)(d16 + i) ;
724 
725  LOG(TERR,"Diff %d",dta-o_dta) ;
726  */
727 
728  if ((ntim>0) && ( 27+127+(ntim-1)*140 >= ((length-2)/3)*8 )) {
729  apv_meta.arc[r].arm[arm].apv[apv].error = 1 ;
730  LOG(ERR,"[evt %d]: RDO %d ARM %d APV %d: Trouble in APV block content, it's shorter than required to unpack %d timebins",
731  get_global_event_num(),r,arm,apv,ntim);
732  continue; // this is a recoverable error
733  }
734  for(int ch=0;ch<128;ch++) {
735  int rch = 32*(ch%4) + 8*(ch/4) - 31*(ch/16) ; // see APV user guide (channel mux sequence)
736  for(int tb=0;tb<ntim;tb++) { // note that ntim=0 in case of skipped APV in format 1 or 2 (non-ZS)
737 
738  int adc = wfm[27+ch+tb*140] ;
739  fgt_d[cou].ch = rch ;
740  fgt_d[cou].tb = tb ;
741  fgt_d[cou].adc = adc ;
742  fgt_d[cou].flags = 0 ;
743  cou++ ;
744  }
745  }
746 
747  // note the reversal: sector->arm, row->rdo,
748  if (nhits>0)
749  adc->finalize(cou, arm, r, apv) ;
750 
751  }
752 
753  }
754  continue;
755 unrecoverable_error:
756  apv_meta.arc[r].error = 1 ;
757  LOG(WARN,"[evt %d]: RDO %d: Cannot reliably recover pointer to next item, dropping the rest of this event on this rdo",
758  get_global_event_num(),r);
759  }
760  }
761 
762  adc->rewind() ;
763 
764  if(found_some) {
765  adc->meta = (void *) &apv_meta ;
766  }
767  else {
768  return 0 ;
769  }
770 
771 
772 
773  return adc ;
774 
775 }
776 
777 daq_dta *daq_fgt::handle_ped(int sec, int rdo)
778 {
779 
780  ped->create(1000,"fgt_pedrms",rts_id,DAQ_DTA_STRUCT(fgt_pedrms_t)) ;
781 
782 
783  char str[128] ;
784  char *full_name ;
785  int bytes ;
786  u_short *d ;
787 
788  sprintf(str,"%s/sec%02d/pedrms",sfs_name, 1) ;
789  full_name = caller->get_sfs_name(str) ;
790 
791  if(full_name) {
792  LOG(TERR,"full_name %s",full_name) ;
793  }
794 
795  if(!full_name) return 0 ;
796  bytes = caller->sfs->fileSize(full_name) ; // this is bytes
797 
798  LOG(TERR,"bytes %d",bytes) ;
799 
800  d = (u_short *) malloc(bytes) ;
801 
802  int ret = caller->sfs->read(str, (char *)d, bytes) ;
803  if(ret != bytes) {
804  LOG(ERR,"ret is %d") ;
805  }
806 
807 
808  if(d[0] != 0xBEEF) {
809  LOG(ERR,"Bad pedestal version") ;
810  }
811 
812  int is_fst = 0 ;
813 
814  switch(d[1]) {
815  case 1 : // old, non FST
816  break ;
817  case 2 :
818  is_fst = 1 ;
819  break ;
820  default :
821  LOG(ERR,"Bad pedestal version 0x%X",d[1]) ;
822  break ;
823  }
824 
825 // int arm_cou = d[2] ;
826 // int apv_cou = d[3] ;
827  int ch_cou = d[4] ;
828  int tb_cou = d[5] ;
829 
830  int ix = 6 ;
831  int max_ix = (bytes/2) ;
832 
833  fgt_pedrms_t *f_ped = 0 ;
834 
835  while(ix < max_ix) {
836  int arc = d[ix++] ;
837  int apvs = d[ix++] ;
838 
839  while(apvs) {
840  int arm = d[ix++] ;
841  int apv = d[ix++] ;
842 
843  f_ped = (fgt_pedrms_t *) ped->request(ch_cou * tb_cou) ;
844 
845  int cou = 0 ;
846  for(int ch=0;ch<ch_cou;ch++) {
847  for(int t=0;t<tb_cou;t++) {
848  u_short ped = d[ix++] ;
849  u_short rms = d[ix++] ;
850  u_short cmn_rms ;
851 
852  if(is_fst) { // SPECIAL
853  cmn_rms = d[ix++] ;
854  }
855  else cmn_rms = 0 ;
856 
857  f_ped[cou].ch = ch ;
858  f_ped[cou].tb = t ;
859  f_ped[cou].ped = ((float)ped) / 16.0 ;
860  f_ped[cou].rms = ((float)rms) / 16.0 ;
861  f_ped[cou].cmn_rms = ((float)cmn_rms) / 16.0 ;
862  cou++ ;
863  }
864  }
865 
866  ped->finalize(cou,arm,arc,apv) ;
867  apvs-- ;
868  }
869 
870  }
871 
872  free(d) ;
873 
874  ped->rewind() ;
875 
876 
877  return ped ;
878 
879 
880 
881 }
882 
883 
884 
885 
886 // used to grab trigger info from the event header
887 int daq_fgt::get_l2(char *buff, int words, struct daq_trg_word *trg, int rdo)
888 {
889  const int FGT_BYTES_MIN = ((6)*4) ; // this is the minimum
890  const int FGT_BYTES_MAX = (512*1024) ;
891 // const u_int FGT_VERSION = 0x0034 ;
892  const u_int FGT_SIGNATURE = 0x46475420 ; // "FGT"
893 
894  int t_cou = 0 ;
895  int bad = 0 ;
896  u_int *d32 = (u_int *)buff ;
897  int id_check_failed = 0 ;
898 // int last_ix = words - 1 ;
899 
900  // FIRST we check the length
901  int buff_bytes = 4 * words ;
902 
903  if((buff_bytes < FGT_BYTES_MIN) || (buff_bytes > FGT_BYTES_MAX)) {
904  LOG(ERR,"RDO %d: expect %d bytes, received %d",rdo,FGT_BYTES_MIN,buff_bytes) ;
905  bad |= 1 ;
906  }
907 
908 
909  // grab crc from the last word
910 
911  // misc signatures and errors from the header
912  if(d32[1] != FGT_SIGNATURE) { // "FGT"
913  LOG(ERR,"RDO %d: bad header sig 0x%08X, expect 0x%08X",rdo,d32[1], FGT_SIGNATURE) ;
914  bad |= 1 ;
915  }
916 
917  if(d32[5] != 0xFEEDBEEF) { // deadface
918  LOG(ERR,"RDO %d: bad FEEDBEEF 0x%08X",rdo,d32[5]) ;
919  bad |= 1 ;
920  }
921 
922 
923  /* wait for it to stabilize
924  if((d32[2] >> 16) != FGT_VERSION) {
925  LOG(ERR,"RDO %d: bad version 0x%04X, expect 0x%04X",rdo,d32[2] >> 16, FGT_VERSION) ;
926  bad |= 2 ; // soft error
927 
928  }
929  */
930 
931  if((d32[3] & 0xFFFF0000)) { // error_flags
932  LOG(ERR,"RDO %d: error flags 0x%04X",rdo,d32[3]>>16) ;
933  bad |= 2 ;
934  }
935 
936 
937 // int arm_mask = (d32[3]>>8) & 0x3F ;
938 
939 
940  int rdo_in_dta = d32[3] & 0xFF ; // fiber ID via jumpers...
941  if(rdo_id[rdo] != 0xFF) {
942  if(rdo_id[rdo] != rdo_in_dta) {
943  id_check_failed++ ;
944  }
945  }
946 
947 
948  LOG(NOTE,"RDO %d: expect %d, in data %d",rdo,rdo_id[rdo],rdo_in_dta) ;
949 
950 
951  int format_code = (d32[2] >> 8) & 0xFF ;
952  if(format_code == 0x02) { // null event
953  LOG(WARN,"RDO %d: format code 0x%X? (null event)",rdo,format_code) ;
954 
955 // trg[0].t = 4097 ;
956 // trg[0].daq = 0 ;
957 // trg[0].trg = 0 ;
958 // trg[0].rhic = d32[4] ;
959 
960 // return 1 ;
961 
962  }
963 
964 #if 0
965 #define G_CONST 0x04C11DB7
966 
967  u_int crc_in_data = d32[last_ix] ;
968  register u_int crc = 0xFFFFFFFF ;
969  if(crc_in_data) {
970  for(int i=0;i<last_ix;i++) {
971  u_int datum ;
972 
973  datum = d32[i] ;
974  register u_int data_j ;
975  register u_int crc_31 ;
976 
977  for(register int j=31;j>=0;j--) {
978  data_j = (datum >> j) & 1 ;
979  crc_31 = (crc & 0x80000000) ? 1 : 0 ;
980 
981  if(crc_31 == data_j) {
982  crc = (crc<<1) ^ G_CONST ;
983  }
984  else {
985  crc = (crc<<1) ;
986  }
987  }
988  }
989 
990  if(crc != crc_in_data) {
991  LOG(ERR,"RDO %d: CRC in data 0x%08X, CRC calculated 0x%08X",rdo,crc_in_data,crc) ;
992  bad |= 1 ;
993  }
994  }
995 
996  LOG(DBG,"RDO %d: CRC in data 0x%08X, CRC calculated 0x%08X",rdo,crc_in_data,crc) ;
997 #endif
998 
999 
1000  // L0 part
1001  t_cou = 0 ;
1002  trg[t_cou].t = d32[0] & 0xFFF ;
1003  trg[t_cou].daq = d32[2] & 0xF ;
1004  trg[t_cou].trg = (d32[2] >> 4) & 0xF ;
1005  trg[t_cou].rhic = d32[4] ;
1006  t_cou++ ;
1007 
1008 
1009  LOG(NOTE,"RDO %d: words %d: token %d, trg %d, daq %d: rhic %u: rdo_in_data %d, format_code 0x%X",rdo,words,
1010  trg[0].t, trg[0].trg, trg[0].daq, trg[0].rhic,
1011  rdo_in_dta,format_code) ;
1012 
1013 
1014  // check token and trg_cmd sanity...
1015  if(trg[0].t == 0) {
1016  LOG(ERR,"RDO %d: token 0?",rdo) ;
1017  trg[0].t = 4097 ; // turn it to sanity!
1018  bad |= 2 ;
1019  }
1020 
1021  switch(trg[0].trg) {
1022  case 4 :
1023  break ;
1024  default :
1025  LOG(ERR,"RDO %d: bad trg_cmd %d",rdo, trg[0].trg) ;
1026  // sanitize
1027  trg[0].t = 4097 ;
1028  bad |= 2 ;
1029  break ;
1030  }
1031 
1032 #if 0 // skip for the temporary 0x8129 V
1033 
1034  // get mesg_length
1035  int mesg_length = d32[last_ix-1] & 0xFFF ; // 12 bits only
1036  if(mesg_length > 30) {
1037  LOG(ERR,"RDO %d: bad trigger length %d",rdo,mesg_length) ;
1038  // kill it! this will make the main length bad too
1039  mesg_length = 0 ;
1040  bad |= 2 ;
1041  }
1042 
1043  for(int i=0;i<mesg_length;i++) {
1044  u_int trg_data = d32[last_ix - 2 - i] ;
1045 
1046 
1047 
1048  trg[t_cou].t = (trg_data >> 8) & 0xFFF ;
1049  trg[t_cou].trg = (trg_data >> 4) & 0xF ;
1050  trg[t_cou].daq = trg_data & 0xF ;
1051  trg[t_cou].rhic = (trg_data >> 20) & 0x7FF ;
1052 
1053 
1054  // check the triggers here!
1055  if(trg_data & 0x80000000) {
1056  LOG(ERR,"RDO %d: FIFO limit 0x%08X",rdo,trg_data) ;
1057  bad |= 2 ;
1058  }
1059 
1060 
1061  // need some sane limit here on t_cou
1062  if(t_cou >= 120) {
1063  LOG(ERR,"RDO %d: too many triggers %d",rdo,t_cou) ;
1064  bad |= 2 ;
1065  break ;
1066  }
1067 
1068  t_cou++ ;
1069  }
1070 
1071 
1072 // int trailer_event = d32[last_ix - 2 - mesg_length] & 0xFFFF ;
1073 
1074 
1075 // if(trailer_event != d32[0]) {
1076 // LOG(ERR,"RDO %d: bad trailer event 0x%08X != header 0x%08X",rdo,trailer_event,d32[0]) ;
1077 // bad |= 2 ;
1078 // }
1079 #endif
1080 
1081 
1082 
1083  if(bad) {
1084  LOG(WARN,"RDO %d: words %d: bad %d:",rdo,words,bad) ;
1085  // dump the whole header
1086  for(int i=0;i<10;i++) {
1087  LOG(WARN,"\tRDO %d: %4d: 0x%08X",rdo,i,d32[i]) ;
1088  }
1089  // dump last 4 words of the trailer as well
1090  for(int i=(words-4);i<words;i++) {
1091  LOG(WARN,"\tRDO %d: %4d: 0x%08X",rdo,i,d32[i]) ;
1092  }
1093 
1094  }
1095  else if(trg[0].trg==11) { // special test pattern!
1096  int bad_cou = 0;
1097  int shutup = 0 ;
1098  for(int i=10;i<2410;i++) {
1099  u_int should ;
1100  u_int b31, b21, b1, b0 ;
1101 
1102  b31 = (t_data >> 31) & 1 ;
1103  b21 = (t_data >> 21) & 1 ;
1104  b1 = (t_data >> 1) & 1 ;
1105  b0 = (t_data >> 0) & 1 ;
1106 
1107  should = !(b31 ^ b21 ^ b1 ^b0) ;
1108  should = (t_data << 1) | should ;
1109 
1110  if(d32[i] != t_data) {
1111  if(!shutup) LOG(WARN,"word %4d: should 0x%08X, is 0x%08X",i,t_data,d32[i]) ;
1112  bad_cou++ ;
1113  }
1114 
1115  if(bad_cou > 2) shutup = 1 ;
1116 
1117  should = !(b31 ^ b21 ^ b1 ^b0) ;
1118  should = (t_data << 1) | should ;
1119 
1120  t_data = should ;
1121 
1122  }
1123 
1124  if(bad_cou) LOG(ERR,"RDO %d: bad locations %d",rdo,bad_cou) ;
1125  }
1126 
1127  if(bad & 1) { // critical errors
1128  return 0 ; // no trigger!
1129  }
1130  else {
1131 
1132  if(id_check_failed) {
1133  rdo_warns[rdo]++ ;
1134  if(rdo_warns[rdo] < 15) {
1135  LOG(CAUTION,"RDO %d: rdo check failed: expect 0x%02X, found 0x%02X",
1136  rdo,rdo_id[rdo],rdo_in_dta) ;
1137  }
1138  }
1139 
1140  return t_cou ;
1141  }
1142 }
1143 
1144