AlcapDAQ  1
crate.cpp
Go to the documentation of this file.
1 /*
2  Fake synchronizer based on Fred's
3  Generic modular MIDAS readout program.
4 */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <sys/time.h>
11 #include <sched.h>
12 
13 #include "midas.h"
14 #include "msystem.h"
15 
16 #include "odb_wrapper.h"
17 #include "crate.h"
18 #include "diag.h"
19 
20 /*
21  * MIDAS frontend boilerplate.
22  */
23 
24 /* from mfe.c */
25 extern int run_state;
26 extern int frontend_index;
27 
28 /* Interrupt state */
30 void (*interrupt_handler)() = NULL;
31 
32 /* The frontend name (client name) as seen by other MIDAS clients */
34 
35 /* The frontend file name, don't change it */
36 char *frontend_file_name = __FILE__;
37 
38 /* frontend_loop is called periodically if this variable is TRUE */
40 
41 /* a frontend status page is displayed with this frequency in ms */
42 //INT display_period = 500;
44 
45 /* maximum event size produced by this frontend */
46 #define MAX_DATA_SIZE 262144
48 
49 /* maximum event size for fragmented events (EQ_FRAGMENTED) */
51 
52 /* buffer size to hold events */
54 
55 /*-- Function declarations -----------------------------------------*/
56 extern "C" {
57  INT frontend_early_init();
58  INT frontend_init();
59  INT frontend_exit();
60  INT pre_begin_of_run(INT run_number, char *error);
61  INT begin_of_run(INT run_number, char *error);
62  INT end_of_run(INT run_number, char *error);
63  INT pause_run(INT run_number, char *error);
64  INT resume_run(INT run_number, char *error);
65  INT frontend_loop();
66  INT poll_event(INT source, INT count, BOOL test);
67  INT interrupt_configure(INT cmd, INT source, PTYPE adr);
68 };
69 INT read_trigger_event(char *pevent, INT off);
70 INT read_periodic_event(char *pevent, INT off);
71 
72 EQUIPMENT equipment[] = {
73  {"Crate ", /* equipment name */
74  {1000, TRIGGER_ALL, /* event ID, trigger mask */
75  "BUF", /* event buffer */
76  EQ_POLLED | EQ_EB, /* equipment type */
77  LAM_SOURCE(0, 0xFFFFFF), /* event source crate 0, all stations */
78  "MIDAS", /* format */
79  TRUE, /* enabled */
80  RO_RUNNING, /* read only when running */
81  500, /* poll for 500ms */
82  0, /* stop run after this event limit */
83  0, /* number of sub events */
84  0, /* don't log history */
85  "", "", ""},
86  read_trigger_event, /* readout routine */
87  },
88  {"Periodic N", /* equipment name */
89  {2000, 0, /* event ID, trigger mask */
90  "SYSTEM", /* event buffer */
91  EQ_PERIODIC, /* equipment type */
92  0, /* event source crate 0, all stations */
93  "MIDAS", /* format */
94  TRUE, /* enabled */
95  RO_RUNNING | RO_ODB, /* read only when running */
96  500, /* poll for 500ms */
97  0, /* stop run after this event limit */
98  0, /* number of sub events */
99  0, /* don't log history */
100  "", "", ""},
101  read_periodic_event, /* readout routine */
102  },
103  {""}
104 };
105 
106 /*
107  * List of modules in main fast event.
108  */
109 extern struct readout_module rpc_master_module;
110 extern struct readout_module rpc_slave_module;
111 //extern struct readout_module rpv130_module;
112 extern struct readout_module parport_module;
113 
116  //&rpv130_module,
118  &rpc_slave_module, // must be last!
119 };
120 int num_trigger_modules = sizeof(trigger_modules)/sizeof(trigger_modules[0]);
121 
122 struct timeval readout_finished_time;
123 
124 /*
125  * List of modules in periodic event.
126  */
127 extern struct readout_module s500_module;
128 
130  //&s500_module,
131 };
132 int num_periodic_modules = sizeof(periodic_modules)/sizeof(periodic_modules[0]);
133 
134 int cycle_active = 0;
135 bool event_avail = false;
136 
137 bool between_runs = true;
138 
139 int crate_number = -1;
140 
141 /*
142  * frontend_early_init: Called before most MIDAS subsystems are initialized,
143  * so we can set the name (etc.) of the frontend here.
144  */
146 {
147  // Determine our crate ID by comparing against a list of hostnames
148  printf("Entering frontend_early_init ... \n");
149  //char *hostnames[] = {"fe1", "fe2", "fe3", "turtle", "fe5", "fe6"};
150  //char *hostnames[] = {"fe1", "fe2", "daq2.MuSIC", "fe4", "fe5", "fe6", "fe7"};
151  //int crate_numbers[] = {1, 2, 3, 4, 5, 6, 9};
152  //char *hostnames[] = {"daq2.MuSIC"};
153  //int crate_numbers[] = {3};
154  //BOOL crate_has_periodic[] = {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE};
155 
156  //int num_hostnames = sizeof(hostnames)/sizeof(char *);
157 
158  //char my_hostname[256];
159 
160  //gethostname(my_hostname, sizeof(my_hostname));
161 
162 #if 0
163  BOOL has_periodic = FALSE;
164  for(int i = 0; i < num_hostnames; i++) {
165  if(!strcmp(my_hostname, hostnames[i])) {
166  crate_number = crate_numbers[i];
167  has_periodic = crate_has_periodic[i];
168  }
169  }
170 #endif
171 
172  crate_number = 3;
173  BOOL has_periodic = FALSE;
174 
175  printf("Hostname and crate cumber defined, crate number = %d ... \n",crate_number);
176 
177  if(crate_number > 0) {
178  frontend_name = new char[32];
179  strcpy(frontend_name, "Crate ");
180 
181 
182 #if 0
183  sprintf(equipment[0].name, "Crate %d", crate_number);
184  sprintf(equipment[0].info.buffer, "BUF%d", crate_number);
185  equipment[0].info.event_id = 1000 + crate_number;
186 #endif
188 
189  printf("Crate number = %d\n",crate_number);
190 
191  if(has_periodic) {
192  sprintf(equipment[1].name, "Periodic %d", crate_number);
193  equipment[1].info.event_id = 2000 + crate_number;
194  } else {
195  sprintf(equipment[1].name, "");
196  }
197  }
198  printf("Frontend early init returns success \n");
199  return SUCCESS;
200 }
201 
202 /* ********************************************************************* */
203 /*
204  * frontend_init: When the frontend program is started. This routine
205  * should initialize the hardware.
206  */
208 {
209  printf("Entering frontend_init() ... \n");
210  INT run_state = odb_get_int("/Runinfo/State");
211  if (run_state != STATE_STOPPED) {
212  cm_msg(MERROR, "Crate",
213  "Run must be stopped before starting crate program.");
214  return FE_ERR_HW;
215  }
216 
217  for(int i = 0; i < num_trigger_modules; i++) {
218  if((*trigger_modules[i]).init != NULL) {
219  int status = (*trigger_modules[i]).init();
220  if(status != SUCCESS) {
221  return status;
222  }
223  }
224  }
225 
226  for(int i = 0; i < num_periodic_modules; i++) {
227  if((*periodic_modules[i]).init != NULL) {
228  int status = (*periodic_modules[i]).init();
229  if(status != SUCCESS) {
230  return status;
231  }
232  }
233  }
234 
235  return SUCCESS;
236 }
237 
238 /* ********************************************************************* */
239 /*
240  * frontend_exit: When the frontend program is shut down. Can be used
241  * to release any locked resources like memory, commu-
242  * nications ports etc.
243  */
245 {
246  for(int i = 0; i < num_trigger_modules; i++) {
247  if((*trigger_modules[i]).exit != NULL) {
248  (*trigger_modules[i]).exit();
249  }
250  }
251 
252  for(int i = 0; i < num_periodic_modules; i++) {
253  if((*periodic_modules[i]).exit != NULL) {
254  (*periodic_modules[i]).exit();
255  }
256  }
257 
258  return SUCCESS;
259 }
260 
261 /*
262  * pre_begin_of_run: Called before a new run is started.
263  */
264 INT pre_begin_of_run(INT run_number, char *error)
265 {
266  diag_print(1, "*** Before begin of run %d ***\n", run_number);
267 
268  for(int i = 0; i < num_trigger_modules; i++) {
269  if((*trigger_modules[i]).pre_bor != NULL) {
270  int status = (*trigger_modules[i]).pre_bor();
271  if(status != SUCCESS) {
272  return status;
273  }
274  }
275  }
276 
277  for(int i = 0; i < num_periodic_modules; i++) {
278  if((*periodic_modules[i]).pre_bor != NULL) {
279  int status = (*periodic_modules[i]).pre_bor();
280  if(status != SUCCESS) {
281  return status;
282  }
283  }
284  }
285 
286 
287  return SUCCESS;
288 }
289 
290 /* ********************************************************************* */
291 /*
292  * begin_of_run: When a new run is started. Clear scalers, open
293  * rungates, etc.
294  */
295 INT begin_of_run(INT run_number, char *error)
296 {
297  diag_print(1, "*** Begin of run %d ***\n", run_number);
298 
299  for(int i = 0; i < num_trigger_modules; i++) {
300  if((*trigger_modules[i]).bor != NULL) {
301  int status = (*trigger_modules[i]).bor();
302  if(status != SUCCESS) {
303  return status;
304  }
305  }
306  }
307 
308  for(int i = 0; i < num_periodic_modules; i++) {
309  if((*periodic_modules[i]).bor != NULL) {
310  int status = (*periodic_modules[i]).bor();
311  if(status != SUCCESS) {
312  return status;
313  }
314  }
315  }
316 
317  cycle_active = 0;
318  event_avail = false;
319 
320  between_runs = false;
321 
322  return SUCCESS;
323 }
324 
325 /* ********************************************************************* */
326 /*
327  * end_of_run: Called on a request to stop a run. Can send
328  * end-of-run event and close run gates.
329  */
330 INT end_of_run(INT run_number, char *error)
331 {
332  diag_print(1, "*** End of run %d ***\n", run_number);
333 
334  between_runs = true;
335 
336  for(int i = 0; i < num_trigger_modules; i++) {
337  if((*trigger_modules[i]).eor != NULL) {
338  int status = (*trigger_modules[i]).eor();
339  if(status != SUCCESS) {
340  return status;
341  }
342  }
343  }
344 
345  for(int i = 0; i < num_periodic_modules; i++) {
346  if((*periodic_modules[i]).eor != NULL) {
347  int status = (*periodic_modules[i]).eor();
348  if(status != SUCCESS) {
349  return status;
350  }
351  }
352  }
353 
354 
355  return SUCCESS;
356 }
357 
358 /* ********************************************************************* */
359 /*
360  * pause_run: When a run is paused. Should disable trigger events.
361  */
362 INT pause_run(INT run_number, char *error)
363 {
364  return SUCCESS;
365 }
366 
367 /* ********************************************************************* */
368 /*
369  * resume_run: When a run is resumed. Should enable trigger events.
370  */
371 INT resume_run(INT run_number, char *error)
372 {
373  return SUCCESS;
374 }
375 
376 /* ********************************************************************* */
377 /*
378  * start_cycle
379  */
381 {
382  printf("starting new cycle in crate.cpp\n");
383  struct timeval restart_time;
384  gettimeofday(&restart_time, NULL);
385 
386  for(int i = 0; i < num_trigger_modules; i++) {
387  if((*trigger_modules[i]).start_cycle != NULL) {
388  (*trigger_modules[i]).start_cycle();
389  }
390  }
391 
392  diag_print(2, "Waited %f microseconds for restart.\n",
393  (restart_time.tv_sec-readout_finished_time.tv_sec)*1e6 +
394  (restart_time.tv_usec-readout_finished_time.tv_usec));
395 
396  cycle_active = 1;
397 }
398 
399 /*
400  * consider_start
401  */
403 {
404  for(int i = 0; i < num_trigger_modules; i++) {
405  if((*trigger_modules[i]).poll_dead != NULL) {
406  int status = (*trigger_modules[i]).poll_dead();
407 
408  if(status == FE_NEED_START && !event_avail) {
409  start_cycle();
410  } else if(status != SUCCESS) {
411  return status;
412  }
413  }
414  }
415 
416 }
417 
418 /*
419  * stop_cycle
420  */
422 {
423  for(int i = 0; i < num_trigger_modules; i++) {
424  if((*trigger_modules[i]).stop_cycle != NULL) {
425  (*trigger_modules[i]).stop_cycle();
426  }
427  }
428 }
429 
430 /* ********************************************************************* */
431 /*
432  * If frontend_call_loop is true, this routine gets called when
433  * the frontend is idle or once between every event
434  */
436 {
437  // If we're going to be pre-empted, get it over with during livetime
438  // rather than deadtime.
439  if (cycle_active || run_state != STATE_RUNNING || between_runs == TRUE) {
440  dm_area_flush();
441  sched_yield();
442  }
443 
444  // Exit immediately if no run in progress
445  if (run_state != STATE_RUNNING || between_runs == TRUE) {
446  return SUCCESS;
447  }
448 
449  // Call appropriate poll functions, depending on whether we're live or dead
450  //printf("fe loop: cycle_active %i\n",cycle_active);
451  if (cycle_active) {
452 
453  for(int i = 0; i < num_trigger_modules; i++) {
454  if((*trigger_modules[i]).poll_live != NULL) {
455 
456  // There are conditions that can lead to changes in run state between
457  // modules...
458  if (run_state != STATE_RUNNING || between_runs == TRUE) {
459  return SUCCESS;
460  }
461  int status = (*trigger_modules[i]).poll_live();
462 
463  if(status == FE_END_BLOCK) {
464  cycle_active = 0;
465  event_avail = true;
466  } else if(status == FE_NEED_STOP) {
467  stop_cycle();
468  } else if(status != SUCCESS) {
469  return status;
470  }
471  }
472  }
473  } else {
474  consider_start();
475  }
476 
477  return SUCCESS;
478 }
479 
480 /* ********************************************************************* */
481 /*
482  * Polling routine for events. Returns TRUE if event
483  * is available. If test equals TRUE, don't return. The test
484  * flag is used to time the polling.
485  */
486 INT poll_event(INT source, INT count, BOOL test)
487 {
488  INT retval = false;
489 
490  if(!test) {
491  count = 1;
492  }
493 
494  for (int i = 0; i < count; i++) {
495  frontend_loop();
496  if(event_avail) {
497  retval = true;
498  }
499  }
500 
501  return retval;
502 }
503 
504 /* ********************************************************************* */
505 INT interrupt_configure(INT cmd, INT source, PTYPE adr)
506 {
507  switch (cmd) {
508  case CMD_INTERRUPT_ENABLE:
510  break;
511  case CMD_INTERRUPT_DISABLE:
513  break;
514  case CMD_INTERRUPT_ATTACH:
515  interrupt_handler = (void (*)(void)) adr;
516  break;
517  case CMD_INTERRUPT_DETACH:
519  interrupt_handler = NULL;
520  break;
521  }
522  return SUCCESS;
523 }
524 
525 void print_diag_output(char *pevent)
526 {
527  printf("--------\n");
528 
529  printf("Event number: %d\n", (((EVENT_HEADER *)pevent)-1)->serial_number);
530 
531  BANK32 *pbk = NULL;
532  do {
533  DWORD *pdata;
534  int size = bk_iterate32(pevent, &pbk, &pdata);
535  if(pbk != NULL) {
536  printf("%c%c%c%c\t%d\t\t", pbk->name[0], pbk->name[1], pbk->name[2],
537  pbk->name[3], size);
538  for(int i = 0; i < MIN(4, size/4); i++) {
539  printf("0x%08x ", pdata[i]);
540  }
541  printf("\n");
542  }
543  } while(pbk != NULL);
544 
545  printf("--------\n");
546 }
547 
548 /* ********************************************************************* */
549 INT read_trigger_event(char *pevent, INT off)
550 {
551  diag_print(2, "Event has ended. Executing read_trigger_event.\n");
552 
553  // Remember that we have read out this event
554  event_avail = false;
555 
556  // Initialize the event
557  bk_init32(pevent);
558 
559  // Protection against readout after run has ended.
560  if (run_state != STATE_RUNNING) {
561  diag_print(1, "Readout after end of run!!!\n");
562  return bk_size(pevent);
563  }
564 
565  struct timeval readout_start_time;
566  gettimeofday(&readout_start_time, NULL);
567  // Ask trigger_modules to read out
568  for(int i = 0; i < num_trigger_modules; i++) {
569  if((*trigger_modules[i]).read != NULL) {
570  int status = (*trigger_modules[i]).read(pevent);
571  if(status != SUCCESS) {
572  return status;
573  }
574  }
575  }
576  gettimeofday(&readout_finished_time, NULL);
577  diag_print(2, "Spent %f microseconds for readout.\n",
578  (readout_finished_time.tv_sec-readout_start_time.tv_sec)*1e6 +
579  (readout_finished_time.tv_usec-readout_start_time.tv_usec));
580 
581  // Consider starting up the next block
582  consider_start();
583 
584  // Print a diagnostic
585  if(diag_print_threshold >= 2) {
586  print_diag_output(pevent);
587  }
588 
589  return bk_size(pevent);
590 }
591 
592 /* ********************************************************************* */
593 INT read_periodic_event(char *pevent, INT off)
594 {
595  diag_print(2, "Periodic event readout:\n");
596 
597  // Initialize the event
598  bk_init32(pevent);
599 
600  // Ask periodic_modules to read out
601  for(int i = 0; i < num_periodic_modules; i++) {
602  if((*periodic_modules[i]).read != NULL) {
603  int status = (*periodic_modules[i]).read(pevent);
604  if(status != SUCCESS) {
605  return status;
606  }
607  }
608  }
609 
610  // Print a diagnostic
611  if(diag_print_threshold >= 2) {
612  print_diag_output(pevent);
613  }
614 
615 
616  return bk_size(pevent);
617 }