StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
fcs_trg_base.cxx
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <string.h>
4 
5 #include <rtsLog.h>
6 #include <DAQ_FCS/fcs_data_c.h>
7 
8 #include "fcs_trg_base.h"
9 
10 // statics
11 fcs_trg_base::marker_t fcs_trg_base::marker ;
12 
13 u_int fcs_trg_base::stage_version[4] ;
14 
15 u_short fcs_trg_base::stage_params[4][32] ;
16 
17 ped_gain_t fcs_trg_base::p_g[NS_COU][ADC_DET_COU][DEP_COU][32] ;
18 u_short fcs_trg_base::ht_threshold[ADC_DET_COU] ;
19 
20 
21 unsigned long long fcs_trg_base::s2_ch_mask[NS_COU] ;
22 u_char fcs_trg_base::s2_ch_phase[NS_COU][34] ;
23 
24 u_char fcs_trg_base::s3_ch_mask ;
25 u_char fcs_trg_base::s3_ch_phase[4] ;
26 u_char fcs_trg_base::s3_out_phase ;
27 
28 int fcs_trg_base::fcs_trgDebug ;
29 int fcs_trg_base::fcs_readPresMaskFromText;
30 u_int fcs_trg_base::PRES_MASK[15][9][6];
31 
32 u_short fcs_trg_base::EM_HERATIO_THR ;
33 u_short fcs_trg_base::HAD_HERATIO_THR ;
34 u_short fcs_trg_base::EMTHR0 ;
35 u_short fcs_trg_base::EMTHR1 ;
36 u_short fcs_trg_base::EMTHR2 ;
37 u_short fcs_trg_base::EMTHR3 ; //obsolete for 202207
38 u_short fcs_trg_base::ELETHR0 ;
39 u_short fcs_trg_base::ELETHR1 ;
40 u_short fcs_trg_base::ELETHR2 ;
41 u_short fcs_trg_base::HADTHR0 ;
42 u_short fcs_trg_base::HADTHR1 ;
43 u_short fcs_trg_base::HADTHR2 ;
44 u_short fcs_trg_base::HADTHR3 ; //obsolete for 202207
45 u_short fcs_trg_base::JETTHR1 ; //obsolete for 202207
46 u_short fcs_trg_base::JETTHR2 ; //obsolete for 202207
47 u_short fcs_trg_base::JPATHR2 ;
48 u_short fcs_trg_base::JPATHR1 ;
49 u_short fcs_trg_base::JPATHR0 ;
50 u_short fcs_trg_base::JPBCTHR2 ;
51 u_short fcs_trg_base::JPBCTHR1 ;
52 u_short fcs_trg_base::JPBCTHR0 ;
53 u_short fcs_trg_base::JPBCTHRD ;
54 u_short fcs_trg_base::JPDETHR2 ;
55 u_short fcs_trg_base::JPDETHR1 ;
56 u_short fcs_trg_base::JPDETHR0 ;
57 u_short fcs_trg_base::JPDETHRD ;
58 u_short fcs_trg_base::ETOTTHR ;
59 u_short fcs_trg_base::HTOTTHR ;
60 u_short fcs_trg_base::EHTTHR ;
61 u_short fcs_trg_base::HHTTHR ;
62 u_short fcs_trg_base::PHTTHR ;
63 
64 u_int fcs_trg_base::data_format ;
65 
66 int fcs_trg_base::run_type ;
67 
68 
69 fcs_trg_base::fcs_trg_base()
70 {
71 // LOG(TERR,"%s (sizeof class %u)",__PRETTY_FUNCTION__,sizeof(*this)) ;
72 
73  log_level = 0 ;
74  realtime = 0 ;
75  id = 0 ;
76  sim_mode = 0 ;
77  data_format = 1 ;
78 
79  run_type = 3 ; // assume normal
80 
81  trg_xing = 5 ;
82 
83  want_stage_2_io = 0 ;
84  want_stage_3_io = 0 ;
85  want_stage_1_sim = 1 ;
86 }
87 
88 
89 fcs_trg_base::~fcs_trg_base()
90 {
91 // LOG(TERR,"%s",__PRETTY_FUNCTION__) ;
92 }
93 
94 u_int fcs_trg_base::get_version()
95 {
96  return 0x21000000 ; //YY,MM,DD,HH in BCD; 0 for base class
97 } ;
98 
99 
100 void fcs_trg_base::init(const char* fname)
101 {
102  if(id != 0) return ; // just one guy
103 
104 
105  // zap input params
106 
107  memset(stage_params,0,sizeof(stage_params)) ;
108  memset(p_g,0,sizeof(p_g)) ;
109 
110  memset(s2_ch_phase,0,sizeof(s2_ch_phase)) ;
111  memset(s2_ch_mask,0,sizeof(s2_ch_mask)) ;
112 
113  memset(s3_ch_phase,0,sizeof(s3_ch_phase)) ;
114  s3_ch_mask = 0 ;
115  s3_out_phase = 0 ;
116 
117  // and then set all gains to 1
118  for(int i=0;i<NS_COU;i++) {
119  for(int j=0;j<ADC_DET_COU;j++) {
120  for(int k=0;k<DEP_COU;k++) {
121  for(int c=0;c<32;c++) {
122  p_g[i][j][k][c].gain = (1<<8) ; // new for FY22
123 
124  }}}}
125 
126 
127  // thresholds to defaults
128  ht_threshold[0] = 90 ; // ecal
129  ht_threshold[1] = 90 ; // hcal
130  ht_threshold[2] = 45 ; // fpRE in FY19
131 
132  // since I can use fcs_trg_base in realtime, all the stuff below is already loaded
133  // if(!realtime && !sim_mode) {
134  if(!realtime) {
135  LOG(INFO,"init: not realtime -- loading stuff from files") ;
136 
137  memset(fcs_data_c::ped,0,sizeof(fcs_data_c::ped)) ;
138 
139  char rdomap[128];
140  sprintf(rdomap,"%s/fcs_daq_map.txt",fname);
141  fcs_data_c::load_rdo_map(rdomap) ;
142  fcs_data_c::gain_from_cache(fname) ;
143 
144  if(!sim_mode){ //no need for pedestal in sim_mode
145  for(int s=1;s<=1;s++) {
146  for(int r=1;r<=6;r++) {
147  char fname[256] ;
148  sprintf(fname,"/net/fcs%02d/RTScache/fcs_pedestals_s%02d_r%d.txt",s,s,r) ;
149  fcs_data_c::ped_from_cache(fname) ;
150  }
151  }
152  }
153 
154 
155  }
156  else if(!sim_mode) {
157 // LOG(TERR,"init:realtime: ht_threshold is %d",fcs_data_c::ht_threshold) ;
158 
159  for(int i=0;i<3;i++) { // known in realtime
160  ht_threshold[i] = fcs_data_c::ht_threshold ;
161  }
162  }
163 
164  for(int i=0;i<NS_COU;i++) {
165  for(int j=0;j<ADC_DET_COU;j++) {
166  for(int k=0;k<DEP_COU;k++) {
167 
168  int sec = fcs_data_c::det_map[j][i][k].sector - 1 ;
169  int rdo = fcs_data_c::det_map[j][i][k].rdo - 1 ;
170 
171  if(sec<0 || rdo<0) continue ; // protection against bad load
172 
173  for(int c=0;c<32;c++) {
174  u_short p = fcs_data_c::ped[sec][rdo].i_ped[c] ;
175  u_short g = fcs_data_c::ped[sec][rdo].i_gain[c] ;
176 
177  if(p && log_level>5 && c==0) { // just a sample, to check sanity
178  LOG(TERR,"S%d:%d: %d:%d:%d: ch %d = i_ped %d, i_gain %d",sec+1,rdo+1,j,i,k,c,p,g) ;
179  }
180 
181  //u_int mask = fcs_data_c::rdo_map[sec][rdo].ch_mask & 0xFFFFFFFFll ;
182 
183 
184  p_g[i][j][k][c].gain = fcs_data_c::ped[sec][rdo].i_gain[c] ;
185  p_g[i][j][k][c].ped = fcs_data_c::ped[sec][rdo].i_ped[c] ;
186  }
187  }}}
188 
189 
190  // BELOW depends on the length of processing so don't change!
191  // Set by Tonko
192 
193  // concrete values at e.g. 09-Dec-2021
194  marker.last_xing = 7 ; // this depends on the post setting and should be calculable
195 
196  marker.adc_start = 7 ; // fixed during board configuration
197  marker.s1_out_start = marker.adc_start + 11 ; // depends on stage_0/1 algo but pretty much fixed
198 
199  marker.s2_in_start = marker.s1_out_start + 2 ; // depends on the cable length from 1-to-2 put pretty much fixed
200  marker.s2_to_s3_start = marker.s2_in_start + 15 ; // depends on stage_2 algo?
201 
202 
203  marker.s3_in_start = marker.s2_to_s3_start + 8 ; // depends on cable length from 2-to-3; 0 in FY19
204  marker.dsm_out_start = marker.s3_in_start + 14 ; // depends on stage_3 algo
205 
206 
207  if(log_level>0) LOG(INFO,"init markers: last xing %d, ADC %d, s1_out %d, s2_in %d, s2_to_s3 %d, s3_in %d, dsm_out %d",
208  marker.last_xing,
209  marker.adc_start,
210  marker.s1_out_start,
211  marker.s2_in_start,
212  marker.s2_to_s3_start,
213  marker.s3_in_start,
214  marker.dsm_out_start) ;
215 
216 
217  // for Akio's code
218  fcs_trgDebug = 0 ;
219  fcs_readPresMaskFromText=0;
220 
221  // stage2 params (defaults are from Akio's code)
222  EM_HERATIO_THR = 32 ; // or 128*(1/4)
223  HAD_HERATIO_THR = 32 ;
224 
225  EMTHR3 = 128 ; //obsolete for 202207
226  HADTHR3 = 169 ; //obsolete for 202207
227  JETTHR2 = 128 ; //obsolete for 202207
228  JETTHR1 = 64 ; //obsolete for 202207
229 
230  //original default
231  EMTHR2 = 192 ;
232  EMTHR1 = 128 ;
233  EMTHR0 = 64 ;
234 
235  ELETHR2 = 32 ;
236  ELETHR1 = 22 ;
237  ELETHR0 = 25 ;
238 
239  HADTHR2 = 192 ;
240  HADTHR1 = 128 ;
241  HADTHR0 = 64 ;
242 
243  JPATHR2 = 254 ;
244  JPATHR1 = 192 ;
245  JPATHR0 = 128 ;
246  JPBCTHR2 = 254 ;
247  JPBCTHR1 = 192 ;
248  JPBCTHR0 = 128 ;
249  JPBCTHRD = 160 ;
250  JPDETHR2 = 254 ;
251  JPDETHR1 = 192 ;
252  JPDETHR0 = 128 ;
253  JPDETHRD = 160 ;
254 
255  ETOTTHR = 32 ;
256  HTOTTHR = 32 ;
257  EHTTHR = 50 ;
258  HHTTHR = 50 ;
259  PHTTHR = 100 ; //stage1
260 
261  if(sim_mode){
262  ht_threshold[0]=EHTTHR;
263  ht_threshold[1]=HHTTHR;
264  ht_threshold[2]=PHTTHR;
265  }
266 
267  // IMPORTANT: Requested Stage_x versions defaults
268  // Either set by the user to her/his wishes or picked up from the DAQ file
269  stage_version[0] = 2 ;
270  stage_version[1] = 1 ;
271  stage_version[2] = 7 ;
272  stage_version[3] = 7 ;
273 
274  // DEP/Trigger masks
275  //s3_ch_mask = (1<<2) ; // South 0
276  //s2_ch_mask[0] = 0 ; // Nothing in North
277  //s2_ch_mask[1] = (1<<3) ; // just 1 fPRE channel in South for early FY19
278 }
279 
280 
281 void fcs_trg_base::run_start(u_int run)
282 {
283  run_number = run ;
284  evts = 0 ;
285 
286  memset(&errs,0,sizeof(errs)) ;
287  memset(&good,0,sizeof(good)) ;
288  memset(&statistics,0,sizeof(statistics)) ;
289 
290  // cleanup, just in case
291  memset(d_in,0,sizeof(d_in));
292  memset(&d_out,0,sizeof(d_out));
293 
294  start_event() ; // just in case
295 
296  if(sim_mode) {
297  marker.adc_start = 0 ;
298  marker.last_xing = 1 ;
299  }
300 
301  LOG(INFO,"%d: starting run %08u, realtime %d, sim_mode %d",id,run_number,realtime,sim_mode) ;
302 
303  return ;
304 }
305 
306 
307 void fcs_trg_base::start_event()
308 {
309  got_one = 0 ;
310 
311  memset(tb_cou,0,sizeof(tb_cou)) ;
312 
313  if(sim_mode) { // only for simulated data
314  memset(d_in,0,sizeof(d_in)); //akio?
315  }
316 } ;
317 
318 
319 void fcs_trg_base::fill_event(int det, int ns, int dep, int c, u_short *d16, int t_cou)
320 {
321 
322  if(t_cou) {
323  if(got_one==0) {
324  evts++ ;
325  got_one = 1 ;
326  }
327  }
328  else return ;
329 
330  //printf("... tb_cou %d %d %d: %d\n",ns,det,dep,t_cou) ;
331 
332  tb_cou[ns][det][dep] = t_cou ;
333 
334  // various markers
335  int is_self = -1 ;
336  int is_tcd = -1 ;
337 
338  for(int t=0;t<t_cou;t++) {
339  int dta = d16[t] & 0xFFF ;
340  int fla = d16[t] >> 12 ;
341 
342  int xing ;
343  int xou ;
344  int tix ;
345 
346  if(log_level>100) printf("%d:%d:%d ch %d: tb %d: ADC %d, fla %d\n",
347  ns,det,dep,c,t,dta,fla) ;
348 
349  if(det != 3) { // DEP/ADC
350  if(c==32) { // stage_1 out data
351  tix = t - marker.s1_out_start ;
352  xing = tix/8 ;
353  xou = tix%8 ;
354 
355  if(dta && log_level>10) {
356  printf("s1 out: %d:%d:%d -- at xing %d:%d(%d) = %d\n",ns,det,dep,xing,xou,t,dta) ;
357  }
358 
359  if(tix>=0 && xing<XING_COU) {
360  // data stage_1 out
361  d_in[xing].s1[ns][det][dep].s1_to_s2.d[xou] = dta ;
362  }
363  }
364  else { // raw ADC data
365  tix = t - marker.adc_start ;
366  xing = tix/8 ;
367  xou = tix%8 ;
368 
369  if(tix>=0 && xing<XING_COU) {
370  // actual ADC data
371  d_in[xing].s1[ns][det][dep].adc[c].d[xou] = dta ;
372  }
373 
374  switch(data_format) {
375  case 0 : // some old shit -- ignore
376  if(c==0 && (fla & 0x1)) {
377 
378 
379  if(is_tcd < 0) is_tcd = t ;
380 
381  if(log_level > 101) {
382  printf("ADC tcd_marker -- at xing %d:%d(%d)\n",xing,xou,t) ;
383  }
384 
385  }
386 
387  if(c==0 && (fla & 0x2)) {
388 
389  if(is_self < 0) is_self = t ;
390 
391  if(log_level>101) {
392  printf("ADC self_trg -- at xing %d:%d(%d)\n",xing,xou,t) ;
393  }
394  }
395 
396  break ;
397  case 1 : //FY21
398 
399  if(c==3 && (fla&4)) {
400 
401  if(is_tcd < 0) is_tcd = t ;
402 
403  if(log_level > 101) {
404  printf("ADC tcd_marker -- at xing %d:%d(%d)\n",xing,xou,t) ;
405  }
406 
407  }
408 
409  if(c==1 && (fla&4)) {
410  if(is_self < 0) is_self = t ;
411 
412  if(log_level>101) {
413  printf("ADC self_trg -- at xing %d:%d(%d)\n",xing,xou,t) ;
414  }
415  }
416 
417 
418  break ;
419  }
420 
421  }
422  }
423  else if(dep==0) { // FY21 stage 3
424  switch(c) {
425  case 4 : // dsm out lo 8 bits
426  tix = t - marker.dsm_out_start ;
427 
428  xing = tix/8 ;
429  xou = tix%8 ;
430 
431  if(tix>=0 && xing<XING_COU) {
432  d_in[xing].s3.dsm_out.d[xou] = dta & 0xFF ; // link
433  }
434  break ;
435  case 5 : // DSM out hi 8 bits
436  tix = t - marker.dsm_out_start ;
437 
438  xing = tix/8 ;
439  xou = tix%8 ;
440 
441 
442  if(tix>=0 && xing<XING_COU) {
443  d_in[xing].s3.dsm_out.d[xou] |= (dta & 0xFF)<<8 ;
444  }
445  break ;
446  default :
447  tix = t - marker.s3_in_start ;
448 
449  xing = tix/8 ;
450  xou = tix%8 ;
451 
452  if(tix>=0 && xing<XING_COU) {
453  d_in[xing].s3.s3_from_s2[c].d[xou] = dta & 0xFF ;
454  }
455 
456 
457  break ;
458  }
459  }
460  else { // Stage 2
461  switch(c) {
462  case 34 : // s2_to_s3
463  case 35 :
464  tix = t - marker.s2_to_s3_start ;
465 
466  xing = tix/8 ;
467  xou = tix%8 ;
468 
469  if(tix>=0 && xing<XING_COU) {
470  // I had to remap this because the stage3 input is _swapped_
471  // S6:34 is S5:1
472  // S6:35 is S5:0
473  // S7:34 is S5:3
474  // S7:35 is S5:2
475  //int cc = (c==34?1:0) ;
476  //d_in[xing].s2[ns].s2_to_s3[cc].d[xou] = dta & 0xFF ;
477 
478  d_in[xing].s2[ns].s2_to_s3[c-34].d[xou] = dta & 0xFF ;
479  }
480  break ;
481  case 36 : // new in FY22
482  //tix = t - (marker.s2_to_s3_start - 1) ; // adjusted by hand!
483  tix = t - marker.dsm_out_start ; // same as S3 to DSM!
484 
485  xing = tix/8 ;
486  xou = tix%8 ;
487 
488  if(tix>=0 && xing<XING_COU) {
489  d_in[xing].s2[ns].s2_to_dsm.d[xou] = dta & 0xFF ;
490  }
491  break ;
492 
493  break ; // for now
494  default :
495  tix = t - marker.s2_in_start ;
496 
497  xing = tix/8 ;
498  xou = tix%8 ;
499 
500  if(tix>=0 && xing<XING_COU) {
501  d_in[xing].s2[ns].s2_from_s1[c].d[xou] = dta & 0xFF ;
502  }
503 
504  break ;
505  }
506  }
507  }
508 
509  // this generally is nonsense because we have many boards...
510  if(is_self>0) {
511  statistics.self_trgs++ ;
512  statistics.self_trg_marker = is_self ;
513  }
514 
515  if(is_tcd > 0) {
516  statistics.tcd_marker = is_tcd ;
517  }
518 
519 } ;
520 
521 int fcs_trg_base::end_event()
522 {
523  event_bad = 0 ;
524 
525  s2_io_ns_bad = 0 ;
526  s2_io_ch_bad = 0 ;
527 
528  s3_io_ch_bad = 0 ;
529 
530  s1_dep_bad = 0 ;
531  s1_det_bad = 0 ;
532  s1_ns_bad = 0 ;
533 
534  s2_ns_bad = 0 ;
535  s2_ch_bad = 0 ;
536 
537  s3_to_dsm = s2_to_dsm[0] = s2_to_dsm[1] = 0 ;
538 
539  if(!got_one) return 0 ; // nothing to do; let's not waste time
540 
541  verify_event_io() ; // verify interconnectivity
542 
543  int dsmout = 0;
544 
545  self_trigger = 0 ;
546 
547  s3_to_dsm = d_in[trg_xing].s3.dsm_out.d[0] ;
548  s2_to_dsm[0] = d_in[trg_xing].s2[0].s2_to_dsm.d[0] ;
549  s2_to_dsm[1] = d_in[trg_xing].s2[1].s2_to_dsm.d[0] ;
550 
551  for(int xing=0;xing<marker.last_xing;xing++) {
552  if(log_level>1) {
553  LOG(NOTE,"run_event_sim: xing %d",xing) ;
554  }
555 
556  dsmout = run_event_sim(xing,sim_mode) ;
557 
558  if(sim_mode) { // when running offline
559  dump_event_sim(xing) ;
560  }
561  else {
562  verify_event_sim(xing) ;
563  }
564  }
565 
566  return dsmout;
567 }
568 
569 int fcs_trg_base::run_stop()
570 {
571  int err = 0 ;
572 
573  for(int i=0;i<4;i++) {
574  if(errs.io_s1_to_s2[i]) err |= 1 ;
575  }
576 
577  if(errs.io_s2_to_s3) err |= 1 ;
578 
579  if(errs.sim_s1 || errs.sim_s2 || errs.sim_s3) {
580  err |= 2 ;
581  }
582 
583  LOG(INFO,"thread %d: self_trg_marker %d, tcd_marker %d",id,statistics.self_trg_marker,statistics.tcd_marker) ;
584 
585  if(err) {
586  if(run_type==3 || (err&1)) { // normal run or IO
587  LOG(ERR,"thread %d: %d/%d events in run %d: errs sim %u %u %u; io [%u %u %u %u] %u",id,
588  statistics.self_trgs,
589  evts,run_number,
590  errs.sim_s1,
591  errs.sim_s2,
592  errs.sim_s3,
593  errs.io_s1_to_s2[0],errs.io_s1_to_s2[1],errs.io_s1_to_s2[2],errs.io_s1_to_s2[3],
594  errs.io_s2_to_s3) ;
595  }
596  else {
597  LOG(WARN,"thread %d: %d/%d events in run %d: errs sim %u %u %u; io [%u %u %u %u] %u",id,
598  statistics.self_trgs,
599  evts,run_number,
600  errs.sim_s1,
601  errs.sim_s2,
602  errs.sim_s3,
603  errs.io_s1_to_s2[0],errs.io_s1_to_s2[1],errs.io_s1_to_s2[2],errs.io_s1_to_s2[3],
604  errs.io_s2_to_s3) ;
605 
606  }
607 
608  }
609 
610  LOG(INFO,"thread %d: %d/%d events in run %d: good sim %u %u %u; io [%u %u %u %u] %u",id,
611  statistics.self_trgs,
612  evts,run_number,
613  good.sim_s1,
614  good.sim_s2,
615  good.sim_s3,
616  good.io_s1_to_s2[0],good.io_s1_to_s2[1],good.io_s1_to_s2[2],good.io_s1_to_s2[3],
617  good.io_s2_to_s3) ;
618 
619 
620  return 0 ;
621 }
622 
623 // verify the IO parts of the event, various links
624 int fcs_trg_base::verify_event_io()
625 {
626  int printed = 0 ;
627  int bad = 0 ;
628 
629  // Stage 1 to Stage 2 DEPs: but ONLY if I have the whole event!!!
630  if(!want_stage_2_io) goto stage_3 ;
631 
632 
633  for(int x=0;x<marker.last_xing;x++) {
634  for(int t=0;t<8;t++) {
635  for(int ns=0;ns<2;ns++) {
636  int s2_from_s1[34] ;
637  int s1_to_s2[34] ;
638  int ix = 0 ;
639 
640  long mask = 0 ;
641 
642  int cns ;
643 
644  if(ns==0) cns='N' ;
645  else cns = 'S' ;
646 
647  //LOG(TERR,"xing %d, t %d, ns %d = %d",x,t,ns,tb_cou[ns][3][1]) ;
648 
649  //watch it!
650  //if(tb_cou[ns][3][1]==0) continue ; // no stage_2
651 
652  for(int i=0;i<34;i++) {
653  s2_from_s1[i] = d_in[x].s2[ns].s2_from_s1[i].d[t] ;
654  }
655 
656 
657  // ECAL
658  //LOG(TERR," %d %d %d %d",
659  // tb_cou[ns][0][0],
660  // tb_cou[ns][0][0],
661  // tb_cou[ns][0][0],
662  // tb_cou[ns][0][0]) ;
663 
664  for(int d=0;d<20;d++) {
665  if(tb_cou[ns][0][d]) mask |= (1ll<<ix) ;
666  s1_to_s2[ix] = d_in[x].s1[ns][0][d].s1_to_s2.d[t] ;
667  ix++ ;
668  }
669 
670  // HCAL
671  for(int d=0;d<8;d++) {
672  if(tb_cou[ns][1][d]) mask |= (1ll<<ix) ;
673  s1_to_s2[ix] = d_in[x].s1[ns][1][d].s1_to_s2.d[t] ;
674  ix++ ;
675  }
676 
677  // FPRE
678  for(int d=0;d<6;d++) {
679  if(tb_cou[ns][2][d]) mask |= (1ll<<ix) ;
680  s1_to_s2[ix] = d_in[x].s1[ns][2][d].s1_to_s2.d[t] ;
681  ix++ ;
682  }
683 
684 
685 
686 
687  if(mask != 0 && log_level>1) LOG(WARN,"xing %d:%d, ns %d: mask 0x%llX, ix %d",x,t,ns,mask,ix) ;
688 
689  for(int i=0;i<34;i++) {
690  // watch it!
691  //if(mask & (1ll<<i)) ;
692  //else continue ;
693 
694  // separate mask
695  if(s2_ch_mask[ns] & (1ll<<i)) continue ;
696 
697  if(s2_from_s1[i] || s1_to_s2[i]) {
698  //printf("... xing %d:%d, ns %d: %d: s2_in 0x%02X, s1_out 0x%02X\n",x,t,ns,i,s2_from_s1[i],s1_to_s2[i]) ;
699  }
700 
701  if(s2_from_s1[i] != s1_to_s2[i]) {
702  event_bad |= 0x10 ;
703 
704  s2_io_ns_bad = ns ;
705  s2_io_ch_bad = i ;
706 
707  if(log_level>0) LOG(ERR,"evt %d: S1_to_S2 IO: NS %c: ch %d: xing %d:%d: out 0x%02X, in 0x%02X",
708  evts,cns,i,x,t,s1_to_s2[i],s2_from_s1[i]) ;
709 
710  if(ns==0 && i<17) errs.io_s1_to_s2[0]++ ;
711  else if(ns==0) errs.io_s1_to_s2[1]++ ;
712  else if(ns==1 && i<17) errs.io_s1_to_s2[2]++ ;
713  else errs.io_s1_to_s2[3]++ ;
714 
715  }
716  else {
717  if(ns==0 && i<17) good.io_s1_to_s2[0]++ ;
718  else if(ns==0) good.io_s1_to_s2[1]++ ;
719  else if(ns==1 && i<17) good.io_s1_to_s2[2]++ ;
720  else good.io_s1_to_s2[3]++ ;
721 
722  }
723  }
724 
725  }
726  }
727  }
728 
729  stage_3:
730 
731  if(!want_stage_3_io) goto end ;
732 
733  // Stage 2 to Stage 3: but only if I have Stage_2 and Stage_3 DEPs in the data
734  for(int x=0;x<marker.last_xing;x++) {
735 
736  if(tb_cou[0][3][0]==0) continue ; // no stage_3 at all
737 
738  for(int c=0;c<4;c++) {
739  int cc = c%2 ;
740 
741  if(tb_cou[c/2][3][1]==0) continue ;
742  int err = 0 ;
743 
744 #if 0 // need to remap
745  switch(c) {
746  case 0 :
747  case 2 :
748  cc = 1 ;
749  break ;
750  case 1 :
751  case 3 :
752  cc = 0 ;
753  break ;
754  }
755 #endif
756  for(int t=0;t<8;t++) {
757  int s3_from_s2 = d_in[x].s3.s3_from_s2[c].d[t] ;
758  int s2_to_s3 = d_in[x].s2[c/2].s2_to_s3[cc].d[t] ;
759 
760  if(s2_to_s3 != s3_from_s2) {
761  event_bad |= 0x20 ;
762 
763  s3_io_ch_bad = c ;
764 
765  errs.io_s2_to_s3++ ;
766  err = 1 ;
767  }
768  else {
769  good.io_s2_to_s3++ ;
770  }
771  }
772 
773  if(err==1 && log_level>0) {
774  for(int t=0;t<8;t++) {
775  char ctmp ;
776 
777  int s3_from_s2 = d_in[x].s3.s3_from_s2[c].d[t] ;
778  int s2_to_s3 = d_in[x].s2[c/2].s2_to_s3[cc].d[t] ;
779 
780  if(s2_to_s3 != s3_from_s2) ctmp = '*' ;
781  else ctmp = ' ' ;
782 
783  LOG(ERR,"evt %d: S3 IO: ch %d: xing %d:%d: in S3 0x%02X, out of S2 0x%02X%c",
784  evts,c,x,t,
785  s3_from_s2,s2_to_s3,ctmp) ;
786  }
787 
788  }
789  }
790  }
791 
792  end:;
793 
794 
795  if(printed) fflush(stdout) ;
796 
797 
798 
799  return bad ;
800 }
801 
802 int fcs_trg_base::dump_event_sim(int xing)
803 {
804  // verify stage_1 data
805 
806  for(int i=0;i<NS_COU;i++) {
807  for(int j=0;j<ADC_DET_COU;j++) {
808  for(int k=0;k<DEP_COU;k++) {
809 
810  //if(tb_cou[i][j][k]==0) continue ; // not in the daat...
811 
812  for(int t=0;t<8;t++) {
813  int d_sim = d_out.s1[i][j][k].s1_to_s2.d[t] ;
814 
815  if(d_sim && fcs_trgDebug>0)
816  printf("S1 sim: %d:%d:%d - xing %d:%d, dta %d\n",
817  i,j,k,xing,t,d_sim) ;
818  }
819  }
820  }
821  }
822 
823 
824  // verify stage_2 data locally to stage_2 DEP
825  for(int i=0;i<NS_COU;i++) {
826  for(int j=0;j<2;j++) {
827 
828 
829  for(int t=0;t<8;t++) {
830  int d_sim = d_out.s2[i].s2_to_s3[j].d[t] ;
831 
832  if(fcs_trgDebug>0)
833  printf("S2 sim: %d:%d - xing %d:%d, dta 0x%03X\n",
834  i,j,xing,t,d_sim) ;
835  }
836  }
837  }
838 
839  //printf("S3 sim: to DSM 0x%04X\n",d_out.s3.dsm_out) ;
840 
841  return 0 ;
842 }
843 
844 
845 int fcs_trg_base::verify_event_sim(int xing)
846 {
847  int bad = 0 ;
848 
849  // class vars
850 
851  // verify stage_1 data
852 
853  int s1_failed = 0 ;
854  int s2_failed = 0 ;
855  int s3_failed = 0 ;
856 
857  if(!want_stage_1_sim) goto skip_stage1 ;
858 
859  for(int i=0;i<NS_COU;i++) {
860  int cns ;
861 
862  if(i==0) cns='N' ;
863  else cns='S' ;
864 
865  for(int j=0;j<ADC_DET_COU;j++) {
866  int cdet ;
867 
868  switch(j) {
869  case 0 :
870  cdet='E' ;
871  break ;
872  case 1 :
873  cdet='H' ;
874  break ;
875  case 2 :
876  cdet='F' ;
877  break ;
878  }
879 
880  for(int k=0;k<DEP_COU;k++) {
881  int want_print = 0 ;
882  int want_log = 0 ;
883 
884  if(tb_cou[i][j][k]==0) continue ; // not in the daat...
885 
886 
887  for(int t=0;t<8;t++) {
888  int d_sim = d_out.s1[i][j][k].s1_to_s2.d[t] ;
889  int d_i = d_in[xing].s1[i][j][k].s1_to_s2.d[t] ;
890 
891  if(d_sim != d_i) {
892  s1_failed = 1 ;
893  errs.sim_s1++ ;
894 
895  s1_dep_bad = k ;
896  s1_det_bad = j ;
897  s1_ns_bad = i ;
898 
899  want_log = 1 ;
900  bad++ ;
901  }
902  else {
903  good.sim_s1++ ;
904  }
905 
906  if(d_i || d_sim) {
907  want_print = 1 ;
908  }
909 
910  }
911 
912 
913  for(int t=0;t<8;t++) {
914  int d_sim = d_out.s1[i][j][k].s1_to_s2.d[t] ;
915  int d_i = d_in[xing].s1[i][j][k].s1_to_s2.d[t] ;
916 
917  if(want_log && log_level>0) {
918  LOG(ERR,"evt %d: S1 sim: %c:%c:%d - xing %d:%d: sim 0x%02X, dta 0x%02X %c",evts,cns,cdet,k,
919  xing,t,
920  d_sim,
921  d_i,d_sim!=d_i?'*':' ') ;
922  }
923 
924  if(want_print && log_level>3) {
925  printf("S1: %d:%d:%d - xing %d:%d: s1 sim %d, dta %d %s\n",i,j,k,
926  xing,t,
927  d_sim,
928  d_i,want_log?"ERROR":"") ;
929  }
930  }
931 
932  if(want_log && log_level>4) {
933  u_int s1_bits = 0 ;
934  for(int c=0;c<32;c++) {
935  int sum = 0 ;
936  for(int t=0;t<8;t++) {
937  sum += d_in[xing].s1[i][j][k].adc[c].d[t] ;
938  LOG(ERR,"ch %2d: t %d: dta %d",c,t,d_in[xing].s1[i][j][k].adc[c].d[t]) ;
939  }
940 
941  //LOG(ERR," sum %d, ped %d, sum-ped %d, ht thresh %d",sum,p_g[i][j][k][c].ped,sum-p_g[i][j][k][c].ped,ht_threshold[j]) ;
942  sum -= p_g[i][j][k][c].ped ;
943  if(sum > ht_threshold[j]) s1_bits |= (1<<c) ;
944  }
945  LOG(ERR," s1_bits 0x%08X",s1_bits) ;
946  }
947 
948  }}}
949 
950  skip_stage1: ;
951 
952  if(s1_failed) {
953  event_bad |= 1 ;
954  }
955 
956  // verify stage_2 data locally to stage_2 DEP
957  for(int i=0;i<NS_COU;i++) {
958 
959  int cns ;
960 
961  if(i==0) cns = 'N' ;
962  else cns = 'S' ;
963 
964 #if 1
965  // check S2-to-DSM
966  for(int j=0;j<1;j++) {
967  int want_print = 0 ;
968  int want_log = 0 ;
969 
970  if(tb_cou[i][3][1]==0) continue ; // no stage_2 in data
971 
972  for(int t=0;t<4;t++) { // just the first 4
973  int d_sim = d_out.s2[i].s2_to_dsm ;
974  int d_i = d_in[xing].s2[i].s2_to_dsm.d[t] ;
975 
976  if(d_sim != d_i) {
977  errs.sim_s2++ ;
978  s2_failed = 1 ;
979  event_bad |= 8 ;
980 
981  s2_ns_bad = i ;
982  s2_ch_bad = j ;
983 
984  want_log = 1 ;
985  bad++ ;
986  }
987  else {
988  good.sim_s2++ ;
989  }
990 
991  if(d_i || d_sim) {
992  want_print = 1 ;
993  }
994  }
995 
996  for(int t=0;t<4;t++) {
997  char ctmp = ' ' ;
998 
999  int d_sim = d_out.s2[i].s2_to_dsm ;
1000  int d_i = d_in[xing].s2[i].s2_to_dsm.d[t] ;
1001 
1002  if(d_sim != d_i) ctmp = '*' ;
1003 
1004  if(want_log && log_level>0) {
1005  LOG(ERR,"evt %d: S2_to_DSM sim: %c - xing %d:%d: sim 0x%02X, dta 0x%02X%c",evts,cns,
1006  xing,t,
1007  d_sim,
1008  d_i,ctmp) ;
1009  }
1010 
1011  if(want_print && log_level>3) {
1012  printf("evt %d: S2_to_DSM sim: %c: - xing %d:%d: sim %d, dta %d %s\n",evts,cns,
1013  xing,t,
1014  d_sim,
1015  d_i,want_log?"ERROR":"") ;
1016  }
1017  }
1018 
1019 
1020  }
1021 #endif
1022 
1023  for(int j=0;j<2;j++) {
1024  int want_print = 0 ;
1025  int want_log = 0 ;
1026 
1027  if(tb_cou[i][3][1]==0) continue ; // no stage_2 in data
1028 
1029  for(int t=0;t<7;t++) { // skip 0xABCD
1030  int d_sim = d_out.s2[i].s2_to_s3[j].d[t] ;
1031  int d_i = d_in[xing].s2[i].s2_to_s3[j].d[t] ;
1032 
1033  if(d_sim != d_i) {
1034  errs.sim_s2++ ;
1035  s2_failed = 1 ;
1036  event_bad |= 2 ;
1037 
1038  s2_ns_bad = i ;
1039  s2_ch_bad = j ;
1040 
1041  want_log = 1 ;
1042  bad++ ;
1043  }
1044  else {
1045  good.sim_s2++ ;
1046  }
1047 
1048  if(d_i || d_sim) {
1049  want_print = 1 ;
1050  }
1051  }
1052 
1053  for(int t=0;t<8;t++) {
1054  char ctmp = ' ' ;
1055 
1056  int d_sim = d_out.s2[i].s2_to_s3[j].d[t] ;
1057  int d_i = d_in[xing].s2[i].s2_to_s3[j].d[t] ;
1058 
1059  if(d_sim != d_i) ctmp = '*' ;
1060 
1061  if(want_log && log_level>0) {
1062  LOG(ERR,"evt %d: S2 sim: %c:%d - xing %d:%d: sim 0x%02X, dta 0x%02X%c",evts,cns,j,
1063  xing,t,
1064  d_sim,
1065  d_i,ctmp) ;
1066  }
1067 
1068  if(want_print && log_level>3) {
1069  printf("evt %d: S2 sim: %c:%d: - xing %d:%d: sim %d, dta %d %s\n",evts,cns,j,
1070  xing,t,
1071  d_sim,
1072  d_i,want_log?"ERROR":"") ;
1073  }
1074  }
1075 
1076 
1077  }}
1078 
1079 
1080 // if(s2_failed) {
1081 // event_bad |= 2 ;
1082 // }
1083 
1084  // verify stage_3 locally to stage_2 DEP
1085  if(tb_cou[0][3][0]==0) return bad ; // no stage_3 in data
1086 
1087 
1088 
1089  int want_log = 0 ;
1090  int want_print = 0 ;
1091 
1092  for(int t=0;t<4;t++) { // not that we look at only the first 4 timebins because the other 4 are 0 in FPGA
1093  int d_sim = d_out.s3.dsm_out ;
1094  int d_i = d_in[xing].s3.dsm_out.d[t] ;
1095 
1096 
1097  if(d_sim || d_i) want_print = 1 ;
1098 
1099  // 24-Feb-21 hack to remove the free-running bit
1100  //d_i &= 0xFFFB ;
1101 
1102  if(d_sim != d_i) {
1103  errs.sim_s3++ ;
1104  s3_failed = 1 ;
1105  bad++ ;
1106  want_log = 1 ;
1107  }
1108  else {
1109  good.sim_s3++ ;
1110  }
1111  }
1112 
1113  // in case I want printouts
1114  for(int t=0;t<4;t++) {
1115  int d_sim = d_out.s3.dsm_out ;
1116  int d_i = d_in[xing].s3.dsm_out.d[t] ;
1117 
1118  if(want_log && log_level>0) {
1119  LOG(ERR,"evt %d: S3 sim: xing %d:%d: sim 0x%04X, dta 0x%04X %s",evts,xing,t,
1120  d_sim,d_i,want_log?"ERROR":"") ;
1121 
1122  }
1123  if(want_print && log_level > 3) {
1124  printf("evt %d: S3 sim: xing %d:%d: sim 0x%04X, dta 0x%04X %s\n",evts,xing,t,
1125  d_sim,d_i,want_log?"ERROR":"") ;
1126  }
1127  }
1128 
1129 
1130  if(s3_failed) {
1131  event_bad |= 4 ;
1132  }
1133 
1134  return bad ;
1135 }
1136 
1137 // Main routine to run the simulations
1138 // type==0 if we only want to compare data from actual DAQ files
1139 // type==1 if this is a GEANT simulation and there are no actual DEP boards
1140 
1141 //u_short fcs_trg_base::run_event_sim(int xing, int type)
1142 u_int fcs_trg_base::run_event_sim(int xing, int type)
1143 {
1144  geom_t geo ;
1145 
1146  if(type) {
1147  memset(&d_out,0,sizeof(d_out)) ;
1148  }
1149 
1150  dbg_xing = xing ;
1151 
1152  for(int i=0;i<NS_COU;i++) { // NS
1153  geo.ns = i ;
1154 
1155  // for stage_2
1156  link_t ecal_in[DEP_ECAL_COU] ;
1157  link_t hcal_in[DEP_HCAL_COU] ;
1158  link_t fpre_in[DEP_PRE_COU] ;
1159 
1160  for(int j=0;j<ADC_DET_COU;j++) { // DET
1161  geo.det = j ;
1162 
1163  for(int k=0;k<DEP_COU;k++) { // DEP/ADC
1164  u_int s0_to_s1[32] ;
1165 
1166  if(tb_cou[i][j][k]==0) continue ; // this DEP/ADC wasn't filled
1167 
1168  geo.dep = k ;
1169 
1170  //if(realtime && (dep != k)) continue ;
1171 
1172  for(int c=0;c<32;c++) { // channel
1173  geo.ch = c ;
1174 
1175  u_int res ;
1176 
1177  stage_0(d_in[xing].s1[i][j][k].adc[c],geo,&(p_g[i][j][k][c]),&res) ;
1178 
1179  s0_to_s1[c] = res ;
1180 
1181  if(log_level>100) printf("... S0: xing %d: %d:%d:%d: ch %d = %d (ADC %d) (ped %d, gain %d) %s\n",xing,i,j,k,c,res,
1182  d_in[xing].s1[i][j][k].adc[c].d[0],
1183  p_g[i][j][k][c].ped,p_g[i][j][k][c].gain,
1184  res?"S1_HIT":"") ;
1185 
1186  if(log_level>101) {
1187  int sum = 0 ;
1188  for(int t=0;t<8;t++) {
1189  sum += d_in[xing].s1[i][j][k].adc[c].d[t] ;
1190  printf(" ADC %d = %d [sum %d, delta %d]\n",t,d_in[xing].s1[i][j][k].adc[c].d[t],sum,sum-p_g[i][j][k][c].ped) ;
1191  }
1192 
1193  printf("SSS0: %d %d %d %d %d\n",j,i,k,c,sum-p_g[i][j][k][c].ped) ;
1194  }
1195  }
1196 
1197  // so that we compare d_out.s1_to_s2 and d_in.s1_to_s2
1198  stage_1(s0_to_s1, geo, &d_out.s1[i][j][k].s1_to_s2) ;
1199 
1200  }
1201  }
1202 
1203  geo.det = 3 ;
1204  geo.dep = 1 ; // stage_2's
1205  geo.ch = 0 ; // ignored
1206 
1207  if(type==0) { // running in realtime or through DAQ file
1208  if(tb_cou[i][3][1]==0) continue ; // DEP/Stage_2 wasn't filled
1209 
1210  memset(ecal_in,0,sizeof(ecal_in)) ; //akio
1211  memset(hcal_in,0,sizeof(hcal_in)) ; //akio
1212  memset(fpre_in,0,sizeof(fpre_in)) ;
1213 
1214  for(int j=0;j<20;j++) {
1215  ecal_in[j] = d_in[xing].s2[i].s2_from_s1[j] ;
1216  }
1217  for(int j=0;j<8;j++) {
1218  hcal_in[j] = d_in[xing].s2[i].s2_from_s1[20+j] ;
1219  }
1220  for(int j=0;j<6;j++) {
1221  fpre_in[j] = d_in[xing].s2[i].s2_from_s1[28+j] ;
1222  }
1223 
1224  stage_2(ecal_in, hcal_in, fpre_in, geo, d_out.s2[i].s2_to_s3, &d_out.s2[i].s2_to_dsm) ;
1225  }
1226  else { // GEANT-like simulation
1227 
1228  for(int c=0;c<DEP_ECAL_COU;c++) {
1229  ecal_in[c] = d_out.s1[i][0][c].s1_to_s2 ;
1230  }
1231  for(int c=0;c<DEP_HCAL_COU;c++) {
1232  hcal_in[c] = d_out.s1[i][1][c].s1_to_s2 ; // FY19 fPRE
1233  }
1234  for(int c=0;c<DEP_PRE_COU;c++) {
1235  fpre_in[c] = d_out.s1[i][2][c].s1_to_s2 ; // FY19 fPRE
1236  }
1237 
1238  stage_2(ecal_in, hcal_in, fpre_in, geo, d_out.s2[i].s2_to_s3, &d_out.s2[i].s2_to_dsm) ;
1239  }
1240  }
1241 
1242 
1243  // stage_3
1244  geo.det = 3 ;
1245  geo.ns = 0 ;
1246  geo.dep = 0 ;
1247  geo.ch = 0 ;
1248 
1249  link_t l_in[4] ;
1250 
1251  if(type==0) { // from actual SFS file
1252  if(tb_cou[0][3][0]==0) return 0 ; // no stage_3 data present
1253 
1254  l_in[0] = d_in[xing].s3.s3_from_s2[0] ;
1255  l_in[1] = d_in[xing].s3.s3_from_s2[1] ;
1256  l_in[2] = d_in[xing].s3.s3_from_s2[2] ;
1257  l_in[3] = d_in[xing].s3.s3_from_s2[3] ;
1258 
1259  stage_3(l_in,&d_out.s3.dsm_out) ;
1260 
1261  }
1262  else {
1263 
1264 
1265  l_in[0] = d_out.s2[0].s2_to_s3[0] ;
1266  l_in[1] = d_out.s2[0].s2_to_s3[1] ;
1267  l_in[2] = d_out.s2[1].s2_to_s3[0] ;
1268  l_in[3] = d_out.s2[1].s2_to_s3[1] ;
1269 
1270  stage_3(l_in,&d_out.s3.dsm_out) ;
1271  }
1272 
1273  // return d_out.s3.dsm_out ; // not that the return is the _simulated_ DSM
1274  return d_out.s3.dsm_out
1275  + ((int)(d_out.s2[0].s2_to_dsm & 0xFF) << 16)
1276  + ((int)(d_out.s2[1].s2_to_dsm & 0xFF) << 24);
1277 
1278 }
1279 
1280 
1281 
1282 
1283 void fcs_trg_base::stage_0(adc_tick_t adc, geom_t geo, ped_gain_t *pg, u_int *dta_out)
1284 {
1285  switch(stage_version[0]) {
1286  case 0 :
1287  stage_0_201900(adc, geo, pg, dta_out) ;
1288  break ;
1289  case 1 :
1290  stage_0_202101(adc, geo, pg, dta_out) ;
1291  break ;
1292  case 2 :
1293  stage_0_202103(adc, geo, pg, dta_out) ;
1294  break ;
1295  case 3 : // current at start of FY22
1296  stage_0_202109(adc, geo, pg, dta_out) ;
1297  break ;
1298  default :
1299  *dta_out = 0 ;
1300  LOG(ERR,"stage_0: unknown version %d",stage_version[0]) ;
1301  }
1302 }
1303 
1304 
1305 
1306 
1307 void fcs_trg_base::stage_1(u_int s0[], geom_t geo, link_t *output)
1308 {
1309 
1310  switch(stage_version[1]) {
1311  case 0 :
1312  stage_1_201900(s0,geo,output) ;
1313  break ;
1314  case 1 : // at start of FY22
1315  stage_1_202201(s0,geo,output) ;
1316  break ;
1317  default :
1318  LOG(ERR,"Unknown stage_1 version %d",stage_version[1]) ;
1319  break ;
1320  }
1321 }
1322 
1323 
1324 // 2 links are output: lo & hi
1325 void fcs_trg_base::stage_2(link_t ecal[], link_t hcal[], link_t pres[], geom_t geo, link_t output[2], u_short* s2_to_dsm)
1326 {
1327  switch(stage_version[2]) {
1328  case 0 :
1329  stage_2_201900(ecal,hcal,pres,geo,output) ;
1330  break ;
1331  case 1 :
1332  stage_2_202201(ecal,hcal,pres,geo,output) ;
1333  break ;
1334  case 2 :
1335  stage_2_TAMU_202202(ecal,hcal,pres,geo,output) ;
1336  break ;
1337  case 3 : // at start of FY22
1338  stage_2_202203(ecal,hcal,pres,geo,output) ;
1339  break ;
1340  case 4 :
1341  stage_2_JP6_202204(ecal,hcal,pres,geo,output) ;
1342  break ;
1343  case 5 :
1344  stage_2_JP6Carl_202205(ecal,hcal,pres,geo,output) ;
1345  break ;
1346  case 6 :
1347  stage_2_JP5_202206(ecal,hcal,pres,geo,output) ;
1348  break ;
1349  case 7 : // for FY22
1350  stage_2_202207(ecal,hcal,pres,geo,output,s2_to_dsm) ;
1351  break ;
1352 
1353  // debugging versions below
1354  case 0xFF210201 :
1355  stage_2_tonko_202101(ecal,hcal,pres,geo,output) ;
1356  break ;
1357  case 0xFF210204 :
1358  stage_2_tonko_202104(ecal,hcal,pres,geo,output) ;
1359  break ;
1360  default :
1361  LOG(ERR,"Unknown stage_2 version %d",stage_version[2]) ;
1362  break ;
1363  }
1364 
1365 }
1366 
1367 
1368 // VERSION 0x0
1369 void fcs_trg_base::stage_3(link_t link[4], u_short *dsm_out)
1370 {
1371 
1372  switch(stage_version[3]) {
1373  case 0 :
1374  stage_3_201900(link,dsm_out) ;
1375  break ;
1376  case 1 :
1377  stage_3_202201(link,dsm_out) ;
1378  break ;
1379  case 3 : // at start of FY22
1380  stage_3_202203(link,dsm_out) ;
1381  break ;
1382  case 7 : // for FY22
1383  stage_3_202207(link,dsm_out) ;
1384  break ;
1385  // debugging versions below
1386  case 0xFF210201 :
1387  stage_3_tonko_202101(link, dsm_out) ;
1388  break ;
1389 
1390  default :
1391  LOG(ERR,"Unknown stage_3 version %d",stage_version[3]) ;
1392  break ;
1393  }
1394 
1395 }
1396