StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
fcfClass.cxx
1 /*
2  This code is property of Brookhaven National Laboratory, USA.
3  Authored by Tonko Ljubicic.
4 
5  No modifications are to be made without the express consent of
6  the author.
7 
8  Version 5.31 12/14/2004 undef-ed FCF_NEW_ADC_ROUNDOFF
9  Version 5.30 Added ADC roundoff
10  Version 5.21 General Cleanup
11  Version 5.20 Added ADC cluster back-annotation if defined
12  Version 5.12 Added track ID
13  Version 5.11 Production for FY04
14  Version 5.00 07/11/2003 Many small fixes
15  Version 4.31 11/19/2002 Still fixing on I960s...
16  Version 4.30 11/13/2002 Re-implemented Gain & T0
17  They are now mandated!
18  Version 4.20 08/08/2002 Gain correction explicitly included
19  Version loaded into /RTS/src/FCF on 08/09/02
20 
21  Version 4.10 05/31/2002 pad-to-pad T0 corrections added
22  Version 4.01 05/31/2002 Small bug fixes..
23  Version 4.00 05/20/2002 50 Hz - really good!
24  Version 3.00 01/15/2002 Major revamp
25  Version 3.10 01/16/2002 Revamped major internal strucutres
26  Version 3.12 01/17/2002 Minor tweaks and redefinitions...
27  Version 3.13 02/27/2002 Added maxClusters protection
28 */
29 
30 #include <stdio.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <stdlib.h>
34 #include <stdarg.h>
35 #include <ctype.h>
36 
37 #define FCF_VERSION "5.31"
38 
39 
40 
41 #include <rts.h>
42 #include <rtsSystems.h>
43 #include <fcfClass.hh>
44 
45 static const char *fcf_cvs_revision = "$Revision: 1.7 $" ;
46 
47 #ifdef __ROOT__ // STAR Offline
48 
49 #include "StDaqLib/TPC/trans_table.hh"
50 
51 #define FCF_10BIT_ADC // ADC data is already in 10 bits!
52 #define LOG(x1,x2,x3,x4,x5,x6,x7)
53 
54 //#define FCF_NEW_ADC_ROUNDOFF
55 
56 #else
57 
58 #include <rtsLog.h>
59 
60 #endif
61 
62 
63 
64 //static u_int delta[20] ;
65 
66 
67 
68 
69 
70 #if __GNUC__ == 2 && __GNUC_MINOR__ < 8
71 #pragma align 1
72 #pragma pack 1
73 #endif
74 
75 struct fcfResx { // 5 words or 7 if EXTENTS are defined...
76  int t ; // this may occasionally be negative!
77  u_int charge ;
78  u_int scharge ;
79 
80  u_short flags ; // short
81  short mean ; // short
82 
83  u_int pad ;
84 
85  u_short t1, t2, p1, p2 ; // extents
86 
87 #if defined(FCF_SIM_ON) || defined(FCF_ANNOTATE_CLUSTERS)
88  // new - test only...
89  u_int pix ; // pixel count
90  u_int adc_max ; // maximum adc
91 
92  short id ; // sim. id
93  u_short cl_id ; // global cluster id!
94 #endif
95 
96 } ;
97 
98 #if __GNUC__ == 2 && __GNUC_MINOR__ < 8
99 #pragma pack 0
100 #pragma align 0
101 #endif
102 
103 
104 
105 
106 
107 #if defined(__unix) || defined(__APPLE__)
108 
109 
110 #define FCF_MAX_RES_COU_FAST 8
111 
112 #define preburst4(x) // meaningless for UNIX
113 
114 #define FCF_960_R8
115 #define FCF_960_R9
116 #define FCF_960_R10
117 #define FCF_960_R11
118 #define FCF_960_R13
119 
120 // simulation global
121 #ifdef FCF_SIM_ON
122 static u_int *simout ;
123 static fcfPixAnnotate pixStruct[183][512];
124 #endif
125 
126 
127 #ifdef FCF_ANNOTATE_CLUSTERS
128 // annotation data - GLOBAL!
129 
130 #ifndef __ROOT__
131 struct fcfPixAnnotate fcfPixA[45][182][512] ;
132 #endif
133 
134 #endif
135 
136 
137 
138 #else // I960
139 
140 
141 #include "mzGlobal.h"
142 #include "mzInlines.h"
143 #include "mzFastTimer.h"
144 
145 
146 #define FCF_MAX_RES_COU_FAST ((sizeof(fastMem->fcfStore)/sizeof(struct fcfResx))/2)
147 
148 #define FCF_960_R8 asm ("r8")
149 #define FCF_960_R9 asm ("r9")
150 #define FCF_960_R10 asm ("r10")
151 #define FCF_960_R11 asm ("r11")
152 #define FCF_960_R13 asm ("r13")
153 
154 
155 
156 #endif // UNIX
157 
158 
159 extern __inline volatile void mstore(struct fcfResx *rr, int av, int ch, u_int mean, u_int flags)
160 {
161 
162  rr->t = av ;
163  rr->charge = rr->scharge = ch ;
164 
165  rr->flags = flags ;
166  rr->mean = mean ;
167 
168  return ;
169 }
170 
171 
172 
173 // Returns the total length of words (4bytes) used in outres
174 // including the row and cluster count.
175 // Since the row and cluster count makes 2 words the routine returns
176 // 2 in case of no clusters found!
177 
178 int fcfClass::finder(u_char *adcin, u_short *cppin, u_int *outres)
179 {
180  int i, j, pad ;
181  int next_pad ;
182  u_int start_flags ;
183 
184  chargeMinCorrect = chargeMin * FCF_GAIN_FACTOR ;
185 
186  int new_res_ix, new_res_cou, old_res_cou ;
187 
188 
189  u_int *cl_found_pointer, *row_pointer ;
190 
191 
192  struct fcfResx **new_res, **old_res ;
193 
194 
195  row_pointer = outres++ ; // mark the row
196  cl_found_pointer = outres++ ; // mark the count
197 
198  *cl_found_pointer = 0 ;
199  *row_pointer = row ;
200 
201 
202 #ifdef FCF_SIM_ON
203  u_int *sim_found_ptr, *sim_row_ptr ;
204  short *simin ;
205 
206  simin = simIn ; // copy the originals
207  simout = simOut ;
208 
209  if(simin && simout) {
210  sim_row_ptr = simout++ ;
211  sim_found_ptr = simout++ ;
212 
213  *sim_found_ptr = 0 ;
214  *sim_row_ptr = row ;
215  }
216  else {
217  simout = 0 ;
218  // WATCH IT!
219  sim_found_ptr = simout ;
220  sim_row_ptr = simout ;
221  }
222 
223  u_short cl_id = 1 ; // start global cluster id with 1
224  memset(pixStruct,0,sizeof(pixStruct)) ;
225 
226 #endif
227 
228 
229  new_res_ix = 0 ;
230  new_res_cou = old_res_cou = 0 ;
231 
232 
233  new_res = old_res = NULL ;
234  next_pad = 0 ;
235 
236 // memset(delta,0,sizeof(delta)) ;
237 
238 
239 
240 
241  for(pad=padStart;pad<=padStop;pad++) {
242  u_int GC ; // gain correction
243  int T0C ; // T0 correction
244 
245  // gain and t0 corrections!
246  GC = gainCorr[pad] ;
247  T0C = t0Corr[pad] ;
248 
249  if(startFlags) {
250  start_flags = startFlags[pad] ;
251  }
252  else {
253  start_flags = 0 ;
254  }
255 
256  if(GC == 0) {
257  //LOG(WARN,"Gain Correction 0 on row %d, pad %d - skipping!",row,pad,0,0,0) ;
258  continue ;
259  }
260 
261  //LOG(WARN,"row %d, pad %d, GC %d, T0C %d",row,pad,GC,T0C,0) ;
262 
263 // u_int mark = mzFastTimerMark() ;
264 
265 
266 #if defined(__unix) || defined(__APPLE__)
267  static u_int cppStore[32] ;
268  u_int *ptrs = cppStore ;
269 #else
270  u_int *ptrs = fastMem->cppStore ;
271 #endif
272  register u_int *ptrs_r = ptrs ;
273  register u_int *cpp_r = (u_int *)((char *)cppin + cppOff[pad]) ;
274  register u_int fe00 = 0xFE00FE00 ;
275 
276  u_int *ptrs_end = ptrs_r + 31 ;
277 
278 
279  //LOG(DBG,"cppin 0x%X, cpp_off[] 0x%X, cpp_r 0x%X, cpp_off 0x%X",cppin,cpp_off[pad],cpp_r,cpp_off,0) ;
280 
281  while(ptrs_r < ptrs_end) {
282  //asm("#tada") ;
283 
284 
285  register unsigned int first FCF_960_R8 ;
286  register unsigned int second FCF_960_R9 ;
287  register unsigned int third FCF_960_R10 ;
288  register unsigned int fourth FCF_960_R11 ;
289 
290  preburst4(cpp_r) ; // this guy puts the results in r8 and r9!!!
291 #if defined(__unix) || defined(__APPLE__)
292  first = *cpp_r ;
293  second = *(cpp_r+1) ;
294  third = *(cpp_r+2) ;
295  fourth = *(cpp_r+3) ;
296  //LOG(DBG,"%X %X %X %X",first,second,third,fourth,0) ;
297 #endif
298  if(first & fe00) goto go_out ;
299  *ptrs_r++ = first ;
300 
301  if(second & fe00) goto go_out ;
302  *ptrs_r++ = second ;
303 
304  if(third & fe00) goto go_out ;
305  *ptrs_r++ = third ;
306 
307  if(fourth & fe00) goto go_out ;
308  *ptrs_r++ = fourth ;
309 
310  cpp_r += 4 ;
311  }
312 
313  // NOTICE! go-to label!
314  go_out : ;
315 
316  u_int cou_ptrs = (ptrs_r - ptrs) ;
317 
318  //LOG(DBG,"Running pad %d with %d clusters, pad %d had %d protoclusters...",pad,cou_ptrs,next_pad-1,new_res_cou,0) ;
319 
320  if(cou_ptrs == 0) {
321  continue ; // continue with the next pad...
322  }
323 
324 
325 
326 #ifdef FCF_10BIT_ADC
327  u_short *val = (u_short *)((char *)adcin + adcOff[pad]) ;
328 #else
329  u_char *val = (u_char *)((char *)adcin + adcOff[pad]) ;
330 #endif
331 
332 #ifdef FCF_SIM_ON
333  u_short *simval ;
334  if(simout) {
335  simval = (u_short *)((char *)simin + adcOff[pad]) ;
336  }
337  else {
338  simval = 0 ;
339  }
340 #endif
341 
342  if((next_pad != pad) && new_res_cou) { // we skipped a pad and there
343  // was some stuff remaining!
344  // so we have to flush it out
345  int wrote ;
346 
347  // check for space!
348  if((*cl_found_pointer + new_res_cou) >= maxClusters) {
349  LOG(ERR,"Too many clusters in pad %d - breaking!",pad,0,0,0,0) ;
350  return outres - row_pointer ;
351  }
352 
353  //LOG(WARN,"Pad skipped: this %d, expect %d, res count %d",pad,next_pad,new_res_cou,0,0) ;
354 
355  // could be less than requested due to cuts...
356  wrote = saveRes(new_res, new_res_cou, outres) ;
357  outres += wrote*2 ; // occupies 8 bytes (2 words)
358  *cl_found_pointer += wrote ;
359 
360 #ifdef FCF_SIM_ON
361  if(simout) {
362  *sim_found_ptr += wrote ;
363  }
364 #endif
365  // since we skipped a pad and stored the old results we must zap the old results, V4.01
366  new_res_cou = 0 ;
367  }
368 
369 
370  // swap the banks...
371  if(new_res_ix == 1) {
372  new_res_ix = 0 ;
373 
374  old_res = resx[1] ;
375  new_res = resx[0] ;
376 
377  }
378  else {
379  new_res_ix = 1 ;
380 
381  old_res = resx[0] ;
382  new_res = resx[1] ;
383 
384  }
385 
386  old_res_cou = new_res_cou ; // the last guys are the old guys now...
387  new_res_cou = 0 ; // start from scratch for the expected guys
388 
389 
390 // delta[0] = mzFastTimerDelta(mark) ;
391 
392 
393  u_short *ptrs_16 = (u_short *)ptrs ;
394  u_int cl_counter ;
395 
396  for(cl_counter=0;cl_counter<cou_ptrs;cl_counter++) {
397  register u_int start, stop ;
398 
399  start = (u_int)*ptrs_16++ ;
400  stop = (u_int) *ptrs_16++ ;
401 
402  // paranoia
403  // don;t need this anymore
404  //stop &= 0x1FF ;
405 
406  //LOG(DBG,"Cluster %d: start %d, stop %d",cl_counter,start,stop,0,0) ;
407 
408  // ignore certain ranges
409  // Tonko, 04/11/03 modified
410  if(start < timebinLo) start = timebinLo ;
411  if(stop > timebinHi) stop = timebinHi ;
412  if(stop < start) continue ;
413 
414 
415  //if((stop < timebinLo) || (start >= timebinHi)) {
416  // //LOG(WARN,"Ignoring cluster start %d, stop %d",start,stop,0,0,0) ;
417  // continue ;
418  //}
419 
420 
421 
422  //asm("#first") ;
423 #ifdef FCF_10BIT_ADC
424  register u_short *adc_p = val + start ;
425  register u_short *adc_end = val + stop + 1;
426 #else
427  register u_char *adc_p = val + start ;
428  register u_char *adc_end = val + stop + 1;
429 #endif
430 
431 #ifdef FCF_SIM_ON
432  u_short *sim_p ;
433  u_short sim_id ;
434 
435  if(simout) {
436  sim_p = simval + start ;
437  sim_id = *sim_p++ ;
438  }
439  else {
440  sim_p = 0 ;
441  sim_id = 0 ;
442  }
443 #endif
444 
445  register int flags = FCF_ONEPAD | start_flags ;
446  register int adc = *adc_p++ ;
447 
448  // move these to registers....
449  register int min_adc = minAdcT ;
450 #ifndef FCF_10BIT_ADC
451  register u_short *adc8to10 FCF_960_R13 = a8to10 ;
452 #endif
453 
454  //LOG(WARN,"Pad %d, cl %d, len %d",pad,cl_counter,stop-start+1,0,0) ;
455 
456  //delta[1] = mzFastTimerDelta(mark) ;
457  do {
458  register int last_falling = 0 ;
459  register int max_a = 0 ;
460  register int mean FCF_960_R11 = 0 ;
461  register u_int charge FCF_960_R9 = 0 ;
462  register int av FCF_960_R8 = 0 ;
463 
464  register int last_a = 0 ;
465 
466 #ifdef FCF_SIM_ON
467  int max_sim = sim_id ;
468 #endif
469 
470 
471  stop = start ; // necessary for the EXTENETS calc
472 
473  //delta[1] = mzFastTimerDelta(mark) ;
474  //asm("#second") ;
475  do {
476 
477  register int a ;
478 
479 
480  if(unlikely(last_falling)) {
481  if(unlikely(adc > (last_a + min_adc))) { // mostly false
482  flags |= FCF_DOUBLE_T ;
483  //LOG(WARN,"T Split before adc %d, at %d...",adc,start,0,0,0) ;
484  break ;
485  }
486  }
487  else {
488  if(unlikely(adc < (last_a - min_adc))) { // mostly false
489  last_falling = 1 ; // Im falling
490  }
491  else {
492  if(unlikely(adc >= max_a)) { // find the maximum and keep it...
493  max_a = adc ;
494 #ifdef FCF_SIM_ON
495  max_sim = sim_id ;
496 #endif
497  mean = start ; // this is not the mean but the position of the max!
498 
499  }
500 
501  }
502  }
503 
504 #ifdef FCF_10BIT_ADC
505  // no lookup - already in 10 bits!
506 
507  //a = adc ; // jml 1/27/02 even when FCF_10BIT_ADC really means the size is short
508  a = log8to10_table[adc]; // we still need to apply the 8to10 bit conversion.
509 
510  //if(row==14) printf("Row %d, pad %d, timebin %d, data %d\n",row,pad,start,a) ;
511 
512  //if(a > 255) printf("Datum is %d\n",a) ;
513 #else
514  a = adc8to10[adc] ; // transfer to 10 bits
515 #endif
516  last_a = adc ;
517 
518 #ifdef FCF_NEW_ADC_ROUNDOFF
519  av += start*a + (start+1)/2 ;
520 #else
521  av += start * a ;
522 #endif
523  charge += a ;
524 
525  //LOG(WARN,"Pad %d, start %d, adc %d, charge %d",pad,start,adc,charge,0) ;
526 
527  adc = *adc_p++ ; // advance here!
528 #ifdef FCF_SIM_ON
529  pixStruct[pad][start].adc = a ;
530  pixStruct[pad][start].cl_id = cl_id ;
531  pixStruct[pad][start].id_simtrk = sim_id ;
532 
533  if(simout) {
534  sim_id = *sim_p++ ;
535  }
536 #endif
537 
538  //LOG(DBG,"... adc_p 0x%08X (end 0x%08X)",adc_p,adc_end,0,0,0) ;
539 
540  start++ ;
541 
542  } while(likely(adc_p <= adc_end)) ;
543  //asm("#third") ;
544 
545 #ifdef FCF_NEW_ADC_ROUNDOFF
546  // new! correcting ADC roundoff errors
547  charge += ((start-stop)+1)/2 ; // Note that "start-1" is the last while "stop" is the first
548  // pixel. Note that I also try to roundoff correctly the div. by 2.
549 #endif
550  // t0Corr is (gain*t0*64)!
551  // This value may go negative here due to the t0 corrections!!!
552  // Time sum is now 64 times larger!!!
553  av = GC * av + T0C * charge ;
554 
555 
556  charge *= GC ; // charge is now 64 times larger!
557 
558 
559 #if defined(__unix) || defined(__APPLE__)
560  if(charge > 0x7FFFFFFF) {
561  LOG(ERR,"Whoa charge 0x%08X, %d GC",charge,GC,0,0,0) ;
562  }
563 #endif
564  //delta[2] += mzFastTimerDelta(mark) -delta[1];
565 
566  // get the next storage location
567  struct fcfResx *rn = new_res[new_res_cou++];
568 
569 
570  rn->pad = charge*pad ; // this may be 64 times larger if gain correction is employed!
571 
572  // store the new results via some assembly inline...
573  mstore(rn,av,charge,mean,flags) ;
574 
575 
576  rn->p1 = pad ;
577  rn->p2 = pad ;
578  rn->t1 = stop ; // this is actually the first...
579  rn->t2 = start-1 ; // this is actually the last...
580 
581 
582  //LOG(WARN,"Pad %d, stored max at %d, t1 %d, t2 %d",pad,mean,rn->t1,rn->t2,0) ;
583 
584 #ifdef FCF_SIM_ON
585  //printf("**** %d %d\n",cl_id,max_a) ;
586 
587  rn->pix = start-stop ;
588  rn->adc_max = max_a ;
589  rn->id = max_sim ;
590  rn->cl_id = cl_id++ ; // global cluster id...
591 #endif
592 
593  //if(((u_int)adc_p & 0xF)==0) preburst4(adc_p) ;
594 
595  } while(likely(adc_p <= adc_end)) ;
596 
597  //delta[2] += mzFastTimerDelta(mark) -delta[1];
598  //asm("#fourth") ;
599 
600  }// end of the pad or cl_counter
601 
602 
603  //delta[3] += mzFastTimerDelta(mark) - delta[0];
604 
605 
606  if(new_res_cou) { // some results
607  next_pad = pad + 1 ; // we expect this pad as the next one!
608  }
609 
610 
611 
612  //LOG(WARN,"Pad %d: cl %d, res %d",pad,cou_ptrs,new_res_cou,0,0) ;
613 
614 
615  //asm("#double") ;
616  int new_start = 0 ;
617 
618  for(i=0;likely(i<old_res_cou);i++) { // loop over old sequneces
619  register struct fcfResx *rr ;
620  register int start ;
621 
622  rr = old_res[i] ;
623 
624  register int merged = 0 ;
625 
626  register int old_mean = rr->mean ;
627  register int old_mean_m = old_mean - param1 ;
628  register int old_mean_p = old_mean + param1 ;
629 
630  register int min_adc = minAdcPad ;
631 
632  register u_int old_scharge = rr->scharge ;
633  register u_int old_flags = rr->flags ;
634 
635  start = new_start ;
636 
637 
638  for(j=start;likely(j<new_res_cou);j++) { // loop over new sequences
639  register struct fcfResx *nresx ;
640  register int mean ;
641 
642  nresx = new_res[j] ;
643 
644  mean = nresx->mean ;
645 
646  if(mean < old_mean_m) {
647  new_start = j + 1 ;
648  continue ;
649  }
650  else if(mean <= old_mean_p) {
651  register u_int charge ;
652 
653  charge = nresx->charge ;
654 
655 
656  if(old_flags & FCF_FALLING) {
657 
658  if(charge > (old_scharge + min_adc)) {
659  register u_int sc_tmp, sc_p_tmp ;
660 
661 
662 
663  sc_tmp = old_scharge / 2 ;
664  sc_p_tmp = sc_tmp * (pad-1) ;
665 
666  nresx->flags |= FCF_DOUBLE_PAD ; // new one
667 
668  // the new one will get half of previous share
669 
670  nresx->charge += sc_tmp ;
671  nresx->pad += sc_p_tmp ;
672 
673  nresx->t += (mean * sc_tmp) ;
674 
675 
676  // the old guy gets half of the previous less
677 
678  if(unlikely(sc_tmp > rr->charge)) {
679  LOG(WARN,"oops - going negative 0x%08X - 0x%08X",rr->charge,sc_tmp,0,0,0) ;
680  }
681 
682 
683  rr->charge -= sc_tmp ;
684  rr->pad -= sc_p_tmp ;
685 
686  // watch it! rr->t may go negative!!!
687  rr->t -= old_mean * sc_tmp ;
688 
689  rr->flags = old_flags | FCF_DOUBLE_PAD ; // old one
690 
691 
692  nresx->p1 = pad - 1 ;
693  rr->p2 = pad ;
694 
695  new_start = j+1 ;
696 
697  break ; // and create a new one; break out of old results scan
698 
699  }
700  // maintain "falling" character
701  nresx->flags |= FCF_FALLING ;
702  }
703  else {
704  // need to go signed for a moment...
705  if((int)charge < ((int)old_scharge - min_adc)) {
706  //llog("MARK!") ;
707  nresx->flags |= FCF_FALLING ;
708  }
709  }
710 
711 
712  merged = 1 ;
713 
714  nresx->flags |= old_flags ;
715  nresx->flags &= (~FCF_ONEPAD) ; // ...clear the one pad flag
716 
717 
718  nresx->scharge = charge ; // last pad charge
719  nresx->charge += rr->charge ;
720  nresx->pad += rr->pad ;
721  nresx->t += rr->t ;
722  // mean stays the same????
723  // I'm not sure this is good!
724 
725 
726  nresx->p1 = rr->p1 ; // the old guy has the smaller pad
727  if(rr->t1 < nresx->t1) nresx->t1 = rr->t1 ;
728  if(rr->t2 > nresx->t2) nresx->t2 = rr->t2 ;
729 
730 
731 #ifdef FCF_SIM_ON
732  nresx->pix += rr->pix ;
733 
734  //printf("%d:now %d, old %d\n",rr->cl_id,nresx->adc_max,rr->adc_max) ;
735 
736  if(rr->adc_max > nresx->adc_max) {
737  nresx->adc_max = rr->adc_max ;
738 
739  nresx->id = rr->id ;
740  }
741 
742  // copy over the pixel data
743  // and take over the old clusters ID
744  for(int ii=0;ii<512;ii++) {
745  if(nresx->cl_id == pixStruct[pad][ii].cl_id) {
746  pixStruct[pad][ii].cl_id = rr->cl_id ;
747  }
748  }
749  nresx->cl_id = rr->cl_id ; // the new id
750 
751 #endif
752  new_start = j + 1 ;
753 
754  break ;
755  }
756  else {
757  new_start = j ;
758 
759  break ;
760  }
761 
762  }
763 
764 
765  if(!merged) { // didn't merge - must store!
766  int wrote ;
767 
768  // check for space!
769  if((*cl_found_pointer + 1) >= maxClusters) {
770  LOG(ERR,"Too many clusters in pad %d - breaking!",pad,0,0,0,0) ;
771  return outres - row_pointer ;
772  }
773 
774  //LOG(DBG,"Mean diff old-new %d [%d], new res cou %d",old_mean-new_res[j]->mean,reason,new_res_cou-j,0,0) ;
775 
776 
777  // could be less than requested due to cuts...
778  wrote = saveRes(&rr, 1, outres) ;
779  outres += wrote*2 ; // occupies 8 bytes
780  *cl_found_pointer += wrote ;
781 #ifdef FCF_SIM_ON
782  if(simout) {
783  *sim_found_ptr += wrote ;
784  }
785 #endif
786  }
787 
788  }
789  //asm("#triple") ;
790 
791  //delta[4] += mzFastTimerDelta(mark) -delta[3];
792  }// for minpad to maxpad
793 
794  // check for leftover in the last pass
795  if(new_res_cou) {
796  int wrote ;
797  // check for space!
798 
799  if((*cl_found_pointer + new_res_cou) >= maxClusters) {
800  //printf("FCF:Too many clusters!\n") ;
801  LOG(ERR,"Too many clusters in pad %d - breaking!",pad,0,0,0,0) ;
802  return outres - row_pointer ;
803  }
804 
805 
806  // could be less than requested due to cuts...
807  wrote = saveRes(new_res, new_res_cou, outres) ;
808  outres += wrote*2 ; // occupies 8 bytes
809  *cl_found_pointer += wrote ;
810 #ifdef FCF_SIM_ON
811  if(simout) {
812  *sim_found_ptr += wrote ;
813  }
814 #endif
815  }
816 
817  //if(row == 14) printf("Row %d: length %d\n",row,outres-row_pointer) ;
818 
819  //LOG(WARN,"One_pad %d, pad decon %d, seq_total %d, low_adc %d, delta %d",one_pad,pad_decon,seq_total,adc_low,delta[2]) ;
820 
821  //LOG(WARN,"Delta2 %d, delta3 %d, delta4 %d",delta[2],delta[3],delta[4],0,0) ;
822 
823  return (outres - row_pointer) ; // length in qwords
824 
825 }
826 
827 
828 fcfClass::fcfClass(int det, u_short *table)
829 {
830  detector = det ;
831 
832 #if defined(__unix) || defined(__APPLE__)
833  a8to10 = adc8to10_storage ;
834 #else // I960
835  a8to10 = fastMem->adc8to10 ;
836 #endif
837 
838 
839  // de-mangle the revision...
840  cvs_revision = 0 ; // let's start with 0 here...
841 
842  { // bracket stuff
843  size_t i ;
844  char tmp[10] ;
845  int num_start=0, num_end=0, num_dot=0 ;
846 
847  for(i=0;i<strlen(fcf_cvs_revision);i++) {
848  if(isdigit(fcf_cvs_revision[i])) {
849  num_start = i ;
850  break ;
851  }
852  }
853  for(i=num_start;i<strlen(fcf_cvs_revision);i++) {
854  if(fcf_cvs_revision[i]==0x20) { // space
855  num_end = i-1 ;
856  break ;
857  }
858  if(fcf_cvs_revision[i]=='.') { // dot
859  num_dot = i ;
860  }
861  }
862 
863  strncpy(tmp,&(fcf_cvs_revision[num_start]),1) ;
864  cvs_revision = atoi(tmp) << 16 ; // major
865  strncpy(tmp,&(fcf_cvs_revision[num_dot+1]),num_end-num_dot) ;
866  cvs_revision |= atoi(tmp) ;
867 
868 // LOG(INFO,"Working with CVS code %s [0x%08X]",fcf_cvs_revision,cvs_revision,0,0,0) ;
869 
870  }
871 
872  simIn = 0 ; // assume no simulation unless explicitly overriden later
873  simOut = 0 ;
874 
875  if(table == NULL) {
876  noADCconversion = 1 ;
877  }
878  else {
879  noADCconversion = 0 ;
880  }
881 
882 
883  svtPedestal = 0 ;
884 
885 
886  deconTime = 1 ;
887  deconPad = 1 ;
888  doCuts = 1 ;
889 
890  param1 = FCF_PARAM1 ;
891  minAdcT = FCF_MIN_ADC_T ;
892  minAdcPad = FCF_MIN_ADC_PAD ;
893 
894  switch(det) {
895  case TPC_ID :
896  maxCPP = 31 ;
897  maxTimebin = 511 ;
898  timebinLo = 0 ;
899  timebinHi = 400 ; // should be 400 normally
900  chargeMin = 40 ; // reasonable estimate was 40
901  break ;
902  case FTP_ID :
903  maxCPP = 31 ;
904  maxTimebin = 511 ;
905  timebinLo = 0 ;
906  timebinHi = 255 ;
907  chargeMin = 40 ;
908  break ;
909  case SVT_ID :
910  maxCPP = 8 ;
911  maxTimebin = 127 ;
912  timebinLo = 0 ;
913  timebinHi = 127 ;
914  chargeMin = 20 ;
915  break ;
916  default :
917  LOG(WARN,"Cluster Finder can't work with DET Type %d",det,0,0,0,0) ;
918  return ;
919  }
920 
921  // take into account the multipication due to
922  // gain being used
923  minAdcPad *= FCF_GAIN_FACTOR ;
924 
925  static struct fcfResx res_slow[2][512] ;
926 #if defined(__unix) || defined(__APPLE__)
927  static struct fcfResx res_fast_ux[2][FCF_MAX_RES_COU_FAST] ;
928  struct fcfResx *res_fast[2] = { res_fast_ux[0], res_fast_ux[1] } ;
929 #else
930 
931 #define RES_COU (sizeof(struct fcfResx)*2*FCF_MAX_RES_COU_FAST)
932 #define I960_MAX_RES (sizeof(fastMem->fcfStore))
933 
934  if(RES_COU > I960_MAX_RES) {
935  LOG(CRIT,"Error in MAX_RES_COU size %d > %d!!!",RES_COU,I960_MAX_RES,0,0,0) ;
936  }
937 
938  // hand adjusted!!! Beware of changes!!!
939  struct fcfResx *res_fast[2] = {
940  (struct fcfResx *) fastMem->fcfStore,
941  (struct fcfResx *) &(fastMem->fcfStore[(sizeof(struct fcfResx)/4)*FCF_MAX_RES_COU_FAST]) } ;
942 
943 
944  //LOG(WARN,"size %d, count %d at %u %u (max %d bytes)",sizeof(struct fcfResx),FCF_MAX_RES_COU_FAST,(UINT32)res_fast[0],(UINT32)res_fast[1],I960_MAX_RES) ;
945 
946 #endif
947 
948 
949  u_int i, j ;
950  for(i=0;i<2;i++) {
951  for(j=0;j<FCF_MAX_RES_COU_FAST;j++) {
952  resx[i][j] = res_fast[i] + j ;
953  //LOG(WARN,"B %d:%d = 0x%08X",i,j,resx[i][j],0,0) ;
954  }
955  }
956  for(i=0;i<2;i++) {
957  for(j=FCF_MAX_RES_COU_FAST;j<512;j++) {
958  resx[i][j] = &(res_slow[i][j]) ;
959  }
960  }
961 
962  return ;
963 }
964 
965 
966 // copy over the ADC conversion table...
967 void fcfClass::set8to10(u_short *table)
968 {
969  int i ;
970 
971  if(table) {
972  for(i=0;i<256;i++) {
973  a8to10[i] = *table++ ;
974  }
975  noADCconversion = 0 ;
976  }
977  else {
978  noADCconversion = 1 ;
979  }
980  return ;
981 }
982 
983 // returns the number of clusters saved
984 inline int fcfClass::saveRes(struct fcfResx *res_p[], int cou, u_int *output)
985 {
986  //asm("#saved") ;
987  int i ;
988  int saved = 0 ;
989  register u_int ch_min = chargeMinCorrect ;
990  register int do_cuts = doCuts ;
991  u_int fla, cha ;
992  u_int pad_c ;
993  u_int time_c ;
994  u_int t_cha ;
995 
996  for(i=0;i<cou;i++) {
997  struct fcfResx *rr ;
998 
999  rr = res_p[i] ;
1000 
1001 
1002  fla = rr->flags ;
1003  cha = rr->charge ;
1004 
1005 
1006  // skip single pad hits
1007  // as well as those with too little charge
1008  //LOG(NOTE,"saveRes: flags 0x%X, charge %d",fla,cha,0,0,0) ;
1009 
1010  if(do_cuts) {
1011  if(fla & FCF_BROKEN_EDGE) { // always pass!
1012  ;
1013  }
1014  else if(fla & (FCF_ROW_EDGE | FCF_DEAD_EDGE | FCF_ONEPAD)) continue ; // kill!
1015  else if(cha <= ch_min) continue ; // kill!
1016  else if(rr->t1 == 0) continue ; // kill if they touch timebin 0
1017  else if((rr->t2-rr->t1) <= 3) continue ;
1018  }
1019 
1020 
1021  if((cha == 0) || (cha > 0x7FFFFFFF)) {
1022  //LOG(WARN,"Bad charge: pad 0x%08X, time 0x%08X, charge 0x%08X, flags 0x%04X",rr->pad,rr->t,rr->charge,fla,0) ;
1023  continue ;
1024  }
1025 
1026 
1027  pad_c = rr->pad ;
1028  time_c = rr->t ;
1029 
1030  if(pad_c > 0x04000000) {
1031  t_cha = cha >> 6 ;
1032 
1033  if(t_cha) {
1034  pad_c = (pad_c + t_cha/2) / t_cha ;
1035  }
1036  else {
1037  pad_c = ((pad_c + cha/2) / cha) << 6 ;
1038  }
1039 
1040  //LOG(WARN,"Precision lost: orig pad %u, orig cha %u, t_cha %u, pad_c %u",rr->pad,cha,t_cha,pad_c,0) ;
1041  }
1042  else {
1043  // increased resolution
1044  pad_c = ((pad_c << 6) + (cha/2)) / cha ;
1045  }
1046 
1047  if(time_c > 0x04000000) {
1048  t_cha = cha >> 6 ;
1049 
1050  if(t_cha) {
1051  time_c = (time_c + t_cha/2) / t_cha ;
1052  }
1053  else {
1054  time_c = ((time_c + cha/2) / cha) << 6 ;
1055  }
1056  }
1057  else {
1058  // increase resoultion
1059  time_c = ((time_c << 6) + (cha/2)) / cha ;
1060  }
1061 
1062 
1063  // do the integerized rounded division
1064  cha = (cha+32)/64 ;
1065 
1066 
1067 
1068  if((pad_c > 0xFFFF) || (time_c > 0xFFFF)) {
1069  //LOG(WARN,"Overload pad 0x%08X, time 0x%08X, charge 0x%08X, flags 0x%04X - discarding ",pad_c,time_c,cha,fla,0) ;
1070  continue ;
1071  }
1072 
1073  if(cha > 0xFFFF) {
1074  //LOG(WARN,"Charge too big 0x%08X - setting to 0xffff (pad 0x%08X, time 0x%08X)...",cha,rr->pad,rr->t,0,0) ;
1075  cha = 0xFFFF ;
1076  fla |= FCF_DOUBLE_T | FCF_DOUBLE_PAD ; // mark it somehow!
1077  }
1078 
1079  // clear the FALLING flag
1080  fla &= (~FCF_FALLING) ;
1081 
1082 
1083  // thse bits should never be set!!! - will use them for flags!
1084  if((pad_c & 0xc000) || (time_c & 0x8000)) {
1085  LOG(ERR,"Strange pad 0x%04X, time 0x%04X...",pad_c,time_c,0,0,0) ;
1086  continue ;
1087  }
1088 
1089 
1090  u_int p = (pad_c >> 6) ;
1091  u_int fl ;
1092 
1093  u_int p1 = p - rr->p1 ;
1094  u_int p2 = rr->p2 - p ;
1095 
1096  if(p1 > 7) p1 = 7 ;
1097  if(p2 > 7) p2 = 7 ;
1098 
1099 
1100 // if((p1 == 15) || (p2 ==15)) {
1101 // fprintf(stderr,"--- %d %d %d %d %d - 0x%04X - ",rr->pad,rr->charge,p,rr->p1,rr->p2,fla) ;
1102 // fprintf(stderr,"%f\n",(double)pad_c/64.0) ;
1103 // }
1104 
1105 
1106  fl = (p1 << 8) | (p2 << 11) ;
1107 
1108 
1109  p = (time_c >> 6) ;
1110 
1111 
1112  p1 = p - rr->t1 ;
1113  p2 = rr->t2 - p ;
1114 
1115  if(p1 > 15) p1 = 15 ;
1116  if(p2 > 15) p2 = 15 ;
1117 
1118 // if((p1 == 15) || (p2 ==15)) {
1119 // fprintf(stderr,"--- %d %d %d %d %d - 0x%04X - ",rr->t,rr->charge,p,rr->t1,rr->t2,fla) ;
1120 // fprintf(stderr,"%f\n",(double)time_c/64.0) ;
1121 // }
1122 
1123  fl |= (p2 << 4) | p1 ;
1124 
1125 
1126 // printf("%d %f %f %d %d %d %d %d %d %d %d %d\n",row,(double)(pad_c)/64.0-1.0,(double)time_c/64.0-0.5,
1127 // cha, fla, rr->p1, rr->p2, rr->t1, rr->t2, rr->pix, rr->adc_max, rr->id) ;
1128 
1129 
1130 
1131  if(fla & FCF_ONEPAD) time_c |= 0x8000 ;
1132  if(fla & (FCF_DOUBLE_T | FCF_DOUBLE_PAD)) pad_c |= 0x8000 ;
1133  if(fla & FCF_DEAD_EDGE) pad_c |= 0x4000 ;
1134 
1135  if(fla & FCF_ROW_EDGE) fl |= 0x8000 ;
1136  if(fla & FCF_BROKEN_EDGE) fl |= 0x4000 ;
1137 
1138 // fla = fl ;
1139 
1140 
1141 
1142  // watchout for ordering!
1143  *output++ = (time_c << 16) | pad_c ;
1144  *output++ = (cha << 16) | fl ;
1145 
1146 #ifdef FCF_SIM_ON
1147  //if(fla==0) printf("PIX %d %d %d %d %d\n",rr->cl_id,fla,cha,rr->pix,rr->adc_max) ;
1148 
1149  {
1150  int i, j ;
1151 
1152  int quality = 1 ;
1153 
1154  if(simout) {
1155 
1156  u_int sim_cha, all_cha ;
1157 
1158  sim_cha = all_cha = 0 ;
1159 
1160  for(i=1;i<=182;i++) {
1161  for(j=0;j<512;j++) {
1162  if(pixStruct[i][j].cl_id == rr->cl_id) {
1163  if(rr->id == pixStruct[i][j].id_simtrk) {
1164  sim_cha += pixStruct[i][j].adc ;
1165  }
1166  all_cha += pixStruct[i][j].adc ;
1167  }
1168  }
1169  }
1170 
1171  if(all_cha) {
1172  quality = (int)(100.0*(double)sim_cha/(double)all_cha) ;
1173  }
1174  else {
1175  quality = 0 ;
1176  }
1177 
1178 
1179  struct FcfSimOutput *s = (struct FcfSimOutput *) simout ;
1180 
1181  s->id_simtrk = rr->id ;
1182  s->id_quality = quality ;
1183 
1184  s->cl_id = rr->cl_id ; // put the local cluster id
1185 
1186  simout += sizeof(struct FcfSimOutput)/4 ; // advance here
1187 
1188  }
1189 
1190 #if defined(FCF_ANNOTATE_CLUSTERS) && !defined(__ROOT__)
1191  for(i=1;i<=182;i++) {
1192  for(j=0;j<512;j++) {
1193  if(pixStruct[i][j].adc) {
1194  fcfPixA[row-1][i-1][j] = pixStruct[i][j] ;
1195  }
1196  }
1197  }
1198 #endif
1199  }
1200 
1201 #endif // FCF_SIM_ON!
1202 
1203 
1204 
1205 
1206  //LOG(WARN,"time 0x%02X, pad 0x%02X, cha 0x%02X, fla 0x%02X",
1207  // time_c, pad_c, cha, fl,0) ;
1208 
1209  saved++ ;
1210 
1211 
1212  }
1213 
1214  //LOG(DBG,"saveRes saved %d clusters...",saved,0,0,0,0) ;
1215  return saved ;
1216 }
1217