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