PAASS
Software suite to Acquire and Analyze Data from Pixie16
poll2_core.cpp
Go to the documentation of this file.
1 
18 #include <algorithm>
19 #include <iostream>
20 #include <iomanip>
21 #include <fstream>
22 #include <string>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <sstream>
26 #include <ctime>
27 
28 #include <cmath>
29 
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <fcntl.h>
33 
34 #include "poll2_core.h"
35 #include "poll2_socket.h"
36 #include "poll2_stats.h"
37 
38 #include "CTerminal.h"
39 
40 // Interface for the PIXIE-16
41 #include "PixieSupport.h"
42 #include "Utility.h"
43 #include "Display.h"
44 
45 #include "MCA_ROOT.h"
46 #include "MCA_DAMM.h"
47 
48 // Values associated with the minimum timing between pixie calls (in us)
49 // Adjusted to help alleviate the issue with data corruption
50 #define POLL_TRIES 100
51 
52 // 4 GB. Maximum allowable .ldf file size in bytes
53 #define MAX_FILE_SIZE 4294967296ll
54 
55 // Length of shm packet header (in bytes)
56 #define PKT_HEAD_LEN 8
57 
58 // Maximum shm packet size (in bytes)
59 #define MAX_PKT_DATA (MAX_ORPH_DATA - PKT_HEAD_LEN)
60 
67 bool IsNumeric(const std::string &input_, const std::string &prefix_/*=""*/, const std::string &msg_/*=""*/){
68  for(size_t i = 0; i < input_.size(); i++){
69  if((input_[i] < 0x30 || input_[i] > 0x39) && input_[i] != 0x2D && input_[i] != 0x2E){
70  if(!msg_.empty()) std::cout << msg_ << " (" << input_ << ").\n";
71  return false;
72  }
73  }
74  return true;
75 }
76 
77 std::vector<std::string> chan_params = {"TRIGGER_RISETIME", "TRIGGER_FLATTOP", "TRIGGER_THRESHOLD", "ENERGY_RISETIME", "ENERGY_FLATTOP", "TAU", "TRACE_LENGTH",
78  "TRACE_DELAY", "VOFFSET", "XDT", "BASELINE_PERCENT", "EMIN", "BINFACTOR", "CHANNEL_CSRA", "CHANNEL_CSRB", "BLCUT",
79  "ExternDelayLen", "ExtTrigStretch", "ChanTrigStretch", "FtrigoutDelay", "FASTTRIGBACKLEN"};
80 
81 std::vector<std::string> mod_params = {"MODULE_CSRA", "MODULE_CSRB", "MODULE_FORMAT", "MAX_EVENTS", "SYNCH_WAIT", "IN_SYNCH", "SLOW_FILTER_RANGE",
82  "FAST_FILTER_RANGE", "MODULE_NUMBER", "TrigConfig0", "TrigConfig1", "TrigConfig2","TrigConfig3"};
83 
84 const std::vector<std::string> Poll::runControlCommands_ ({"run", "stop",
85  "startacq", "startvme", "stopacq", "stopvme", "timedrun", "acq", "shm", "spill",
86  "hup", "prefix", "fdir", "title", "runnum", "oform", "close", "reboot", "stats",
87  "mca"});
88 
89 const std::vector<std::string> Poll::paramControlCommands_ ({"dump", "pread",
90  "pmread", "pwrite", "pmwrite", "adjust_offsets", "find_tau", "toggle",
91  "toggle_bit", "csr_test", "bit_test", "get_traces"});
92 
93 const std::vector<std::string> Poll::pollStatusCommands_ ({"status", "thresh",
94  "debug", "quiet", "quit", "help", "version"});
95 
97  mca = NULL;
98  Zero();
99 }
100 
101 MCA_args::MCA_args(bool useRoot_, int totalTime_, std::string basename_){
102  running = false;
103  useRoot = useRoot_;
104  totalTime = totalTime_;
105  basename = basename_;
106 
107  mca = NULL;
108 }
109 
111  if(mca){ delete mca; }
112 }
113 
115  if(running){ return false; }
116 
117  pif_->RemovePresetRunLength(0);
118 
119  // Initialize the MCA object.
120 #if defined(USE_ROOT) && defined(USE_DAMM)
121  if(useRoot)
122  mca = (MCA*)(new MCA_ROOT(pif_, basename.c_str()));
123  else
124  mca = (MCA*)(new MCA_DAMM(pif_, basename.c_str()));
125 #elif defined(USE_ROOT)
126  mca = (MCA*)(new MCA_ROOT(pif_, basename.c_str()));
127 #elif defined(USE_DAMM)
128  mca = (MCA*)(new MCA_DAMM(pif_, basename.c_str()));
129 #endif
130 
131  pif_->StartHistogramRun();
132 
133  if(!mca->IsOpen()){
134  pif_->EndRun();
135  return false;
136  }
137 
138  return (running = true);
139 }
140 
142  if(!mca){ return false; }
143  return mca->Step();
144 }
145 
147  if(!mca || (totalTime <= 0 || (mca->GetRunTime() >= totalTime))){ return false; }
148  return true;
149 }
150 
152  running = false;
153  useRoot = false;
154  totalTime = 0; // Needs to be zero for checking of MCA arguments
155  basename = "MCA";
156 
157  if(mca){
158  delete mca;
159  mca = NULL;
160  }
161 }
162 
164  pif_->EndRun();
165  Zero();
166 }
167 
169  // System flags and variables
170  sys_message_head(" POLL: "),
171  kill_all(false), // Set to true when the program is exiting
172  do_start_acq(false), // Set to true when the command is given to start a run
173  do_stop_acq(false), // Set to true when the command is given to stop a run
174  record_data(false), // Set to true if data is to be recorded to disk
175  do_reboot(false), // Set to true when the user tells POLL to reboot PIXIE
176  force_spill(false), // Force poll2 to dump the current data spill
177  acq_running(false), // Set to true when run_command is recieving data from PIXIE
178  run_ctrl_exit(false), // Set to true when run_command exits
179  had_error(false), //Set to true when aborting due to an error.
180  file_open(false), //Set to true when a file is opened.
181  raw_time(0),
182  do_MCA_run(false), // Set to true when the "mca" command is received
183  // Run control variables
184  boot_fast(false),
185  insert_wall_clock(true),
186  is_quiet(false),
187  send_alarm(false),
188  show_module_rates(false),
189  zero_clocks(false),
190  debug_mode(false),
191  shm_mode(false),
192  pac_mode(false),
193  init(false),
194  runTime(-1.0),
195  // Options relating to output data file
196  output_directory("./"), // Set with 'fdir' command
197  filename_prefix("run"),
198  output_title("PIXIE data file"), // Set with 'title' command
199  next_run_num(1), // Set with 'runnum' command
200  output_format(0), // Set with 'oform' command
201  current_file_num(0),
202  // Some pacman stuff
203  udp_sequence(0),
204  total_spill_chunks(0)
205 {
206  pif = new PixieInterface("pixie.cfg");
207 
208  // Check the scheduler (kernel priority)
209  Display::LeaderPrint("Checking scheduler");
210  int startScheduler = sched_getscheduler(0);
211  if(startScheduler == SCHED_BATCH){
212  std::cout << Display::InfoStr("SCHED_BATCH") << std::endl;
213  }
214  else if(startScheduler == SCHED_OTHER){
215  std::cout << Display::InfoStr("STANDARD (SCHED_OTHER)") << std::endl;
216  }
217  else{ std::cout << Display::WarningStr("UNEXPECTED") << std::endl; }
218 
219  client = new Client();
220 
221 }
222 
224  if(init){
225  Close();
226  }
227 
228  delete pif;
229 }
230 
232  for (int mod=0; mod<pif->GetNumberCards(); mod++) {
233  unsigned short revision, adcBits, adcMsps;
234  unsigned int serialNumber;
235  if (pif->GetModuleInfo(mod, &revision, &serialNumber, &adcBits, &adcMsps)) {
236  std::cout << "Module " << std::right << std::setw(2) << mod << ": " <<
237  "Serial Number " << std::right << std::setw(4) << serialNumber << ", " <<
238  "Rev " << std::hex << std::uppercase << revision << std::dec << " " <<
239  "(" << revision << "), " <<
240  adcBits << "-bit " << adcMsps << " MS/s " <<
241  std::endl;
242  }
243  }
244 }
245 
247  if(init){ return false; }
248 
249  // Set debug mode
250  if(debug_mode){
251  std::cout << sys_message_head << "Setting debug mode\n";
253  }
254 
255  // Initialize the pixie interface and boot
256  pif->GetSlots();
257  if(!pif->Init()){ return false; }
258 
259  PrintModuleInfo();
260 
261  //Boot the modules.
262  if(boot_fast){
264  }
265  else{
266  if(!pif->Boot(PixieInterface::BootAll)){ return false; }
267  }
268 
269  //Set module syncronization parameters
270  if(!synch_mods()){ return false; }
271 
272  // Allocate memory buffers for FIFO
274 
275  if(pac_mode){
276  //Initialize pacman data port
277  client->Init("127.0.0.1", 45080);
278 
279  //Initialize pacman command port
280  server = new Server();
281  server->Init(45086, 1); // Set the timeout to 1 second.
282  }
283  else{
284  //Initialize Cory's shm port
285  // This port number is used to avoid tying up udptoipc's port
286  client->Init("127.0.0.1", 5555);
287  }
288 
289  //Allocate an array of vectors to store partial events from the FIFO.
290  partialEvents = new std::vector<word_t>[n_cards];
291 
292  //Create a stats handler and set the interval.
295 
296  //Build the list of commands
297  commands_.insert(commands_.begin(), pollStatusCommands_.begin(), pollStatusCommands_.end());
298  commands_.insert(commands_.begin(), paramControlCommands_.begin(), paramControlCommands_.end());
299  //Omit the run control commands.
300  if (!pac_mode) {
301  commands_.insert(commands_.begin(), runControlCommands_.begin(), runControlCommands_.end());
302  }
303 
304  return init = true;
305 }
306 
311 bool Poll::Close(){
312  //We return if the class has not been initialized.
313  if(!init){ return false; }
314 
315  //Send message to Cory's SHM that we are closing.
316  if(!pac_mode){ client->SendMessage((char *)"$KILL_SOCKET", 13); }
317  //Close the pacman command port.
318  else{ server->Close(); }
319  //Close the UDP data / SHM port.
320  client->Close();
321 
322  // Close any open files.
324 
325  //Delete the array of partial event vectors.
326  delete[] partialEvents;
327  partialEvents = NULL;
328 
329  delete statsHandler;
330  statsHandler = NULL;
331 
332  // We are no longer initialized.
333  init = false;
334 
335  return true;
336 }
337 
345 bool Poll::CloseOutputFile(const bool continueRun /*=false*/){
346  Display::LeaderPrint("Closing output file");
347 
348  //No file was open.
349  if(!output_file.IsOpen()){
350  std::cout << Display::WarningStr() << std::endl;
351  std::cout << "|- No file is open.\n";
352  file_open = false;
353  return false;
354  }
355 
356  //Clear the stats
357  if (!continueRun){
358  statsHandler->Clear();
359  statsHandler->Dump();
360  }
361 
363 
364  //Broadcast to Cory's SHM that the file is now closed.
365  if(!pac_mode){ client->SendMessage((char *)"$CLOSE_FILE", 12); }
366 
367  //Set the flag that no file is open.
368  file_open = false;
369  std::cout << Display::OkayStr() << std::endl;
370 
371  //We call get next file name to update the run number.
372  if (!continueRun) {
374  }
375 
376  return true;
377 }
378 
391 bool Poll::OpenOutputFile(bool continueRun){
392  Display::LeaderPrint("Opening output file");
393  //A file was already open
394  if(output_file.IsOpen()){
395  std::cout << Display::ErrorStr() << std::endl;
396  std::cout << "|- A file is already open!\n";
397  CloseOutputFile();
398 
399  had_error = true;
400  record_data = false;
401 
402  return false;
403  }
404 
405  //Try to open a file and check if unsuccessful.
407  std::cout << Display::ErrorStr() << std::endl;
408  //Unsuccessful when opening file print a message.
409  std::cout << "|- Failed to open output file! Check that the path is correct.\n";
410  std::cout << "|- Filename: '" << output_file.GetCurrentFilename() << "'.\n";
411 
412  //Set the error flag and disable data recording.
413  had_error = true;
414  record_data = false;
415 
416  return false;
417  }
418  std::cout <<Display::OkayStr() <<std::endl;
419  std::cout << "|- Filename: '" << output_file.GetCurrentFilename() << "'.\n";
420 
421  //Clear the stats
422  statsHandler->Clear();
423  statsHandler->Dump();
424 
425  //When using Cory's SHM send a message that the file is open.
426  if(!pac_mode){ client->SendMessage((char *)"$OPEN_FILE", 12); }
427 
428  file_open = true;
429 
430  return true;
431 }
432 
434  static bool firstTime = true;
435  static char synchString[] = "IN_SYNCH";
436  static char waitString[] = "SYNCH_WAIT";
437 
438  bool hadError = false;
439  Display::LeaderPrint("Synchronizing");
440 
441  if(firstTime){
442  // only need to set this in the first module once
443  if(!pif->WriteSglModPar(waitString, 1, 0)){ hadError = true; }
444  firstTime = false;
445  }
446 
447  for(unsigned int mod = 0; mod < pif->GetNumberCards(); mod++){
448  if (!pif->WriteSglModPar(synchString, 0, mod)){ hadError = true; }
449  }
450 
451  if (!hadError){ std::cout << Display::OkayStr() << std::endl; }
452  else{ std::cout << Display::ErrorStr() << std::endl; }
453 
454  return !hadError;
455 }
456 
457 int Poll::write_data(word_t *data, unsigned int nWords){
458  // Open an output file if needed
459  if(!output_file.IsOpen()){
460  std::cout << Display::ErrorStr() << " Recording data, but no file is open!\n";
461  do_stop_acq = true;
462  had_error = true;
463  return 0;
464  }
465 
466  // Handle the writing of buffers to the file
467  std::streampos current_filesize = output_file.GetFilesize();
468  if(current_filesize + (std::streampos)(4*nWords + 65552) > MAX_FILE_SIZE){
469  // Adding nWords plus 2 EOF buffers to the file will push it over MAX_FILE_SIZE.
470  // Open a new output file instead
471  std::cout << sys_message_head << "Maximum ifile size reached. New output file will be created.\n";
472  std::cout << sys_message_head << "Current filesize is " << current_filesize + (std::streampos)65552 << " bytes.\n";
473  CloseOutputFile(true);
474  OpenOutputFile(true);
475  }
476 
477  if (!is_quiet) std::cout << "Writing " << nWords << " words.\n";
478 
479  return output_file.Write((char*)data, nWords);
480 }
481 
482 void Poll::broadcast_data(word_t *data, unsigned int nWords) {
483  // Maximum size of the shared memory buffer
484  static const unsigned int maxShmSizeL = 4050; // in pixie words
485  static const unsigned int maxShmSize = maxShmSizeL * sizeof(word_t); // in bytes
486 
487  if(pac_mode){ // Broadcast the spill onto the network using the classic pacman shm style
488  unsigned int nBufs = nWords / maxShmSizeL;
489  unsigned int wordsLeft = nWords % maxShmSizeL;
490 
491  unsigned int totalBufs = nBufs + 1 + ((wordsLeft != 0) ? 1 : 0);
492 
493  if (debug_mode) std::cout << "Broadcasting " << totalBufs << " pacman buffers.\n";
494 
495  word_t *pWrite = (word_t *)AcqBuf.Data;
496 
497  // Chop the data and send it through the network
498  for(size_t buf=0; buf < nBufs; buf++){
499  // Get a long sized pointer to the data block for writing
500  // put a header on each shared memory buffer
501  AcqBuf.BufLen = (maxShmSizeL + 3) * sizeof(word_t);
502  pWrite[0] = AcqBuf.BufLen; // size
503  pWrite[1] = totalBufs; // number of buffers we expect
504  pWrite[2] = buf;
505  memcpy(&pWrite[3], &data[buf * maxShmSizeL], maxShmSize);
506 
508  usleep(1);
509  }
510 
511  // Send the last fragment (if there is any)
512  if (wordsLeft != 0) {
513  AcqBuf.BufLen = (wordsLeft + 3) * sizeof(word_t);
514  pWrite[0] = AcqBuf.BufLen;
515  pWrite[1] = totalBufs;
516  pWrite[2] = nBufs;
517  memcpy(&pWrite[3], &data[nBufs * maxShmSizeL],
518  wordsLeft * sizeof(word_t) );
519 
521  usleep(1);
522  }
523 
524  // Send a buffer to say that we are done
525  AcqBuf.BufLen = 5 * sizeof(word_t);
526  pWrite[0] = AcqBuf.BufLen;
527  pWrite[1] = totalBufs;
528  pWrite[2] = totalBufs - 1;
529 
530  // Pacman looks for the following data
531  pWrite[3] = 0x2;
532  pWrite[4] = 0x270f; // vsn 9999
533 
535  }
536  else if(shm_mode){ // Broadcast the spill onto the network using the new shm style
537  int shm_data[maxShmSizeL+2]; // packets of data
538  unsigned int num_net_chunks = nWords / maxShmSizeL;
539  unsigned int num_net_remain = nWords % maxShmSizeL;
540  if(num_net_remain != 0){ num_net_chunks++; }
541 
542  unsigned int net_chunk = 1;
543  unsigned int words_bcast = 0;
544  if(debug_mode){ std::cout << " debug: Splitting " << nWords << " words into network spill of " << num_net_chunks << " chunks (fragment = " << num_net_remain << " words)\n"; }
545 
546  while(words_bcast < nWords){
547  if(nWords - words_bcast > maxShmSizeL){ // Broadcast the spill chunks
548  memcpy(&shm_data[0], &net_chunk, 4);
549  memcpy(&shm_data[1], &num_net_chunks, 4);
550  memcpy(&shm_data[2], &data[words_bcast], maxShmSize);
551  client->SendMessage((char *)shm_data, maxShmSize+8);
552  words_bcast += maxShmSizeL;
553  }
554  else{ // Broadcast the spill remainder
555  memcpy(&shm_data[0], &net_chunk, 4);
556  memcpy(&shm_data[1], &num_net_chunks, 4);
557  memcpy(&shm_data[2], &data[words_bcast], (nWords-words_bcast)*4);
558  client->SendMessage((char *)shm_data, (nWords - words_bcast + 2)*4);
559  words_bcast += nWords-words_bcast;
560  }
561  usleep(1);
562  net_chunk++;
563  }
564  }
565  else{ // Broadcast a spill notification to the network
567  }
568 }
569 
571  const int BufEnd=0xFFFFFFFF;
572  short int status, cont_pkt;
573  char *bufptr;
574  int size,bytes;
575 
576  size = AcqBuf.BufLen;
577  memcpy(AcqBuf.Data+size, &BufEnd, 4);
578  size += 4;
579  if(size % 2 != 0){
580  memcpy(AcqBuf.Data+size,&BufEnd,2);
581  size+=2;
582  }
583 
584  if (debug_mode) std::cout << "PAC broadcast size " << size << "/" << MAX_PKT_DATA << " B.\n";
585 
586  if(size <= MAX_PKT_DATA){
588  AcqBuf.DataSize = size + 8;
590  AcqBuf.Events = 1;
591  AcqBuf.Cont=0;
592 
593  status = client->SendMessage((char *)&AcqBuf, size + PKT_HEAD_LEN + 8);
594  if(status < 0){ std::cout << Display::WarningStr("[WARNING]") << ": Error sending UDP message to pacman."; }
595 
596  return;
597  }
598 
599  cont_pkt = 1;
600  bufptr =(char *)&AcqBuf;
602  //This loops through the large data packet and writes the header info into
603  // data_pack::Data for each packet as it goes along. It does not follow the structure.
604  do {
605  if(size > MAX_PKT_DATA){
606  bytes = MAX_PKT_DATA;
607  *((unsigned short *)(bufptr+PKT_HEAD_LEN+4)) = 0; //Events
608  }
609  else{
610  bytes = size;
611  *((unsigned short *)(bufptr+PKT_HEAD_LEN+4)) = 1; //Events
612  }
613  *((int *)(bufptr+PKT_HEAD_LEN)) = total_spill_chunks; //TotalEvents
614  *((unsigned short *)(bufptr+PKT_HEAD_LEN+6)) = cont_pkt; //Cont
615  *((unsigned int *)(bufptr)) = udp_sequence++; //Sequence
616  *((int *)(bufptr+4)) = bytes+8; //DataSize
617 
618  status = client->SendMessage((char *)bufptr, bytes + PKT_HEAD_LEN + 8);
619  if(status < 0){ std::cout << Display::WarningStr("[WARNING]") << ": Error sending UDP message to pacman."; }
620 
621  cont_pkt++;
622  bufptr += bytes;
623  size = size - bytes;
624  } while (size > 0);
625 }
626 
627 /* Print help dialogue for POLL options. */
628 void Poll::help(){
629  std::cout << " Help:\n";
630  if(!pac_mode){
631  std::cout << " run - Start data acquisition and start recording data to disk\n";
632  std::cout << " stop - Stop data acqusition and stop recording data to disk\n";
633  std::cout << " startacq (startvme) - Start data acquisition\n";
634  std::cout << " stopacq (stopvme) - Stop data acquisition\n";
635  std::cout << " timedrun <seconds> - Run for the specified number of seconds\n";
636  std::cout << " acq (shm) - Run in \"shared-memory\" mode\n";
637  std::cout << " spill (hup) - Force dump of current spill\n";
638  std::cout << " prefix [name] - Set the output filename prefix (default='run_#.ldf')\n";
639  std::cout << " fdir [path] - Set the output file directory (default='./')\n";
640  std::cout << " title [runTitle] - Set the title of the current run (default='PIXIE Data File)\n";
641  std::cout << " runnum [number] - Set the number of the current run (default=0)\n";
642  std::cout << " oform [0|1|2] - Set the format of the output file (default=0)\n";
643  std::cout << " reboot - Reboot PIXIE crate\n";
644  std::cout << " stats [time] - Set the time delay between statistics dumps (default=-1)\n";
645  std::cout << " mca [root|damm] [time] [filename] - Use MCA to record data for debugging purposes\n";
646  }
647  std::cout << " dump [filename] - Dump pixie settings to file (default='Fallback.set')\n";
648  std::cout << " pread <mod> <chan> <param> - Read parameters from individual PIXIE channels\n";
649  std::cout << " pmread <mod> <param> - Read parameters from PIXIE modules\n";
650  std::cout << " pwrite <mod> <chan> <param> <val> - Write parameters to individual PIXIE channels\n";
651  std::cout << " pmwrite <mod> <param> <val> - Write parameters to PIXIE modules\n";
652  std::cout << " adjust_offsets <module> - Adjusts the baselines of a pixie module\n";
653  std::cout << " find_tau <module> <channel> - Finds the decay constant for an active pixie channel\n";
654  std::cout << " toggle <module> <channel> <bit> - Toggle any of the 19 CHANNEL_CSRA bits for a pixie channel\n";
655  std::cout << " toggle_bit <mod> <chan> <param> <bit> - Toggle any bit of any parameter of 32 bits or less\n";
656  std::cout << " csr_test <number> - Output the CSRA parameters for a given integer\n";
657  std::cout << " bit_test <num_bits> <number> - Display active bits in a given integer up to 32 bits long\n";
658  std::cout << " get_traces <mod> <chan> [threshold] - Get traces for all channels in a specified module\n";
659  std::cout << " status - Display system status information\n";
660  std::cout << " thresh [threshold] - Modify or display the current polling threshold.\n";
661  std::cout << " debug - Toggle debug mode flag (default=false)\n";
662  std::cout << " quiet - Toggle quiet mode flag (default=false)\n";
663  std::cout << " quit - Close the program\n";
664  std::cout << " help (h) - Display this dialogue\n";
665  std::cout << " version (v) - Display Poll2 version information\n";
666 }
667 
668 /* Print help dialogue for reading/writing pixie channel parameters. */
670  std::cout << " Valid Pixie16 channel parameters:\n";
671  for(unsigned int i = 0; i < chan_params.size(); i++){
672  std::cout << " " << chan_params[i] << "\n";
673  }
674 }
675 
676 /* Print help dialogue for reading/writing pixie module parameters. */
678  std::cout << " Valid Pixie16 module parameters:\n";
679  for(unsigned int i = 0; i < mod_params.size(); i++){
680  std::cout << " " << mod_params[i] << "\n";
681  }
682 }
683 
692 bool Poll::start_run(const bool &record_/*=true*/, const double &time_/*=-1.0*/){
693  if(do_MCA_run){
694  std::cout << sys_message_head << "Warning! Cannot run acquisition while MCA program is running\n";
695  return false;
696  }
697  else if(acq_running){
698  std::cout << sys_message_head << "Acquisition is already running\n";
699  return false;
700  }
701 
702  // Set the acquistion time.
703  runTime = time_;
704 
705  if(runTime > 0.0)
706  std::cout << sys_message_head << "Running for approximately " << runTime << " seconds.\n";
707 
708  record_data = record_;
709 
710  //Start the acquistion
711  do_start_acq = true;
712 
713  return true;
714 }
715 
722  if(!acq_running && !do_MCA_run){
723  std::cout << sys_message_head << "Acquisition is not running\n";
724  return false;
725  }
726 
727  // Stop the acquisition.
728  do_stop_acq = true;
729 
730  if (record_data) {
731  std::stringstream output;
732  output << "Run " << output_file.GetRunNumber() << " time";
733  Display::LeaderPrint(output.str());
734  std::cout << statsHandler->GetTotalTime() << "s\n";
735 
736  }
737 
738  record_data = false;
739 
740  return true;
741 }
742 
744  std::cout << " Poll Run Status:\n";
745  std::cout << " Acq starting - " << yesno(do_start_acq) << std::endl;
746  std::cout << " Acq stopping - " << yesno(do_stop_acq) << std::endl;
747  std::cout << " Acq running - " << yesno(acq_running) << std::endl;
748  if(!pac_mode){
749  std::cout << " Shared memory - " << yesno(shm_mode) << std::endl;
750  std::cout << " Write to disk - " << yesno(record_data) << std::endl;
751  std::cout << " File open - " << yesno(output_file.IsOpen()) << std::endl;
752  std::cout << " Rebooting - " << yesno(do_reboot) << std::endl;
753  std::cout << " Force Spill - " << yesno(force_spill) << std::endl;
754  std::cout << " Do MCA run - " << yesno(do_MCA_run) << std::endl;
755  }
756  else{ std::cout << " Pacman mode - " << yesno(pac_mode) << std::endl; }
757  std::cout << " Run ctrl Exited - " << yesno(run_ctrl_exit) << std::endl;
758 
759  std::cout << "\n Poll Options:\n";
760  std::cout << " Boot fast - " << yesno(boot_fast) << std::endl;
761  std::cout << " Wall clock - " << yesno(insert_wall_clock) << std::endl;
762  std::cout << " Is quiet - " << yesno(is_quiet) << std::endl;
763  std::cout << " Send alarm - " << yesno(send_alarm) << std::endl;
764  std::cout << " Show rates - " << yesno(show_module_rates) << std::endl;
765  std::cout << " Zero clocks - " << yesno(zero_clocks) << std::endl;
766  std::cout << " Debug mode - " << yesno(debug_mode) << std::endl;
767  std::cout << " Initialized - " << yesno(init) << std::endl;
768 }
769 
771  float threshPercent = (float) threshWords / EXTERNAL_FIFO_LENGTH * 100;
772  std::cout << sys_message_head << "Polling Threshold = " << threshPercent << "% (" << threshWords << "/" << EXTERNAL_FIFO_LENGTH << ")\n";
773 }
774 
776 void Poll::get_traces(int mod_, int chan_, int thresh_/*=0*/){
777  size_t trace_size = PixieInterface::GetTraceLength();
778  size_t module_size = pif->GetNumberChannels() * trace_size;
779  std::cout << sys_message_head << "Searching for traces from mod = " << mod_ << ", chan = " << chan_ << " above threshold = " << thresh_ << ".\n";
780  std::cout << sys_message_head << "Allocating " << (trace_size+module_size)*sizeof(unsigned short) << " bytes of memory for pixie traces.\n";
781  std::cout << sys_message_head << "Searching for traces. Please wait...\n";
782  poll_term_->flush();
783 
784  unsigned short *trace_data = new unsigned short[trace_size];
785  unsigned short *module_data = new unsigned short[module_size];
786  memset(trace_data, 0, sizeof(unsigned short)*trace_size);
787  memset(module_data, 0, sizeof(unsigned short)*module_size);
788 
789  GetTraces gtraces(module_data, module_size, trace_data, trace_size, thresh_);
790  forChannel(pif, mod_, chan_, gtraces, (int)0);
791 
792  if(!gtraces.GetStatus()){ std::cout << sys_message_head << "Failed to find trace above threshold in " << gtraces.GetAttempts() << " attempts!\n"; }
793  else{ std::cout << sys_message_head << "Found trace above threshold in " << gtraces.GetAttempts() << " attempts.\n"; }
794 
795  std::cout << " Baselines:\n";
796  for(unsigned int channel = 0; channel < pif->GetNumberChannels(); channel++){
797  if(channel == (unsigned)chan_){ std::cout << "\033[0;33m"; }
798  if(channel < 10){ std::cout << " 0" << channel << ": "; }
799  else{ std::cout << " " << channel << ": "; }
800  std::cout << "\t" << gtraces.GetBaseline(channel);
801  std::cout << "\t" << gtraces.GetMaximum(channel) << std::endl;
802  if(channel == (unsigned)chan_){ std::cout << "\033[0m"; }
803  }
804 
805  std::ofstream get_traces_out("/tmp/traces.dat");
806  if(!get_traces_out.good()){ std::cout << sys_message_head << "Could not open /tmp/traces.dat!\n"; }
807  else{ // Write the output file.
808  // Add a header.
809  get_traces_out << "time";
810  for(size_t channel = 0; channel < pif->GetNumberChannels(); channel++){
811  if(channel < 10){ get_traces_out << "\tC0" << channel; }
812  else{ get_traces_out << "\tC" << channel; }
813  }
814  get_traces_out << std::endl;
815 
816  // Write channel traces.
817  for(size_t index = 0; index < trace_size; index++){
818  get_traces_out << index;
819  for(size_t channel = 0; channel < pif->GetNumberChannels(); channel++){
820  get_traces_out << "\t" << module_data[(channel * trace_size) + index];
821  }
822  get_traces_out << std::endl;
823  }
824  std::cout << sys_message_head << "Traces written to '/tmp/traces.dat'." << std::endl;
825  }
826  get_traces_out.close();
827 
828  delete[] trace_data;
829  delete[] module_data;
830 }
831 
838 bool Poll::SplitParameterArgs(const std::string &arg, int &start, int &stop) {
839  //If a character is found that is nonnumeric or is not the delimeter we stop.
840  if (arg.find_first_not_of("-0123456789:") != std::string::npos) return false;
841 
842  size_t delimeterPos = arg.find(':');
843  try {
844  start = std::stoi(arg.substr(0, delimeterPos));
845  //If the delimeter was found we can seperate the stop otherwise set start = stop.
846  if (delimeterPos != std::string::npos) {
847  stop = std::stoi(arg.substr(delimeterPos + 1));
848  if (start < 0 || stop < 0 || start > stop) return false;
849  }
850  else stop = start;
851  }
852  catch (const std::invalid_argument &ia) {
853  return false;
854  }
855  return true;
856 }
858 // Poll::CommandControl
860 
861 /* Function to control the POLL command line interface */
862 void Poll::CommandControl(){
863  std::string cmd = "", arg;
864 
865  while(true){
866  if(kill_all){ // Check if poll has been killed externally (pacman)
867  while(!run_ctrl_exit){ sleep(1); }
868  break;
869  }
870  if(pac_mode){ // Check for commands from pacman, if enabled
871  int select_dummy;
872  if(server->Select(select_dummy)){
873  UDP_Packet pacman_command;
874 
875  // We have a pacman command. Retrieve the command
876  server->RecvMessage((char *)&pacman_command, sizeof(UDP_Packet));
877 
878  /* Valid poll commands
879  0x11 - INIT_ACQ
880  0x22 - START_ACQ
881  0x33 - STOP_ACQ
882  0x44 - STATUS_ACQ
883  0x55 - PAC_FILE
884  0x66 - HOST
885  0x77 - ZERO_CLK
886  Return codes:
887  0x00 - ACQ_OK
888  0x01 - ACQ_RUN
889  0x02 - ACQ_STOP
890  0xFB - ACQ_STP_HALT
891  0xFC - ACQ_STR_RUN*/
892 
893  if(pacman_command.Data[0] == 0x11){ // INIT_ACQ
894  std::cout << "RECV PACMAN COMMAND 0x11 (INIT_ACQ)\n";
895  pacman_command.Data[0] = 0x00;
896  }
897  else if(pacman_command.Data[0] == 0x22){ // START_ACQ
898  std::cout << "RECV PACMAN COMMAND 0x22 (START_ACQ)\n";
899  if(acq_running){ pacman_command.Data[0] = 0xFC; }
900  else{ pacman_command.Data[0] = 0x00; }
901  do_start_acq = true;
902  }
903  else if(pacman_command.Data[0] == 0x33){ // STOP_ACQ
904  std::cout << "RECV PACMAN COMMAND 0x33 (STOP_ACQ)\n";
905  if(!acq_running){ pacman_command.Data[0] = 0xFB; }
906  else{ pacman_command.Data[0] = 0x00; }
907  do_stop_acq = true;
908  }
909  else if(pacman_command.Data[0] == 0x44){ // STATUS_ACQ
910  std::cout << "RECV PACMAN COMMAND 0x44 (STATUS_ACQ)\n";
911  pacman_command.Data[0] = 0x00;
912  pacman_command.Data[1] = acq_running ? 0x01 : 0x02;
913  }
914  else if(pacman_command.Data[0] == 0x55){ // PAC_FILE
915  std::cout << "RECV PACMAN COMMAND 0x55 (PAC_FILE)\n";
916  pacman_command.Data[0] = 0x00;
917  }
918  else if(pacman_command.Data[0] == 0x66){ // HOST
919  std::cout << "RECV PACMAN COMMAND 0x66 (HOST)\n";
920  pacman_command.Data[0] = 0x00;
921  }
922  else if(pacman_command.Data[0] == 0x77){ // ZERO_CLK
923  std::cout << "RECV PACMAN COMMAND 0x77 (ZERO_CLK)\n";
924  pacman_command.Data[0] = 0x00;
925  }
926  else{
927  std::cout << "RECV PACMAN COMMAND 0x" << std::hex << (int)pacman_command.Data[0] << std::dec << " (?)\n";
928  pacman_command.Data[0] = 0x00;
929  }
930 
931  // Send the reply to pacman
932  server->SendMessage((char *)&pacman_command, sizeof(UDP_Packet));
933  }
934  }
935 
936  cmd = poll_term_->GetCommand(arg);
937  if(cmd == "_SIGSEGV_"){
938  std::cout << Display::ErrorStr("SEGMENTATION FAULT") << std::endl;
939  Close();
940  exit(EXIT_FAILURE);
941  }
942  else if(cmd == "CTRL_D"){
943  std::cout << sys_message_head << "Received EOF (ctrl-d) signal. Exiting...\n";
944  cmd = "quit";
945  }
946  else if(cmd == "CTRL_C"){
947  std::cout << sys_message_head << "Received SIGINT (ctrl-c) signal.";
948  if (do_MCA_run) {
949  std::cout << " Stopping MCA...\n";
950  cmd = "stop";
951  }
952  else {
953  std::cout << " Ignoring signal.\n";
954  continue;
955  }
956  }
957  else if(cmd == "CTRL_Z"){
958  std::cout << sys_message_head << "Warning! Received SIGTSTP (ctrl-z) signal.\n";
959  continue;
960  }
961 
962  if (cmd.find("\t") != std::string::npos) { // Completing a command.
964  continue;
965  }
966  else if (arg.find("\t") != std::string::npos) { // Completing the argument.
967  if(cmd == "pread" || cmd == "pwrite")
968  poll_term_->TabComplete(arg, chan_params);
969  else if(cmd == "pmread" || cmd == "pmwrite")
970  poll_term_->TabComplete(arg, mod_params);
971  else if(cmd == "toggle")
973  continue;
974  }
975  poll_term_->flush();
976 
977  if(cmd == ""){ continue; }
978 
979  std::vector<std::string> arguments;
980  unsigned int p_args = split_str(arg, arguments);
981 
982  //We clear the error flag when a command is entered.
983  had_error = false;
984  // check for defined commands
985  if(cmd == "quit" || cmd == "exit"){
986  if(do_MCA_run){ std::cout << sys_message_head << "Warning! Cannot quit while MCA program is running\n"; }
987  else if(acq_running){ std::cout << sys_message_head << "Warning! Cannot quit while acquisition running\n"; }
988  else{
989  kill_all = true;
990  while(!run_ctrl_exit){ sleep(1); }
991  break;
992  }
993  }
994  else if(cmd == "kill"){
995  if(acq_running || do_MCA_run){
996  std::cout << sys_message_head << "Sending KILL signal\n";
997  do_stop_acq = true;
998  }
999  kill_all = true;
1000  while(!run_ctrl_exit){ sleep(1); }
1001  break;
1002  }
1003  else if(cmd == "help" || cmd == "h"){ help(); }
1004  else if(cmd == "version" || cmd == "v"){
1005  std::cout << " Poll2 Core v" << POLL2_CORE_VERSION << " (" << POLL2_CORE_DATE << ")\n";
1006  std::cout << " Poll2 Socket v" << POLL2_SOCKET_VERSION << " (" << POLL2_SOCKET_DATE << ")\n";
1007  std::cout << " HRIBF Buffers v" << HRIBF_BUFFERS_VERSION << " (" << HRIBF_BUFFERS_DATE << ")\n";
1008  std::cout << " CTerminal v" << CTERMINAL_VERSION << " (" << CTERMINAL_DATE << ")\n";
1009  }
1010  else if(cmd == "status"){
1011  show_status();
1012  }
1013  else if(cmd == "thresh"){
1014  if(p_args==1){
1015  if(!IsNumeric(arguments.at(0), sys_message_head, "Invalid FIFO threshold specification")) continue;
1016  SetThreshWords(EXTERNAL_FIFO_LENGTH * atof(arguments.at(0).c_str()) / 100.0);
1017  }
1018  show_thresh();
1019  }
1020  else if(cmd == "dump"){ // Dump pixie parameters to file
1021  std::ofstream ofile;
1022 
1023  if(p_args >= 1){
1024  ofile.open(arg.c_str());
1025  if(!ofile.good()){
1026  std::cout << sys_message_head << "Failed to open output file '" << arg << "'\n";
1027  std::cout << sys_message_head << "Check that the path is correct\n";
1028  continue;
1029  }
1030  }
1031  else{
1032  ofile.open("./Fallback.set");
1033  if(!ofile.good()){
1034  std::cout << sys_message_head << "Failed to open output file './Fallback.set'\n";
1035  continue;
1036  }
1037  }
1038 
1039  ParameterChannelDumper chanReader(&ofile);
1040  ParameterModuleDumper modReader(&ofile);
1041 
1042  // Channel dependent settings
1043  for(unsigned int param = 0; param < chan_params.size(); param++){
1044  forChannel<std::string>(pif, -1, -1, chanReader, chan_params[param]);
1045  }
1046 
1047  // Channel independent settings
1048  for(unsigned int param = 0; param < mod_params.size(); param++){
1049  forModule(pif, -1, modReader, mod_params[param]);
1050  }
1051 
1052  if(p_args >= 1){ std::cout << sys_message_head << "Successfully wrote output parameter file '" << arg << "'\n"; }
1053  else{ std::cout << sys_message_head << "Successfully wrote output parameter file './Fallback.set'\n"; }
1054  ofile.close();
1055  }
1056  else if(cmd == "pwrite" || cmd == "pmwrite"){ // Write pixie parameters
1057  if(acq_running || do_MCA_run){
1058  std::cout << sys_message_head << "Warning! Cannot edit pixie parameters while acquisition is running\n\n";
1059  continue;
1060  }
1061 
1062  if(cmd == "pwrite"){ // Syntax "pwrite <module> <channel> <parameter name> <value>"
1063  if(p_args > 0 && arguments.at(0) == "help"){ pchan_help(); }
1064  else if(p_args >= 4){
1065  int modStart, modStop;
1066  if (!SplitParameterArgs(arguments.at(0), modStart, modStop)) {
1067  std::cout << "ERROR: Invalid module argument: '" << arguments.at(0) << "'\n";
1068  continue;
1069  }
1070  int chStart, chStop;
1071  if (!SplitParameterArgs(arguments.at(1), chStart, chStop)) {
1072  std::cout << "ERROR: Invalid channel argument: '" << arguments.at(1) << "'\n";
1073  continue;
1074  }
1075 
1076  //Check that there are no characters in the string unless it is hex.
1077  std::string &valueStr = arguments.at(3);
1078  if (valueStr.find_last_not_of("+-eE0123456789.") != std::string::npos &&
1079  !((valueStr.find("0x") == 0 || valueStr.find("0X") == 0) &&
1080  valueStr.find_first_not_of("0123456789abcdefABCDEF", 2) == std::string::npos) ) {
1081  std::cout << "ERROR: Invalid parameter value: '" << valueStr << "'\n";
1082  continue;
1083  }
1084 
1085  double value;
1086  try { value = std::stod(valueStr); }
1087  catch (const std::invalid_argument &ia) {
1088  std::cout << "ERROR: Invalid parameter value: '" << valueStr << "'\n";
1089  continue;
1090  }
1091 
1092  ParameterChannelWriter writer;
1093  bool error = false;
1094  for (int mod = modStart; mod <= modStop; mod++) {
1095  for (int ch = chStart; ch <= chStop; ch++) {
1096  if(forChannel(pif, mod, ch, writer, make_pair(arguments.at(2), value))){
1097  error = true;
1098  }
1099  }
1100  }
1101  if (!error) pif->SaveDSPParameters();
1102  }
1103  else{
1104  std::cout << sys_message_head << "Invalid number of parameters to pwrite\n";
1105  std::cout << sys_message_head << " -SYNTAX- pwrite <module> <channel> <parameter> <value>\n";
1106  }
1107  }
1108  else if(cmd == "pmwrite"){ // Syntax "pmwrite <module> <parameter name> <value>"
1109  if(p_args > 0 && arguments.at(0) == "help"){ pmod_help(); }
1110  else if(p_args >= 3){
1111  int modStart, modStop;
1112  if (!SplitParameterArgs(arguments.at(0), modStart, modStop)) {
1113  std::cout << "ERROR: Invalid module argument: '" << arguments.at(0) << "'\n";
1114  continue;
1115  }
1116 
1117  //Check that there are no characters in the string unless it is hex.
1118  std::string &valueStr = arguments.at(2);
1119  if (valueStr.find_last_not_of("0123456789") != std::string::npos &&
1120  !((valueStr.find("0x") == 0 || valueStr.find("0X") == 0) &&
1121  valueStr.find_first_not_of("0123456789abcdefABCDEF", 2) == std::string::npos) ) {
1122  std::cout << "ERROR: Invalid parameter value: '" << valueStr << "'\n";
1123  continue;
1124  }
1125 
1126  unsigned int value;
1127  //Use stod to add hex capability. The decimal and negative values are
1128  // caught above and rejected.
1129  try { value = (unsigned int) std::stod(valueStr); }
1130  catch (const std::invalid_argument &ia) {
1131  std::cout << "ERROR: Invalid parameter value: '" << valueStr << "'\n";
1132  continue;
1133  }
1134 
1135  ParameterModuleWriter writer;
1136  bool error = false;
1137  for (int mod = modStart; mod <= modStop; mod++) {
1138  if(!forModule(pif, mod, writer, make_pair(arguments.at(1), value))){
1139  error = true;
1140  }
1141  }
1142  if (!error) pif->SaveDSPParameters();
1143  }
1144  else{
1145  std::cout << sys_message_head << "Invalid number of parameters to pmwrite\n";
1146  std::cout << sys_message_head << " -SYNTAX- pmwrite <module> <parameter> <value>\n";
1147  }
1148  }
1149  }
1150  else if(cmd == "pread" || cmd == "pmread"){ // Read pixie parameters
1151  if(acq_running || do_MCA_run){
1152  std::cout << sys_message_head << "Warning! Cannot view pixie parameters while acquisition is running\n\n";
1153  continue;
1154  }
1155 
1156  if(cmd == "pread"){ // Syntax "pread <module> <channel> <parameter name>"
1157  if(p_args > 0 && arguments.at(0) == "help"){ pchan_help(); }
1158  else if(p_args >= 3){
1159  int modStart, modStop;
1160  if (!SplitParameterArgs(arguments.at(0), modStart, modStop)) {
1161  std::cout << "ERROR: Invalid module argument: '" << arguments.at(0) << "'\n";
1162  continue;
1163  }
1164  int chStart, chStop;
1165  if (!SplitParameterArgs(arguments.at(1), chStart, chStop)) {
1166  std::cout << "ERROR: Invalid channel argument: '" << arguments.at(1) << "'\n";
1167  continue;
1168  }
1169 
1170  ParameterChannelReader reader;
1171  for (int mod = modStart; mod <= modStop; mod++) {
1172  for (int ch = chStart; ch <= chStop; ch++) {
1173  forChannel(pif, mod, ch, reader, arguments.at(2));
1174  }
1175  }
1176  }
1177  else{
1178  std::cout << sys_message_head << "Invalid number of parameters to pread\n";
1179  std::cout << sys_message_head << " -SYNTAX- pread <module> <channel> <parameter>\n";
1180  }
1181  }
1182  else if(cmd == "pmread"){ // Syntax "pmread <module> <parameter name>"
1183  if(p_args > 0 && arguments.at(0) == "help"){ pmod_help(); }
1184  else if(p_args >= 2){
1185  int modStart, modStop;
1186  if (!SplitParameterArgs(arguments.at(0), modStart, modStop)) {
1187  std::cout << "ERROR: Invalid module argument: '" << arguments.at(0) << "'\n";
1188  continue;
1189  }
1190 
1191  ParameterModuleReader reader;
1192  for (int mod = modStart; mod <= modStop; mod++) {
1193  forModule(pif, mod, reader, arguments.at(1));
1194  }
1195  }
1196  else{
1197  std::cout << sys_message_head << "Invalid number of parameters to pmread\n";
1198  std::cout << sys_message_head << " -SYNTAX- pread <module> <parameter>\n";
1199  }
1200  }
1201  }
1202  else if(cmd == "adjust_offsets"){ // Run adjust_offsets
1203  if(acq_running || do_MCA_run){
1204  std::cout << sys_message_head << "Warning! Cannot edit pixie parameters while acquisition is running\n\n";
1205  continue;
1206  }
1207 
1208  if(p_args >= 1){
1209  int modStart, modStop;
1210  if (!SplitParameterArgs(arguments.at(0), modStart, modStop)) {
1211  std::cout << "ERROR: Invalid module argument: '" << arguments.at(0) << "'\n";
1212  continue;
1213  }
1214 
1215  OffsetAdjuster adjuster;
1216  bool error = false;
1217  for (int mod = modStart; mod <= modStop; mod++) {
1218  if(!forModule(pif, mod, adjuster, 0)){ error = true; }
1219  }
1220  if (!error) pif->SaveDSPParameters();
1221  }
1222  else{
1223  std::cout << sys_message_head << "Invalid number of parameters to adjust_offsets\n";
1224  std::cout << sys_message_head << " -SYNTAX- adjust_offsets <module>\n";
1225  }
1226  }
1227  else if(cmd == "find_tau"){ // Run find_tau
1228  if(acq_running || do_MCA_run){
1229  std::cout << sys_message_head << "Warning! Cannot edit pixie parameters while acquisition is running\n\n";
1230  continue;
1231  }
1232 
1233  if(p_args >= 2){
1234  if(!IsNumeric(arguments.at(0), sys_message_head, "Invalid module specification")) continue;
1235  else if(!IsNumeric(arguments.at(1), sys_message_head, "Invalid channel specification")) continue;
1236  int mod = atoi(arguments.at(0).c_str());
1237  int ch = atoi(arguments.at(1).c_str());
1238 
1239  TauFinder finder;
1240  forChannel(pif, mod, ch, finder, 0);
1241  }
1242  else{
1243  std::cout << sys_message_head << "Invalid number of parameters to find_tau\n";
1244  std::cout << sys_message_head << " -SYNTAX- find_tau <module> <channel>\n";
1245  }
1246  }
1247  else if(cmd == "toggle"){ // Toggle a CHANNEL_CSRA bit
1248  if(acq_running || do_MCA_run){
1249  std::cout << sys_message_head << "Warning! Cannot edit pixie parameters while acquisition is running\n\n";
1250  continue;
1251  }
1252 
1253  BitFlipper flipper;
1254 
1255  if(p_args >= 3){
1256  int modStart, modStop;
1257  if (!SplitParameterArgs(arguments.at(0), modStart, modStop)) {
1258  std::cout << "ERROR: Invalid module argument: '" << arguments.at(0) << "'\n";
1259  continue;
1260  }
1261  int chStart, chStop;
1262  if (!SplitParameterArgs(arguments.at(1), chStart, chStop)) {
1263  std::cout << "ERROR: Invalid channel argument: '" << arguments.at(1) << "'\n";
1264  continue;
1265  }
1266  flipper.SetCSRAbit(arguments.at(2));
1267 
1268  std::string dum_str = "CHANNEL_CSRA";
1269  bool error = false;
1270  for (int mod = modStart; mod <= modStop; mod++) {
1271  for (int ch = chStart; ch <= chStop; ch++) {
1272  if(!forChannel(pif, mod, ch, flipper, dum_str)){
1273  error = true;
1274  }
1275  }
1276  }
1277  if (!error) pif->SaveDSPParameters();
1278  }
1279  else{
1280  std::cout << sys_message_head << "Invalid number of parameters to toggle\n";
1281  std::cout << sys_message_head << " -SYNTAX- toggle <module> <channel> <CSRA bit>\n";
1282  flipper.Help();
1283  }
1284  }
1285  else if(cmd == "toggle_bit"){ // Toggle any bit of any parameter under 32 bits long
1286  if(acq_running || do_MCA_run){
1287  std::cout << sys_message_head << "Warning! Cannot edit pixie parameters while acquisition is running\n\n";
1288  continue;
1289  }
1290 
1291  BitFlipper flipper;
1292 
1293  if(p_args >= 4){
1294  if(!IsNumeric(arguments.at(0), sys_message_head, "Invalid module specification")) continue;
1295  else if(!IsNumeric(arguments.at(1), sys_message_head, "Invalid channel specification")) continue;
1296  else if(!IsNumeric(arguments.at(3), sys_message_head, "Invalid bit number specification")) continue;
1297  flipper.SetBit(arguments.at(3));
1298 
1299  if(forChannel(pif, atoi(arguments.at(0).c_str()), atoi(arguments.at(1).c_str()), flipper, arguments.at(2))){
1301  }
1302  }
1303  else{
1304  std::cout << sys_message_head << "Invalid number of parameters to toggle_any\n";
1305  std::cout << sys_message_head << " -SYNTAX- toggle_any <module> <channel> <parameter> <bit>\n";
1306  }
1307  }
1308  else if(cmd == "csr_test"){ // Run CSRAtest method
1309  BitFlipper flipper;
1310  if(p_args >= 1){
1311  //Check that there are no characters in the string unless it is hex.
1312  std::string &valueStr = arguments.at(0);
1313  if (valueStr.find_last_not_of("0123456789") != std::string::npos &&
1314  !((valueStr.find("0x") == 0 || valueStr.find("0X") == 0) &&
1315  valueStr.find_first_not_of("0123456789abcdefABCDEF", 2) == std::string::npos) ) {
1316  std::cout << "ERROR: Invalid parameter value: '" << valueStr << "'\n";
1317  continue;
1318  }
1319  unsigned int value;
1320  //Use stod to add hex capability. The decimal and negative values are
1321  // caught above and rejected.
1322  try { value = (unsigned int) std::stod(valueStr); }
1323  catch (const std::invalid_argument &ia) {
1324  std::cout << "ERROR: Invalid parameter value: '" << valueStr << "'\n";
1325  continue;
1326  }
1327 
1328  flipper.CSRAtest(value);
1329  }
1330  else{
1331  std::cout << sys_message_head << "Invalid number of parameters to csr_test\n";
1332  std::cout << sys_message_head << " -SYNTAX- csr_test <number>\n";
1333  }
1334  }
1335  else if(cmd == "bit_test"){ // Run Test method
1336  BitFlipper flipper;
1337  if(p_args >= 2){
1338  if(!IsNumeric(arguments.at(1), sys_message_head, "Invalid number of bits specified")) continue;
1339  else if(!IsNumeric(arguments.at(2), sys_message_head, "Invalid parameter value specification")) continue;
1340  std::vector<std::string> empty_vector;
1341  flipper.Test((unsigned int)atoi(arguments.at(0).c_str()), std::strtoul(arguments.at(1).c_str(), NULL, 0), empty_vector);
1342  }
1343  else{
1344  std::cout << sys_message_head << "Invalid number of parameters to bit_test\n";
1345  std::cout << sys_message_head << " -SYNTAX- bit_test <num_bits> <number>\n";
1346  }
1347  }
1348  else if(cmd == "get_traces"){ // Run GetTraces method
1349  if(acq_running || do_MCA_run){
1350  std::cout << sys_message_head << "Warning! Cannot view live traces while acquisition is running\n\n";
1351  continue;
1352  }
1353 
1354  if(p_args >= 2){
1355  if(!IsNumeric(arguments.at(0), sys_message_head, "Invalid module specification")) continue;
1356  else if(!IsNumeric(arguments.at(1), sys_message_head, "Invalid channel specification")) continue;
1357  int mod = atoi(arguments.at(0).c_str());
1358  int chan = atoi(arguments.at(1).c_str());
1359 
1360  if(mod < 0 || chan < 0){
1361  std::cout << sys_message_head << "Error! Must select one module and one channel to trigger on!\n";
1362  continue;
1363  }
1364  else if(mod > (int)n_cards){
1365  std::cout << sys_message_head << "Error! Invalid module specification (" << mod << ")!\n";
1366  continue;
1367  }
1368  else if(chan > NUMBER_OF_CHANNELS){
1369  std::cout << sys_message_head << "Error! Invalid channel specification (" << chan << ")!\n";
1370  continue;
1371  }
1372 
1373  int trace_threshold = 0;
1374  if(p_args >= 3){
1375  if(!IsNumeric(arguments.at(2), sys_message_head, "Invalid threshold specified")) continue;
1376  else{
1377  trace_threshold = atoi(arguments.at(2).c_str());
1378  if(trace_threshold < 0){
1379  std::cout << sys_message_head << "Cannot set negative threshold!\n";
1380  trace_threshold = 0;
1381  }
1382  }
1383  }
1384 
1385  get_traces(mod, chan, trace_threshold);
1386  }
1387  else{
1388  std::cout << sys_message_head << "Invalid number of parameters to get_traces\n";
1389  std::cout << sys_message_head << " -SYNTAX- get_traces <mod> <chan> [threshold]\n";
1390  }
1391  }
1392  else if(cmd == "quiet"){ // Toggle quiet mode
1393  if(is_quiet){
1394  std::cout << sys_message_head << "Toggling quiet mode OFF\n";
1395  is_quiet = false;
1396  }
1397  else{
1398  std::cout << sys_message_head << "Toggling quiet mode ON\n";
1399  is_quiet = true;
1400  }
1401  }
1402  else if(cmd == "debug"){ // Toggle debug mode
1403  if(debug_mode){
1404  std::cout << sys_message_head << "Toggling debug mode OFF\n";
1405  output_file.SetDebugMode(false);
1406  debug_mode = false;
1407  }
1408  else{
1409  std::cout << sys_message_head << "Toggling debug mode ON\n";
1411  debug_mode = true;
1412  }
1413  }
1414  else if(!pac_mode){ // These command are only available when not running in pacman mode!
1415  if(cmd == "run"){ // Tell POLL to start acq and start recording data to disk.
1416  start_run();
1417  }
1418  else if(cmd == "timedrun"){
1419  if(!arg.empty()){
1420  double runSeconds = strtod(arg.c_str(), NULL);
1421  if(IsNumeric(arg) && runSeconds > 0.0)
1422  start_run(true, runSeconds);
1423  else
1424  std::cout << sys_message_head << Display::ErrorStr() << " User attempted to run for an invalid length of time (" << arg << ")!\n";
1425  }
1426  else{
1427  std::cout << sys_message_head << "Invalid number of parameters to timedrun\n";
1428  std::cout << sys_message_head << " -SYNTAX- timedrun <seconds>\n";
1429  }
1430  }
1431  else if(cmd == "startacq" || cmd == "startvme"){ // Tell POLL to start data acquisition without recording to disk.
1432  start_run(false);
1433  }
1434  else if(cmd == "stop" || cmd == "stopacq" || cmd == "stopvme"){ // Tell POLL to stop recording data to disk and stop acq.
1435  stop_run();
1436  }
1437  else if(cmd == "shm"){ // Toggle "shared-memory" mode
1438  if(shm_mode){
1439  std::cout << sys_message_head << "Toggling shared-memory mode OFF\n";
1440  shm_mode = false;
1441  }
1442  else{
1443  std::cout << sys_message_head << "Toggling shared-memory mode ON\n";
1444  shm_mode = true;
1445  }
1446  }
1447  else if(cmd == "reboot"){ // Tell POLL to attempt a PIXIE crate reboot
1448  if(do_MCA_run){ std::cout << sys_message_head << "Warning! Cannot reboot while MCA is running\n"; }
1449  else if(acq_running || do_MCA_run){ std::cout << sys_message_head << "Warning! Cannot reboot while acquisition running\n"; }
1450  else{
1451  do_reboot = true;
1453  }
1454  }
1455  else if(cmd == "hup" || cmd == "spill"){ // Force spill
1456  if(do_MCA_run){ std::cout << sys_message_head << "Command not available for MCA run\n"; }
1457  else if(!acq_running){ std::cout << sys_message_head << "Acquisition is not running\n"; }
1458  else{ force_spill = true; }
1459  }
1460  else if(cmd == "fdir"){ // Change the output file directory
1461  if (arg == "") { std::cout << sys_message_head << "Using output directory '" << output_directory << "'\n"; }
1462  else if (file_open) {
1463  std::cout << sys_message_head << Display::WarningStr("Warning:") << " Directory cannot be changed while a file is open!\n";
1464  }
1465  else {
1466  output_directory = arg;
1467  current_file_num = 0;
1468 
1469  // Append a '/' if the user did not include one
1470  if(*(output_directory.end()-1) != '/'){ output_directory += '/'; }
1471 
1472  std::cout << sys_message_head << "Set output directory to '" << output_directory << "'.\n";
1473 
1474  //Check what run files already exist.
1475  unsigned int temp_run_num = next_run_num;
1476  std::string filename = output_file.GetNextFileName(next_run_num,filename_prefix, output_directory);
1477  if (temp_run_num != next_run_num) {
1478  std::cout << sys_message_head << Display::WarningStr("Warning") << ": Run file existed for run " << temp_run_num << "! Next run number will be " << next_run_num << ".\n";
1479  }
1480 
1481  std::cout << sys_message_head << "Next file will be '" << filename << "'.\n";
1482  }
1483  }
1484  else if (cmd == "prefix") {
1485  if (arg == "") {
1486  std::cout << sys_message_head << "Using output filename prefix '" << filename_prefix << "'.\n";
1487  }
1488  else if (file_open) {
1489  std::cout << sys_message_head << Display::WarningStr("Warning:") << " Prefix cannot be changed while a file is open!\n";
1490  }
1491  else {
1492  filename_prefix = arg;
1493  next_run_num = 1;
1494 
1495  //Check what run files already exist.
1497  if (next_run_num != 1) {
1498  std::cout << sys_message_head << Display::WarningStr("Warning") << ": Some run files existed! Next run number will be " << next_run_num << ".\n";
1499  }
1500 
1501  std::cout << sys_message_head << "Set output filename prefix to '" << filename_prefix << "'.\n";
1502  std::cout << sys_message_head << "Next file will be '" << output_file.GetNextFileName(next_run_num,filename_prefix, output_directory) << "'.\n";
1503  }
1504  }
1505  else if(cmd == "title"){ // Change the title of the output file
1506  if (arg == "") { std::cout << sys_message_head << "Using output file title '" << output_title << "'.\n"; }
1507  else if (file_open) {
1508  std::cout << sys_message_head << Display::WarningStr("Warning:") << " Run title cannot be changed while a file is open!\n";
1509  }
1510  else {
1511  //Check if argument is within double quotes and strip them. Otherwise take the whole argument.
1512  if (arg.find_first_of('"') == 0 && arg.find_last_of('"') == arg.length() - 1)
1513  output_title = arg.substr(1,arg.length() - 2);
1514  else output_title = arg;
1515  if(output_format == 0 && output_title.size() > 80){
1516  std::cout << sys_message_head << Display::WarningStr("Warning:") << " Title length " << output_title.size() - 80 << " characters too long for ldf format!\n";
1517  output_title = output_title.substr(0, 80);
1518  }
1519  std::cout << sys_message_head << "Set run title to '" << output_title << "'.\n";
1520  }
1521  }
1522  else if(cmd == "runnum"){ // Change the run number to the specified value
1523  if (arg == "") {
1524  if (output_file.IsOpen())
1525  std::cout << sys_message_head << "Current output file run number '" << output_file.GetRunNumber() << "'.\n";
1527  std::cout << sys_message_head << "Next output file run number '" << next_run_num << "' for prefix '" << filename_prefix << "'.\n";
1528  }
1529  else if (file_open) {
1530  std::cout << sys_message_head << Display::WarningStr("Warning:") << " Run number cannot be changed while a file is open!\n";
1531  }
1532  else {
1533  next_run_num = atoi(arg.c_str());
1535  if (next_run_num != (unsigned int)atoi(arg.c_str())) {
1536  std::cout << sys_message_head << Display::WarningStr("Wanring") << ": Run file existed for run " << atoi(arg.c_str()) << ".\n";
1537  }
1538  std::cout << sys_message_head << "Set run number to '" << next_run_num << "'.\n";
1539  std::cout << sys_message_head << "Next file will be '" << filename << "'.\n";
1540  }
1541  }
1542  else if(cmd == "oform"){ // Change the output file format
1543  if(arg != ""){
1544  int format = atoi(arg.c_str());
1545  if(format == 0 || format == 1 || format == 2){
1546  output_format = atoi(arg.c_str());
1547  std::cout << sys_message_head << "Set output file format to '" << output_format << "'\n";
1548  if(output_format == 1){ std::cout << " Warning! This output format is experimental and is not recommended for data taking\n"; }
1549  else if(output_format == 2){ std::cout << " Warning! This output format is experimental and is not recommended for data taking\n"; }
1550  output_file.SetFileFormat(output_format);
1551  }
1552  else{
1553  std::cout << sys_message_head << "Unknown output file format ID '" << format << "'\n";
1554  std::cout << " Available file formats include:\n";
1555  std::cout << " 0 - .ldf (HRIBF) file format (default)\n";
1556  std::cout << " 1 - .pld (PIXIE) file format (experimental)\n";
1557  std::cout << " 2 - .root file format (slow, not recommended)\n";
1558  }
1559  }
1560  else{ std::cout << sys_message_head << "Using output file format '" << output_format << "'\n"; }
1561  if(output_file.IsOpen()){ std::cout << sys_message_head << "New output format used for new files only! Current file is unchanged.\n"; }
1562  }
1563  else if(cmd == "mca" || cmd == "MCA"){ // Run MCA program using either root or damm
1564  if(do_MCA_run){
1565  std::cout << sys_message_head << "MCA program is already running\n\n";
1566  continue;
1567  }
1568  else if(acq_running){
1569  std::cout << sys_message_head << "Warning! Cannot run MCA program while acquisition is running\n\n";
1570  continue;
1571  }
1572 
1573  if (p_args >= 1) {
1574  std::string type = arguments.at(0);
1575 
1576  if(type == "root"){ mca_args.SetUseRoot(); }
1577  else if(type != "damm"){ mca_args.SetTotalTime(atoi(type.c_str())); }
1578 
1579  if(p_args >= 2){
1580  if(mca_args.GetTotalTime() == 0){ mca_args.SetTotalTime(atoi(arguments.at(1).c_str())); }
1581  else{ mca_args.SetBasename(arguments.at(1)); }
1582  if(p_args >= 3){ mca_args.SetBasename(arguments.at(2)); }
1583  }
1584  }
1585 
1586  if(mca_args.GetTotalTime() == 0){
1587  mca_args.SetTotalTime(10);
1588  std::cout << sys_message_head << "Using default MCA time of 10 seconds\n";
1589  }
1590 
1591  do_MCA_run = true;
1592  }
1593  else{ std::cout << sys_message_head << "Unknown command '" << cmd << "'\n"; }
1594  }
1595  else{ std::cout << sys_message_head << "Unknown command '" << cmd << "'\n"; }
1596  }
1597 }
1598 
1600 // Poll::RunControl
1602 
1604 void Poll::RunControl(){
1605  time_t acqStartTime;
1606  time_t currentTime;
1607  while(true){
1608  if(kill_all){ // Supersedes all other commands
1609  if(acq_running || mca_args.IsRunning()){ do_stop_acq = true; } // Safety catch
1610  else{ break; }
1611  }
1612 
1613  if(do_reboot){ // Attempt to reboot the PIXIE crate
1614  if(acq_running){ do_stop_acq = true; } // Safety catch
1615  else{
1616  std::cout << sys_message_head << "Attempting PIXIE crate reboot\n";
1618  printf("Press Enter key to continue...");
1619  std::cin.get();
1620  do_reboot = false;
1621  }
1622  }
1623 
1624  if(do_MCA_run){ // Do an MCA run, if the acq is not running.
1625  if(acq_running){ do_stop_acq = true; } // Safety catch.
1626  else{
1627  if(!mca_args.IsRunning()){ // Start the pixie histogram run.
1628  if(mca_args.GetTotalTime() > 0.0){ std::cout << sys_message_head << "Performing MCA data run for " << mca_args.GetTotalTime() << " s\n"; }
1629  else{ std::cout << sys_message_head << "Performing infinite MCA data run. Type \"stop\" to quit\n"; }
1630 
1631  if(!mca_args.Initialize(pif)){
1632  std::cout << Display::ErrorStr("Run TERMINATED") << std::endl;
1633  do_MCA_run = false;
1634  had_error = true;
1635  continue;
1636  }
1637  }
1638 
1639  if(!mca_args.CheckTime() || do_stop_acq){ // End the run.
1640  pif->EndRun();
1641  std::cout << sys_message_head << "Ending MCA run.\n";
1642  std::cout << sys_message_head << "Ran for " << mca_args.GetMCA()->GetRunTime() << " s.\n";
1643  mca_args.Close(pif);
1644  do_stop_acq = false;
1645  do_MCA_run = false;
1646  }
1647  else{
1648  sleep(1); // Sleep for a small amount of time.
1649  if(!mca_args.Step()){ // Update the histograms.
1650  std::cout << Display::ErrorStr("Run TERMINATED") << std::endl;
1651  mca_args.Close(pif);
1652  do_MCA_run = false;
1653  had_error = true;
1654  }
1655  }
1656  }
1657  }
1658 
1659  //Start acquistion
1660  if (do_start_acq) {
1661  if (!acq_running) {
1662  if(record_data){
1663  //Close a file if open
1664  if(output_file.IsOpen()){
1665  std::cout << Display::WarningStr() << " Unexpected output file open!\n";
1666  CloseOutputFile();
1667  }
1668 
1669  //Prepare the output file
1670  if (!OpenOutputFile()) {
1671  do_start_acq = false;
1672  acq_running = false;
1673  record_data = false;
1674  had_error = true;
1675  continue;
1676  }
1677  }
1678 
1679  //Start list mode
1680  if(pif->StartListModeRun(LIST_MODE_RUN, NEW_RUN)) {
1681  time(&acqStartTime);
1682  if (record_data) std::cout << "Run " << output_file.GetRunNumber();
1683  else std::cout << "Acq";
1684  std::cout << " started on " << ctime(&acqStartTime);
1685 
1686  acq_running = true;
1687  startTime = usGetTime(0);
1688  lastSpillTime = 0;
1689  }
1690  else{
1691  std::cout << sys_message_head << "Failed to start list mode run. Try rebooting PIXIE\n";
1692  acq_running = false;
1693  had_error = true;
1694  }
1695  do_start_acq = false;
1696  } //if(!acq_running)
1697  else {
1698  std::cout << sys_message_head << "Already running!\n";
1699  do_start_acq = false;
1700  }
1701  }
1702 
1703  if(acq_running){
1704  // Check the run time.
1705  time(&currentTime);
1706 
1707  if(runTime > 0.0 && difftime(currentTime, acqStartTime) >= runTime)
1708  stop_run(); // Handle this cleanly.
1709 
1710  //Handle a stop signal
1711  if(do_stop_acq){
1712  // Read data from the modules.
1713  if (!had_error) ReadFIFO();
1714 
1715  // Instruct all modules to end the current run.
1716  pif->EndRun();
1717 
1718  // Check if each module has ended its run properly.
1719  for(size_t mod = 0; mod < n_cards; mod++){
1720  //If the run status is 1 then the run has not finished in the module.
1721  // We need to read it out.
1722  if(pif->CheckRunStatus(mod) == 1) {
1723  if (!is_quiet) std::cout << "Module " << mod << " still has " << pif->CheckFIFOWords(mod) << " words in the FIFO.\n";
1724  //We set force_spill to true in case the remaining words is small.
1725  force_spill = true;
1726  //We sleep to allow the module to finish.
1727  sleep(1);
1728  //We read the FIFO out.
1729  if (!had_error) ReadFIFO();
1730  }
1731 
1732  //Print the module status.
1733  std::stringstream leader;
1734  leader << "Run end status in module " << mod;
1735  if (!partialEvents[mod].empty()) {
1737  leader << Display::WarningStr(" (partial evt)");
1738  partialEvents[mod].clear();
1739  }
1740 
1741  Display::LeaderPrint(leader.str());
1742  if(!pif->CheckRunStatus(mod)){
1743  std::cout << Display::OkayStr() << std::endl;
1744  }
1745  else {
1746  std::cout << Display::ErrorStr() << std::endl;
1747  had_error = true;
1748  }
1749  }
1750 
1751  if (record_data) std::cout << "Run " << output_file.GetRunNumber();
1752  else std::cout << "Acq";
1753  std::cout << " stopped on " << ctime(&currentTime);
1754 
1756  statsHandler->Dump();
1758 
1759  //Close the output file
1761 
1762  //Reset status flags
1763  do_stop_acq = false;
1764  acq_running = false;
1765  } //if (do_stop_acq) -- End of handling a stop acq flag
1766 
1767  // Read data from the modules.
1768  ReadFIFO();
1769  }
1770 
1771  UpdateStatus();
1772 
1773  //Sleep the run control if idle to reduce CPU utilization.
1774  if (!acq_running && !do_MCA_run) sleep(1);
1775  }
1776 
1777  run_ctrl_exit = true;
1778  std::cout << "Run Control exited\n";
1779 }
1780 void Poll::UpdateStatus() {
1781  //Build status string
1782  std::stringstream status;
1783  if (had_error) status << Display::ErrorStr("[ERROR]");
1784  else if (acq_running && record_data) status << Display::OkayStr("[ACQ]");
1785  else if (acq_running && !record_data) status << Display::WarningStr("[ACQ]");
1786  else if (do_MCA_run) status << Display::OkayStr("[MCA]");
1787  else status << Display::InfoStr("[IDLE]");
1788 
1789  if (file_open) status << " Run " << output_file.GetRunNumber();
1790 
1791  if(do_MCA_run){
1792  status << " " << (int)mca_args.GetMCA()->GetRunTime() << "s";
1793  status << " of " << mca_args.GetTotalTime() << "s";
1794  }
1795  else{
1796  //Add run time to status
1797  status << " " << (long long) statsHandler->GetTotalTime() << "s";
1798  //Add data rate to status
1799  status << " " << humanReadable(statsHandler->GetTotalDataRate()) << "/s";
1800  }
1801 
1802  if (file_open) {
1803  if (acq_running && !record_data) status << TermColors::DkYellow;
1804  //Add file size to status
1805  status << " " << humanReadable(output_file.GetFilesize());
1806  status << " " << output_file.GetCurrentFilename();
1807  if (acq_running && !record_data) status << TermColors::Reset;
1808  }
1809 
1810  //Update the status bar
1811  poll_term_->SetStatus(status.str());
1812 }
1813 
1814 
1815 void Poll::ReadScalers() {
1816  static std::vector< std::pair<double, double> > xiaRates(16, std::make_pair<double, double>(0,0));
1817  static int numChPerMod = pif->GetNumberChannels();
1818 
1819  for (unsigned short mod=0;mod < n_cards; mod++) {
1820  //Tell interface to get stats data from the modules.
1821  pif->GetStatistics(mod);
1822 
1823  for (int ch=0;ch< numChPerMod; ch++)
1824  xiaRates[ch] = std::make_pair<double, double>(pif->GetInputCountRate(mod, ch),pif->GetOutputCountRate(mod,ch));
1825 
1826  //Populate Stats Handler with ICR and OCR.
1827  statsHandler->SetXiaRates(mod, &xiaRates);
1828  }
1829 }
1830 bool Poll::ReadFIFO() {
1831  static word_t *fifoData = new word_t[(EXTERNAL_FIFO_LENGTH + 2) * n_cards];
1832 
1833  if (!acq_running) return false;
1834 
1835  //Number of words in the FIFO of each module.
1836  std::vector<word_t> nWords(n_cards);
1837  //Iterator to determine which card has the most words.
1838  std::vector<word_t>::iterator maxWords;
1839 
1840  //We loop until the FIFO has reached the threshold for any module unless we are stopping and then we skip the loop.
1841  for (unsigned int timeout = 0; timeout < POLL_TRIES; timeout++){
1842  //Check the FIFO size for every module
1843  for (unsigned short mod=0; mod < n_cards; mod++) {
1844  nWords[mod] = pif->CheckFIFOWords(mod);
1845  }
1846  //Find the maximum module
1847  maxWords = std::max_element(nWords.begin(), nWords.end());
1848  if(*maxWords > threshWords){ break; }
1849  }
1850 
1851  //We need to read the data out of the FIFO
1852  if (*maxWords > threshWords || force_spill) {
1853  force_spill = false;
1854  //Number of data words read from the FIFO
1855  size_t dataWords = 0;
1856 
1857  //Loop over each module's FIFO
1858  for (unsigned short mod=0;mod < n_cards; mod++) {
1859 
1860  //if the module has no words in the FIFO we continue to the next module
1861  if (nWords[mod] < MIN_FIFO_READ) {
1862  // write an empty buffer if there is no data
1863  fifoData[dataWords++] = 2;
1864  fifoData[dataWords++] = mod;
1865  continue;
1866  }
1867  else if (nWords[mod] < 0) {
1868  std::cout << Display::WarningStr("Number of FIFO words less than 0") << " in module " << mod << std::endl;
1869  // write an empty buffer if there is no data
1870  fifoData[dataWords++] = 2;
1871  fifoData[dataWords++] = mod;
1872  continue;
1873  }
1874 
1875  //Check if the FIFO is overfilled
1876  bool fullFIFO = (nWords[mod] >= EXTERNAL_FIFO_LENGTH);
1877  if (fullFIFO) {
1878  std::cout << Display::ErrorStr() << " Full FIFO in module " << mod
1879  << " size: " << nWords[mod] << "/"
1880  << EXTERNAL_FIFO_LENGTH << Display::ErrorStr(" ABORTING!") << std::endl;
1881  had_error = true;
1882  do_stop_acq = true;
1883  return false;
1884  }
1885 
1886  //We inject two words describing the size of the FIFO spill and the module.
1887  //We inject the size after it has been computedos we skip it for now and only add the module number.
1888  dataWords++;
1889  fifoData[dataWords++] = mod;
1890 
1891  //We store the partial event if we had one
1892  for (size_t i=0;i<partialEvents[mod].size();i++)
1893  fifoData[dataWords + i] = partialEvents[mod].at(i);
1894 
1895  //Try to read FIFO and catch errors.
1896  if(!pif->ReadFIFOWords(&fifoData[dataWords + partialEvents[mod].size()], nWords[mod], mod, debug_mode)){
1897  std::cout << Display::ErrorStr() << " Unable to read " << nWords[mod] << " from module " << mod << "\n";
1898  had_error = true;
1899  do_stop_acq = true;
1900  return false;
1901  }
1902 
1903  //Print a message about what we did
1904  if(!is_quiet || debug_mode) {
1905  std::cout << "Read " << nWords[mod] << " words from module " << mod;
1906  if (!partialEvents[mod].empty())
1907  std::cout << " and stored " << partialEvents[mod].size() << " partial event words";
1908  std::cout << " to buffer position " << dataWords << std::endl;
1909  }
1910 
1911  //After reading the FIFO and printing a status message we can update the number of words to include the partial event.
1912  nWords[mod] += partialEvents[mod].size();
1913  //Clear the partial event
1914  partialEvents[mod].clear();
1915 
1916  //We now need to parse the event to determine if there is a hanging event. Also, allows a check for corrupted data.
1917  size_t parseWords = dataWords;
1918  //We declare the eventSize outside the loop in case there is a partial event.
1919  word_t eventSize = 0, prevEventSize = 0;
1920  word_t slotExpected = pif->GetSlotNumber(mod);
1921  while (parseWords < dataWords + nWords[mod]) {
1922  //Check first word to see if data makes sense.
1923  // We check the slot, channel and event size.
1924  word_t slotRead = ((fifoData[parseWords] & 0xF0) >> 4);
1925  word_t chanRead = (fifoData[parseWords] & 0xF);
1926  eventSize = ((fifoData[parseWords] & 0x7FFE2000) >> 17);
1927  bool virtualChannel = ((fifoData[parseWords] & 0x20000000) != 0);
1928 
1929  if( slotRead != slotExpected ){
1930  std::cout << Display::ErrorStr() << " Slot read " << slotRead
1931  << " not the same as slot expected "
1932  << slotExpected << std::endl;
1933  had_error = true;
1934  }
1935  if (chanRead < 0 || chanRead > 15) {
1936  std::cout << Display::ErrorStr() << " Channel read (" << chanRead << ") not valid!\n";
1937  had_error = true;
1938  }
1939  if(eventSize == 0){
1940  std::cout << Display::ErrorStr() << " ZERO EVENT SIZE in mod " << mod << "!\n";
1941  had_error = true;
1942  }
1943  if (had_error) break;
1944 
1945  // Update the statsHandler with the event (for monitor.bash)
1946  if(!virtualChannel && statsHandler){
1947  statsHandler->AddEvent(mod, chanRead, sizeof(word_t) * eventSize);
1948  }
1949 
1950  //Iterate to the next event and continue parsing
1951  parseWords += eventSize;
1952  prevEventSize = eventSize;
1953  }
1954 
1955  //We now check the outcome of the data parsing.
1956  //If we have too many words as an event was not completely pulled form the FIFO
1957  if (parseWords > dataWords + nWords[mod]) {
1958  word_t missingWords = parseWords - dataWords - nWords[mod];
1959  word_t partialSize = eventSize - missingWords;
1960  if (debug_mode) std::cout << "Partial event " << partialSize << "/" << eventSize << " words!\n";
1961 
1962  //We could get the words now from the FIFO, but me may have to wait. Instead we store the partial event for the next FIFO read.
1963  for(unsigned short i=0;i< partialSize;i++)
1964  partialEvents[mod].push_back(fifoData[parseWords - eventSize + i]);
1965 
1966  //Update the number of words to indicate removal or partial event.
1967  nWords[mod] -= partialSize;
1968  }
1969  //If parseWords is small then the parse failed for some reason
1970  else if (parseWords < dataWords + nWords[mod]) {
1971  //Determine the fifo position from successfully parsed words plus the last event length.
1972  std::cout << Display::ErrorStr() << " Parsing indicated corrupted data for module " << mod << ".\n";
1973  std::cout << "| Parsing failed at " << parseWords - dataWords << "/" << nWords[mod]
1974  << " (" << parseWords << "/" << dataWords + nWords[mod] << ") words into FIFO." << std::endl;
1975 
1976  //Print the previous event
1977  std::cout << "|\n| Event prior to parsing error (" << prevEventSize << " words):";
1978  std::cout << std::hex << std::setfill('1');
1979  for(size_t i=0;i< prevEventSize;i++) {
1980  if (i%5 == 0) std::cout << std::endl << "| ";
1981  std::cout << "0x" << std::right << std::setw(8) << std::setfill('0');
1982  std::cout << fifoData[parseWords - prevEventSize + i] << " ";
1983  }
1984  std::cout << std::dec << std::setfill(' ') << std::endl;
1985 
1986  //Print the parsed event
1987  std::cout << "|\n| Event at parsing error (" << eventSize << " words):";
1988  size_t outputSize = eventSize;
1989  if (eventSize > 50) {
1990  outputSize = 50;
1991  std::cout << "\n| (Truncated at " << outputSize << " words.)";
1992  }
1993  std::cout << std::hex << std::setfill('0');
1994  for(size_t i=0;i< outputSize;i++) {
1995  if (i%5 == 0) std::cout << std::endl << "| ";
1996  std::cout << "0x" << std::right << std::setw(8) << std::setfill('0');
1997  std::cout << fifoData[parseWords + i] << " ";
1998  }
1999  std::cout << std::dec << std::setfill(' ') << std::endl;
2000 
2001  //Print the following event
2002  //Determine size of following event.
2003  word_t nextEventSize = 0;
2004  if (parseWords + eventSize < dataWords + nWords[mod]) {
2005  nextEventSize = ((fifoData[parseWords + eventSize] & 0x7FFE2000) >> 17);
2006  }
2007  std::cout << "|\n| Event after parsing error (" << nextEventSize << " words):";
2008 
2009  //Determine output size for event.
2010  outputSize = nextEventSize;
2011  if (eventSize > 50) outputSize = 50;
2012  if (parseWords + eventSize + outputSize >= dataWords + nWords[mod])
2013  outputSize = dataWords + nWords[mod] - (parseWords + eventSize);
2014  if (outputSize != nextEventSize)
2015  std::cout << "\n| (Truncated at " << outputSize << " words.)";
2016 
2017  std::cout << std::hex << std::setfill('0');
2018  for(size_t i=0;i< outputSize;i++) {
2019  if (i%5 == 0) std::cout << std::endl << "| ";
2020  std::cout << "0x" << std::right << std::setw(8);
2021  std::cout << fifoData[parseWords + eventSize + i] << " ";
2022  }
2023  std::cout << std::dec << std::setfill(' ') << std::endl << "|\n";
2024 
2025  do_stop_acq = true;
2026  had_error = true;
2027  return false;
2028  }
2029 
2030  //Assign the first injected word of spill to final spill length
2031  fifoData[dataWords - 2] = nWords[mod] + 2;
2032  //The data should be good so we iterate the position in the storage array.
2033  dataWords += nWords[mod];
2034  } //End loop over modules for reading FIFO
2035 
2036  //Get the length of the spill
2037  double spillTime = usGetTime(startTime);
2038  double durSpill = spillTime - lastSpillTime;
2039  lastSpillTime = spillTime;
2040 
2041  // Add time to the statsHandler and check if interval has been exceeded.
2042  //If exceed interval we read the scalers from the modules and dump the stats.
2043  if (statsHandler->AddTime(durSpill * 1e-6)) {
2044  ReadScalers();
2045  statsHandler->Dump();
2047  }
2048 
2049  if (!is_quiet || debug_mode) std::cout << "Writing/Broadcasting " << dataWords << " words.\n";
2050  //We have read the FIFO now we write the data
2051  if (record_data && !pac_mode) write_data(fifoData, dataWords);
2052  broadcast_data(fifoData, dataWords);
2053 
2054  } //If we had exceeded the threshold or forced a flush
2055 
2056  return true;
2057 }
2058 
2060 // Support Functions
2062 
2063 std::string humanReadable(double size) {
2064  int power = std::log10(size);
2065  std::stringstream output;
2066  output << std::setprecision(3);
2067  if (power >= 9) output << size/pow(1024,3) << "GB";
2068  else if (power >= 6) output << size/pow(1024,2) << "MB";
2069  else if (power >= 3) output << size/1024 << "kB";
2070  else output << " " << size << "B";
2071  return output.str();
2072 }
2073 
2074 /* Pad a string with '.' to a specified length. */
2075 std::string pad_string(const std::string &input_, unsigned int length_){
2076  std::string output = input_;
2077  for(unsigned int i = input_.size(); i <= length_; i++){
2078  output += '.';
2079  }
2080  return output;
2081 }
2082 
2083 std::string yesno(bool value_){
2084  if(value_){ return "Yes"; }
2085  return "No";
2086 }
2087 
#define POLL2_SOCKET_DATE
Definition: poll2_socket.h:21
bool GetStatistics(unsigned short mod)
void TabComplete(const std::string &input_, const std::vector< std::string > &possibilities_)
Handle tab complete functionality.
Definition: CTerminal.cpp:740
void Close()
Close the socket.
std::string WarningStr(const std::string &str="[WARNING]")
Definition: Display.cpp:73
std::vector< word_t > * partialEvents
A vector to store the partial events.
Definition: poll2_core.h:107
#define PKT_HEAD_LEN
Definition: poll2_core.cpp:56
double runTime
Definition: poll2_core.h:148
#define POLL_TRIES
Definition: poll2_core.cpp:50
std::string output_directory
Time to run the acquisition, in seconds.
Definition: poll2_core.h:151
bool file_open
Definition: poll2_core.h:130
Server * server
UDP client for network access.
Definition: poll2_core.h:115
bool Init(bool offlineMode=false)
bool Initialize(PixieInterface *pif_)
Definition: poll2_core.cpp:114
static const std::vector< std::string > pollStatusCommands_
Definition: poll2_core.h:176
std::string InfoStr(const std::string &str="[INFO]")
Definition: Display.cpp:55
bool record_data
Set to true when the command is given to stop a run.
Definition: poll2_core.h:124
bool RemovePresetRunLength(int mod)
double startTime
Definition: poll2_core.h:109
std::string sys_message_head
The main pixie interface pointer.
Definition: poll2_core.h:120
void CommandControl()
Main control loop for handling user input.
bool GetSlots(const char *slotF=NULL)
int DataSize
Sequence number for reliable transport.
Definition: poll2_core.h:89
bool do_reboot
Set to true if data is to be recorded to disk.
Definition: poll2_core.h:125
std::vector< std::string > mod_params
Definition: poll2_core.cpp:81
static size_t GetTraceLength(void)
#define HRIBF_BUFFERS_VERSION
Definition: hribf_buffers.h:28
#define MAX_FILE_SIZE
Definition: poll2_core.cpp:53
static const char Reset[]
Definition: TermColors.h:23
#define HRIBF_BUFFERS_DATE
Definition: hribf_buffers.h:29
void show_status()
Display run status information.
Definition: poll2_core.cpp:743
unsigned int split_str(std::string str, std::vector< std::string > &args, char delimiter=' ')
Split a string about some delimiter.
Definition: CTerminal.cpp:1120
StatsHandler * statsHandler
Definition: poll2_core.h:171
void Close()
Close the socket.
std::vector< std::string > commands_
Definition: poll2_core.h:177
PixieInterface * pif
UDP server to listen for pacman commands.
Definition: poll2_core.h:117
int totalTime
Definition: poll2_core.h:42
double lastSpillTime
Time when the acquistion was started.
Definition: poll2_core.h:110
bool insert_wall_clock
Definition: poll2_core.h:139
bool do_start_acq
Set to true when the program is exiting.
Definition: poll2_core.h:122
static size_t GetNumberChannels(void)
Controls the poll2 command interpreter and data acquisition system.
void LeaderPrint(const std::string &str)
Definition: Display.cpp:28
Provides network connectivity for poll2.
int write_data(word_t *data, unsigned int nWords)
Write a data spill to disk.
Definition: poll2_core.cpp:457
void ClearTotals()
bool useRoot
Definition: poll2_core.h:41
void SetThreshWords(const size_t &thresh_)
Definition: poll2_core.h:276
void pause(bool &flag)
Disrupt ncurses while boolean is true.
Definition: CTerminal.cpp:246
int RecvMessage(char *message_, size_t length_)
double GetInputCountRate(int mod, int chan)
double GetTotalDataRate()
bool kill_all
Command line message header.
Definition: poll2_core.h:121
int SendMessage(char *message_, size_t length_)
bool do_stop_acq
Set to true when the command is given to start a run.
Definition: poll2_core.h:123
bool WriteSglModPar(const char *name, word_t val, int mod)
float GetBaseline(size_t chan_)
Definition: PixieSupport.h:158
bool GetStatus()
Definition: PixieSupport.h:162
static const int statsInterval_
The amount time between scaler reads in seconds.
Definition: poll2_core.h:172
MCA * GetMCA()
Definition: poll2_core.h:62
#define POLL2_CORE_DATE
Definition: poll2_core.h:28
unsigned long CheckFIFOWords(unsigned short mod)
bool Test(unsigned int num_bits_, unsigned int input_, const std::vector< std::string > &text_)
void flush()
Dump all text in the stream to the output screen.
Definition: CTerminal.cpp:690
bool start_run(const bool &record_=true, const double &time_=-1.0)
Start a data recording run.
Definition: poll2_core.cpp:692
bool Select(int &retval)
bool ReadFIFOWords(word_t *buf, unsigned long nWords, unsigned short mod, bool verbose=false)
void SetUseRoot(bool state_=true)
Definition: poll2_core.h:64
std::string basename
Definition: poll2_core.h:43
#define MAX_PKT_DATA
Definition: poll2_core.cpp:59
int Write(char *data_, unsigned int nWords_)
Write nWords_ of data to the file.
void ClearRates()
bool ReadFIFO()
Routine to read Pixie FIFOs.
unsigned int total_spill_chunks
Total number of poll data spill chunks sent over the network.
Definition: poll2_core.h:163
Abstract MCA class.
Definition: MCA.h:11
void get_traces(int mod_, int chan_, int thresh_=0)
Acquire raw traces from a pixie module.
Definition: poll2_core.cpp:776
void help()
Data packet for class shared-memory broadcast.
Definition: poll2_core.cpp:628
static const std::vector< std::string > toggle_names
Definition: PixieSupport.h:108
static const std::vector< std::string > runControlCommands_
Definition: poll2_core.h:174
void SetDumpInterval(double interval)
Set the amount of time between scalers dumps in seconds.
Definition: poll2_stats.h:21
bool Boot(int mode=0x7f, bool useWorkingSetFile=false)
void SetXiaRates(int mod, std::vector< std::pair< double, double >> *xiaRates)
Set the ICR and OCR from the XIA module.
#define CTERMINAL_DATE
Definition: CTerminal.h:29
bool acq_running
Force poll2 to dump the current data spill.
Definition: poll2_core.h:127
void SetTotalTime(int totalTime_)
Definition: poll2_core.h:66
bool do_MCA_run
Definition: poll2_core.h:134
#define CTERMINAL_VERSION
Definition: CTerminal.h:28
void show_thresh()
Display polling threshold.
Definition: poll2_core.cpp:770
Library to handle all aspects of a stand-alone command line interface.
bool IsNumeric(const std::string &input_, const std::string &prefix_, const std::string &msg_)
Definition: poll2_core.cpp:67
#define POLL2_CORE_VERSION
Definition: poll2_core.h:27
bool shm_mode
Definition: poll2_core.h:145
unsigned int next_run_num
Set with &#39;htit&#39; command.
Definition: poll2_core.h:154
unsigned int udp_sequence
Pacman related variables.
Definition: poll2_core.h:162
void SetCSRAbit(std::string bit_)
std::string pad_string(const std::string &input_, unsigned int length_)
Pad a string with periods until it is the specified length_.
#define MIN_FIFO_READ
bool Init(const char *address_, int port_)
unsigned int GetRunNumber()
MCA * mca
Definition: poll2_core.h:45
bool GetModuleInfo(const unsigned short &mod, unsigned short *rev, unsigned int *serNum, unsigned short *adcBits, unsigned short *adcMsps)
bool debug_mode
Definition: poll2_core.h:144
std::string GetNextFileName(unsigned int &run_num_, std::string prefix, std::string output_dir, bool continueRun=false)
Return the filename of the next output file.
static const std::vector< std::string > paramControlCommands_
Definition: poll2_core.h:175
size_t threshWords
Definition: poll2_core.h:166
Client * client
Definition: poll2_core.h:114
void CSRAtest(unsigned int input_)
void PrintModuleInfo()
Prints the information about each module.
Definition: poll2_core.cpp:231
void Zero()
Definition: poll2_core.cpp:151
bool Close()
Close the sockets, any open files, and clean up.
Definition: poll2_core.cpp:311
int GetTotalTime()
Definition: poll2_core.h:58
bool init
Pacman shared-memory mode.
Definition: poll2_core.h:147
size_t n_cards
Definition: poll2_core.h:165
bool had_error
Set to true when run_command exits.
Definition: poll2_core.h:129
void broadcast_data(word_t *data, unsigned int nWords)
Broadcast a data spill onto the network.
Definition: poll2_core.cpp:482
int BufLen
The data to be transmitted.
Definition: poll2_core.h:94
std::vector< std::string > chan_params
Definition: poll2_core.cpp:77
bool CheckRunStatus(void)
void broadcast_pac_data()
Broadcast a data spill onto the network in the classic pacman format.
Definition: poll2_core.cpp:570
int Sequence
Definition: poll2_core.h:88
MCA_args mca_args
Set to true when the "mca" command is received.
Definition: poll2_core.h:135
bool CheckTime()
Definition: poll2_core.cpp:146
bool show_module_rates
Definition: poll2_core.h:142
bool stop_run()
Stop an active data recording run.
Definition: poll2_core.cpp:721
unsigned char Data[MAX_ORPH_DATA]
Number of useable bytes in Data.
Definition: poll2_core.h:84
Poll()
Default constructor.
Definition: poll2_core.cpp:168
void ReadScalers()
Routine to read Pixie scalers.
void pmod_help()
Print help dialogue for reading/writing pixie module parameters.
Definition: poll2_core.cpp:677
virtual bool Step()
Update the MCA histograms.
Definition: MCA.cpp:81
bool SaveDSPParameters(const char *fn=NULL)
dictionary channel
bool running
Definition: poll2_core.h:40
void SetBit(unsigned int bit_)
Definition: PixieSupport.h:123
bool force_spill
Set to true when the user tells POLL to reboot PIXIE.
Definition: poll2_core.h:126
PixieInterface::word_t word_t
Definition: poll2_core.h:33
virtual bool IsOpen()
Check if the histogram construction was successful.
Definition: MCA.h:40
~Poll()
Destructor.
Definition: poll2_core.cpp:223
void pchan_help()
Print help dialogue for reading/writing pixie channel parameters.
Definition: poll2_core.cpp:669
bool pac_mode
New style shared-memory mode.
Definition: poll2_core.h:146
int GetAttempts()
Definition: PixieSupport.h:156
PollOutputFile output_file
Definition: poll2_core.h:159
std::string output_title
Set with &#39;ouf&#39; command.
Definition: poll2_core.h:153
int SendMessage(char *message_, size_t length_)
std::string GetCurrentFilename()
Get the name of the current output file.
bool run_ctrl_exit
Set to true when run_command is recieving data from PIXIE.
Definition: poll2_core.h:128
float GetMaximum(size_t chan_)
Definition: PixieSupport.h:160
short GetSlotNumber(int mod) const
bool zero_clocks
Definition: poll2_core.h:143
void SetStatus(std::string status, unsigned short line=0)
Set the status message.
Definition: CTerminal.cpp:323
void SetDebugMode(bool debug_=true)
Toggle debug mode.
bool Step()
Definition: poll2_core.cpp:141
void CloseFile(float total_run_time_=0.0)
Write the footer and close the file.
bool CloseOutputFile(const bool continueRun=false)
Close the current output file, if one is open.
Definition: poll2_core.cpp:345
int SendPacket(Client *cli_)
std::string ErrorStr(const std::string &str="[ERROR]")
Definition: Display.cpp:46
void Clear()
Clear the stats.
bool SplitParameterArgs(const std::string &arg, int &start, int &stop)
Splits the arguments to pread and pwrite on a colon delimeter.
bool OpenOutputFile(bool continueRun=false)
Opens a new file if no file is currently open.
Definition: poll2_core.cpp:391
void UpdateStatus()
Routine to update the status message.
bool Init(int port_, int sec_=10, int usec_=0)
Initialize the serv object and open a specified port. Returns false if the socket fails to open or th...
unsigned char Data[4 *(4050+4)]
Continuation flag for large events.
Definition: poll2_core.h:93
void SetBasename(std::string basename_)
Definition: poll2_core.h:68
Terminal * poll_term_
Definition: poll2_core.h:105
bool SetFileFormat(unsigned int format_)
Set the output file format.
#define EXTERNAL_FIFO_LENGTH
int TotalEvents
Number of useable bytes in Data.
Definition: poll2_core.h:90
std::string OkayStr(const std::string &str="[OK]")
Definition: Display.cpp:64
std::string yesno(bool value_)
Return a string containing "yes" for value_==true and "no" for value_==false.
bool IsOpen()
Return true if an output file is open and writable and false otherwise.
unsigned int output_format
Set with &#39;hnum&#39; command.
Definition: poll2_core.h:155
bool OpenNewFile(std::string title_, unsigned int &run_num_, std::string prefix, std::string output_dir="./", bool continueRun=false)
Close the current file, if one is open, and open a new file for data output.
bool send_alarm
Definition: poll2_core.h:141
#define POLL2_SOCKET_VERSION
Definition: poll2_socket.h:20
bool StartHistogramRun(unsigned short mode=NEW_RUN)
bool StartListModeRun(unsigned short listMode=LIST_MODE_RUN, unsigned short runMode=NEW_RUN)
void Close(PixieInterface *pif_)
Definition: poll2_core.cpp:163
double GetRunTime()
Return the length of time the MCA has been running.
Definition: MCA.cpp:17
void RunControl()
Main acquisition control loop for handling data acq.
std::string filename_prefix
Set with &#39;fdir&#39; command.
Definition: poll2_core.h:152
void AddEvent(unsigned int mod, unsigned int ch, size_t size, int delta_=1)
Definition: poll2_stats.cpp:78
bool forChannel(PixieInterface *pif, int mod, int ch, PixieFunction< T > &f, T par)
Definition: PixieSupport.h:31
data_pack AcqBuf
Definition: poll2_core.h:179
bool IsRunning()
Definition: poll2_core.h:54
double GetOutputCountRate(int mod, int chan)
unsigned short Events
Total number of events.
Definition: poll2_core.h:91
std::string humanReadable(double size)
Convert a rate number to more useful form.
bool Initialize()
Initialize the poll object.
Definition: poll2_core.cpp:246
double usGetTime(double par)
Definition: Utility.cpp:5
static const char DkYellow[]
Definition: TermColors.h:7
int current_file_num
Set with &#39;oform&#39; command.
Definition: poll2_core.h:158
unsigned short Cont
Number of events in this packet.
Definition: poll2_core.h:92
bool AddTime(double dtime)
Definition: poll2_stats.cpp:96
std::string GetCommand(std::string &args, const int &prev_cmd_return_=0)
Wait for the user to input a command.
Definition: CTerminal.cpp:822
bool synch_mods()
Set IN_SYNCH and SYNCH_WAIT parameters on all modules.
Definition: poll2_core.cpp:433
bool boot_fast
Structure to hold arguments for MCA program.
Definition: poll2_core.h:138
std::streampos GetFilesize()
Get the size of the current file, in bytes.
bool forModule(PixieInterface *pif, int mod, PixieFunction< T > &f, T par)
Definition: PixieSupport.h:67
unsigned short GetNumberCards(void) const
double GetTotalTime()
Return the total run time.
bool is_quiet
Definition: poll2_core.h:140