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