FACT++  1.0
fadctrl.cc
Go to the documentation of this file.
1 #include <functional>
2 
3 #include "Dim.h"
4 #include "Event.h"
5 #include "Shell.h"
6 #include "StateMachineDim.h"
7 #include "StateMachineAsio.h"
8 #include "Connection.h"
9 #include "LocalControl.h"
10 #include "Configuration.h"
11 #include "Console.h"
12 #include "Converter.h"
13 #include "HeadersFAD.h"
14 
15 #include "tools.h"
16 
17 #include "DimDescriptionService.h"
18 #include "EventBuilderWrapper.h"
19 
20 #include "../externals/zofits.h"
21 
22 namespace ba = boost::asio;
23 namespace bs = boost::system;
24 
25 using ba::ip::tcp;
26 
27 using namespace std;
28 
29 // ------------------------------------------------------------------------
30 
31 class ConnectionFAD : public Connection
32 {
33  uint16_t fSlot;
34 // tcp::endpoint fEndpoint;
35 
36  vector<uint16_t> fBuffer;
37 
38 protected:
39  FAD::EventHeader fEventHeader;
40  FAD::ChannelHeader fChannelHeader[FAD::kNumChannels];
41 
42 private:
43  bool fIsVerbose;
47 
48  uint64_t fCounter;
49 
50  FAD::EventHeader fBufEventHeader;
51  vector<uint16_t> fTargetRoi;
52 
53 protected:
55  {
56  Out() << endl << kBold << "Header received (N=" << dec << fCounter << "):" << endl;
57  Out() << fEventHeader;
58  if (fIsHexOutput)
59  Out() << Converter::GetHex<uint16_t>(fEventHeader, 16) << endl;
60  }
61 
63  {
64  Out() << dec << endl;
65 
66  for (unsigned int c=0; c<FAD::kNumChips; c++)
67  {
68  Out() << "ROI|" << fEventHeader.Crate() << ":" << fEventHeader.Board() << ":" << c << ":";
69  for (unsigned int ch=0; ch<FAD::kNumChannelsPerChip; ch++)
70  Out() << " " << setw(4) << fChannelHeader[c+ch*FAD::kNumChips].fRegionOfInterest;
71  Out() << endl;
72  }
73 
74  Out() << "CEL|" << fEventHeader.Crate() << ":" <<fEventHeader.Board() << ": ";
75  for (unsigned int c=0; c<FAD::kNumChips; c++)
76  {
77  if (0)//fIsFullChannelHeader)
78  {
79  for (unsigned int ch=0; ch<FAD::kNumChannelsPerChip; ch++)
80  Out() << " " << setw(4) << fChannelHeader[c+ch*FAD::kNumChips].fStartCell;
81  Out() << endl;
82  }
83  else
84  {
85  Out() << " ";
86  const uint16_t cel = fChannelHeader[c*FAD::kNumChannelsPerChip].fStartCell;
87  for (unsigned int ch=1; ch<FAD::kNumChannelsPerChip; ch++)
88  if (cel!=fChannelHeader[c+ch*FAD::kNumChips].fStartCell)
89  {
90  Out() << "!";
91  break;
92  }
93  Out() << cel;
94  }
95  }
96  Out() << endl;
97 
98  if (fIsHexOutput)
99  Out() << Converter::GetHex<uint16_t>(fChannelHeader, 16) << endl;
100 
101  }
102 
103  virtual void UpdateFirstHeader()
104  {
105  }
106 
107  virtual void UpdateEventHeader()
108  {
109  // emit service with trigger counter from header
110  if (fIsVerbose)
111  PrintEventHeader();
112  }
113 
114  virtual void UpdateChannelHeaders()
115  {
116  // emit service with trigger counter from header
117  if (fIsVerbose)
118  PrintChannelHeaders();
119 
120  }
121 
122  virtual void UpdateData(const uint16_t *data, size_t sz)
123  {
124  // emit service with trigger counter from header
125  if (fIsVerbose && fIsDataOutput)
126  Out() << Converter::GetHex<uint16_t>(data, sz, 16, true) << endl;
127  }
128 
129 private:
130  enum
131  {
132  kReadHeader = 1,
133  kReadData = 2,
134  };
135 
136  void HandleReceivedData(const bs::error_code& err, size_t bytes_received, int type)
137  {
138  // Do not schedule a new read if the connection failed.
139  if (bytes_received==0 || err)
140  {
141  if (err==ba::error::eof)
142  Warn("Connection to "+URL()+" closed by remote host (FAD).");
143 
144  // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
145  // 125: Operation canceled
146  if (err && err!=ba::error::eof && // Connection closed by remote host
147  err!=ba::error::basic_errors::not_connected && // Connection closed by remote host
148  err!=ba::error::basic_errors::operation_aborted) // Connection closed by us
149  {
150  ostringstream str;
151  str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
152  Error(str);
153  }
154  //PostClose(err!=ba::error::basic_errors::operation_aborted);
155  PostClose(false);
156  return;
157  }
158 
159  if (type==kReadHeader)
160  {
161  if (bytes_received!=sizeof(FAD::EventHeader))
162  {
163  ostringstream str;
164  str << "Bytes received (" << bytes_received << " don't match header size " << sizeof(FAD::EventHeader);
165  Error(str);
166  PostClose(false);
167  return;
168  }
169 
170  fEventHeader = fBuffer;
171 
172  if (fEventHeader.fStartDelimiter!=FAD::kDelimiterStart)
173  {
174  ostringstream str;
175  str << "Invalid header received: start delimiter wrong, received ";
176  str << hex << fEventHeader.fStartDelimiter << ", expected " << FAD::kDelimiterStart << ".";
177  Error(str);
178  PostClose(false);
179  return;
180  }
181 
182  if (fCounter==0)
183  UpdateFirstHeader();
184 
185  UpdateEventHeader();
186 
187  EventBuilderWrapper::This->debugHead(fEventHeader);
188 
189  fBuffer.resize(fEventHeader.fPackageLength-sizeof(FAD::EventHeader)/2);
190  AsyncRead(ba::buffer(fBuffer), kReadData);
191  AsyncWait(fInTimeout, 2000, &Connection::HandleReadTimeout);
192 
193  return;
194  }
195 
196  fInTimeout.cancel();
197 
198  if (ntohs(fBuffer.back())!=FAD::kDelimiterEnd)
199  {
200  ostringstream str;
201  str << "Invalid data received: end delimiter wrong, received ";
202  str << hex << ntohs(fBuffer.back()) << ", expected " << FAD::kDelimiterEnd << ".";
203  Error(str);
204  PostClose(false);
205  return;
206  }
207 
208  uint8_t *ptr = reinterpret_cast<uint8_t*>(fBuffer.data());
209  uint8_t *end = ptr + fBuffer.size()*2;
210  for (unsigned int i=0; i<FAD::kNumChannels; i++)
211  {
212  if (ptr+sizeof(FAD::ChannelHeader) > end)
213  {
214  Error("Channel header exceeds buffer size.");
215  PostClose(false);
216  return;
217  }
218 
219  fChannelHeader[i] = vector<uint16_t>((uint16_t*)ptr, (uint16_t*)ptr+sizeof(FAD::ChannelHeader)/2);
220  ptr += sizeof(FAD::ChannelHeader);
221 
222  //UpdateChannelHeader(i);
223 
224  if (ptr+fChannelHeader[i].fRegionOfInterest*2 > end)
225  {
226  Error("Data block exceeds buffer size.");
227  PostClose(false);
228  return;
229  }
230 
231  const uint16_t *data = reinterpret_cast<uint16_t*>(ptr);
232  UpdateData(data, fChannelHeader[i].fRegionOfInterest*2);
233  ptr += fChannelHeader[i].fRegionOfInterest*2;
234  }
235 
236  if (fIsVerbose)
237  UpdateChannelHeaders();
238 
239  fCounter++;
240 
241  fBuffer.resize(sizeof(FAD::EventHeader)/2);
242  AsyncRead(ba::buffer(fBuffer), kReadHeader);
243  }
244 
245  void HandleReadTimeout(const bs::error_code &error)
246  {
247  if (error==ba::error::basic_errors::operation_aborted)
248  return;
249 
250  if (error)
251  {
252  ostringstream str;
253  str << "Read timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
254  Error(str);
255 
256  PostClose(false);
257  return;
258 
259  }
260 
261  if (!is_open())
262  {
263  // For example: Here we could schedule a new accept if we
264  // would not want to allow two connections at the same time.
265  return;
266  }
267 
268  // Check whether the deadline has passed. We compare the deadline
269  // against the current time since a new asynchronous operation
270  // may have moved the deadline before this actor had a chance
271  // to run.
272  if (fInTimeout.expires_at() > ba::deadline_timer::traits_type::now())
273  return;
274 
275  Error("Timeout reading data from "+URL());
276  PostClose(false);
277  }
278 
279  // This is called when a connection was established
281  {
282  fBufEventHeader.clear();
283  fBufEventHeader.fEventCounter = 1;
284  fBufEventHeader.fStatus = 0xf000|
285  FAD::EventHeader::kDenable|
286  FAD::EventHeader::kDwrite|
287  FAD::EventHeader::kDcmLocked|
288  FAD::EventHeader::kDcmReady|
289  FAD::EventHeader::kSpiSclk;
290 
291  fEventHeader.clear();
292  for (unsigned int i=0; i<FAD::kNumChannels; i++)
293  fChannelHeader[i].clear();
294 
295  fCounter = 0;
296 
297  fBuffer.resize(sizeof(FAD::EventHeader)/2);
298  AsyncRead(ba::buffer(fBuffer), kReadHeader);
299 
300 // for (int i=0; i<36; i++)
301 // CmdSetRoi(i, 100);
302 
303 // Cmd(FAD::kCmdTriggerLine, true);
304 // Cmd(FAD::kCmdSingleTrigger);
305  }
306 
307 public:
308  void PostCmd(std::vector<uint16_t> cmd)
309  {
310  if (fBlockTransmission || !IsConnected())
311  return;
312 
313 #ifdef DEBUG_TX
314  ostringstream msg;
315  msg << "Sending command:" << hex;
316  msg << " 0x" << setw(4) << setfill('0') << cmd[0];
317  msg << " (+ " << cmd.size()-1 << " bytes data)";
318  Message(msg);
319 #endif
320  transform(cmd.begin(), cmd.end(), cmd.begin(), htons);
321 
322  PostMessage(cmd);
323  }
324 
325  void PostCmd(uint16_t cmd)
326  {
327  if (fBlockTransmission || !IsConnected())
328  return;
329 
330 #ifdef DEBUG_TX
331  ostringstream msg;
332  msg << "Sending command:" << hex;
333  msg << " 0x" << setw(4) << setfill('0') << cmd;
334  Message(msg);
335 #endif
336  cmd = htons(cmd);
337  PostMessage(&cmd, sizeof(uint16_t));
338  }
339 
340  void PostCmd(uint16_t cmd, uint16_t data)
341  {
342  if (fBlockTransmission || !IsConnected())
343  return;
344 
345 #ifdef DEBUG_TX
346  ostringstream msg;
347  msg << "Sending command:" << hex;
348  msg << " 0x" << setw(4) << setfill('0') << cmd;
349  msg << " 0x" << setw(4) << setfill('0') << data;
350  Message(msg);
351 #endif
352  const uint16_t d[2] = { htons(cmd), htons(data) };
353  PostMessage(d, sizeof(d));
354  }
355 
356 public:
357  ConnectionFAD(ba::io_service& ioservice, MessageImp &imp, uint16_t slot) :
358  Connection(ioservice, imp()), fSlot(slot),
359  fIsVerbose(false), fIsHexOutput(false), fIsDataOutput(false),
360  fBlockTransmission(false), fCounter(0),
361  fTargetRoi(FAD::kNumChannels)
362  {
363  // Maximum possible needed space:
364  // The full header, all channels with all DRS bins
365  // Two trailing shorts
366  fBuffer.reserve(sizeof(FAD::EventHeader) + FAD::kNumChannels*(sizeof(FAD::ChannelHeader) + FAD::kMaxBins*sizeof(uint16_t)) + 2*sizeof(uint16_t));
367 
368  SetLogStream(&imp);
369  }
370 
371  void Cmd(FAD::Enable cmd, bool on=true)
372  {
373  switch (cmd)
374  {
375  case FAD::kCmdDrsEnable: fBufEventHeader.Enable(FAD::EventHeader::kDenable, on); break;
376  case FAD::kCmdDwrite: fBufEventHeader.Enable(FAD::EventHeader::kDwrite, on); break;
377  case FAD::kCmdTriggerLine: fBufEventHeader.Enable(FAD::EventHeader::kTriggerLine, on); break;
378  case FAD::kCmdBusyOn: fBufEventHeader.Enable(FAD::EventHeader::kBusyOn, on); break;
379  case FAD::kCmdBusyOff: fBufEventHeader.Enable(FAD::EventHeader::kBusyOff, on); break;
380  case FAD::kCmdContTrigger: fBufEventHeader.Enable(FAD::EventHeader::kContTrigger, on); break;
381  case FAD::kCmdSocket: fBufEventHeader.Enable(FAD::EventHeader::kSock17, !on); break;
382  default:
383  break;
384  }
385 
386  PostCmd(cmd + (on ? 0 : 0x100));
387  }
388 
389  // ------------------------------
390 
391  // IMPLEMENT: Abs/Rel
392  void CmdPhaseShift(int16_t val)
393  {
394  vector<uint16_t> cmd(abs(val)+2, FAD::kCmdPhaseApply);
395  cmd[0] = FAD::kCmdPhaseReset;
397  PostCmd(cmd);
398  }
399 
400  bool CmdSetTriggerRate(int32_t val)
401  {
402  if (val<0 || val>0xffff)
403  return false;
404 
405  fBufEventHeader.fTriggerGeneratorPrescaler = val;
406  PostCmd(FAD::kCmdWriteRate, val);//uint8_t(1000./val/12.5));
407  //PostCmd(FAD::kCmdWriteExecute);
408 
409  return true;
410  }
411 
412  void CmdSetRunNumber(uint32_t num)
413  {
414  fBufEventHeader.fRunNumber = num;
415 
416  PostCmd(FAD::kCmdWriteRunNumberLSW, num&0xffff);
417  PostCmd(FAD::kCmdWriteRunNumberMSW, num>>16);
418  PostCmd(FAD::kCmdWriteExecute);
419  }
420 
421  void CmdSetRegister(uint8_t addr, uint16_t val)
422  {
423  // Allowed addr: [0, MAX_ADDR]
424  // Allowed value: [0, MAX_VAL]
425  PostCmd(FAD::kCmdWrite + addr, val);
426  PostCmd(FAD::kCmdWriteExecute);
427  }
428 
429  bool CmdSetDacValue(int8_t addr, uint16_t val)
430  {
431  if (addr<0)
432  {
433  for (unsigned int i=0; i<=FAD::kMaxDacAddr; i++)
434  {
435  fBufEventHeader.fDac[i] = val;
436  PostCmd(FAD::kCmdWriteDac + i, val);
437  }
438  PostCmd(FAD::kCmdWriteExecute);
439  return true;
440  }
441 
442  if (uint8_t(addr)>FAD::kMaxDacAddr) // NDAC
443  return false;
444 
445  fBufEventHeader.fDac[addr] = val;
446 
447  PostCmd(FAD::kCmdWriteDac + addr, val);
448  PostCmd(FAD::kCmdWriteExecute);
449  return true;
450  }
451 
452  bool CmdSetRoi(int8_t addr, uint16_t val)
453  {
454  if (val>FAD::kMaxRoiValue)
455  return false;
456 
457  if (addr<0)
458  {
459  for (unsigned int i=0; i<=FAD::kMaxRoiAddr; i++)
460  {
461  fTargetRoi[i] = val;
462  PostCmd(FAD::kCmdWriteRoi + i, val);
463  }
464  PostCmd(FAD::kCmdWriteExecute);
465  return true;
466  }
467 
468  if (uint8_t(addr)>FAD::kMaxRoiAddr)
469  return false;
470 
471  fTargetRoi[addr] = val;
472 
473  PostCmd(FAD::kCmdWriteRoi + addr, val);
474  PostCmd(FAD::kCmdWriteExecute);
475  return true;
476  }
477 
478  bool CmdSetRoi(uint16_t val) { return CmdSetRoi(-1, val); }
479 
480  void SetVerbose(bool b)
481  {
482  fIsVerbose = b;
483  }
484 
485  void SetHexOutput(bool b)
486  {
487  fIsHexOutput = b;
488  }
489 
490  void SetDataOutput(bool b)
491  {
492  fIsDataOutput = b;
493  }
494 
495  void SetBlockTransmission(bool b)
496  {
497  fBlockTransmission = b;
498  }
499 
501  {
502  return fBlockTransmission;
503  }
504 
505  void PrintEvent()
506  {
507  if (fCounter>0)
508  {
509  PrintEventHeader();
510  PrintChannelHeaders();
511  }
512  else
513  Out() << "No event received yet." << endl;
514  }
515 
516  bool HasCorrectRoi() const
517  {
518  for (int i=0; i<FAD::kNumChannels; i++)
519  if (fTargetRoi[i]!=fChannelHeader[i].fRegionOfInterest)
520  return false;
521 
522  return true;
523  }
524 
525  bool HasCorrectHeader() const
526  {
527  return fEventHeader==fBufEventHeader;
528  }
529 
530  bool IsConfigured() const
531  {
532  return HasCorrectRoi() && HasCorrectHeader();
533  }
534 
536  {
537  Out() << "================================================================================" << endl;
538  fEventHeader.print(Out());
539  Out() << "--------------------------------------------------------------------------------" << endl;
540  fBufEventHeader.print(Out());
541  Out() << "================================================================================" << endl;
542  }
543 
544  const FAD::EventHeader &GetConfiguration() const { return fBufEventHeader; }
545 };
546 
547 // ------------------------------------------------------------------------
548 
549 template <class T>
550 class StateMachineFAD : public StateMachineAsio<T>, public EventBuilderWrapper
551 {
552 private:
553  typedef map<uint8_t, ConnectionFAD*> BoardList;
554 
555  BoardList fBoards;
556 
560  bool fDebugTx;
561 
562  bool CheckEventSize(size_t has, const char *name, size_t size)
563  {
564  if (has==size)
565  return true;
566 
567  ostringstream msg;
568  msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
569  T::Fatal(msg);
570  return false;
571  }
572 
573  int Cmd(FAD::Enable command)
574  {
575  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
576  i->second->Cmd(command);
577 
578  return T::GetCurrentState();
579  }
580 
581  int SendCmd(const EventImp &evt)
582  {
583  if (!CheckEventSize(evt.GetSize(), "SendCmd", 4))
584  return T::kSM_FatalError;
585 
586  if (evt.GetUInt()>0xffff)
587  {
588  T::Warn("Command value out of range (0-65535).");
589  return T::GetCurrentState();
590  }
591 
592  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
593  i->second->PostCmd(evt.GetUInt());
594 
595  return T::GetCurrentState();
596  }
597 
598  int SendCmdData(const EventImp &evt)
599  {
600  if (!CheckEventSize(evt.GetSize(), "SendCmdData", 8))
601  return T::kSM_FatalError;
602 
603  const uint32_t *ptr = evt.Ptr<uint32_t>();
604 
605  if (ptr[0]>0xffff)
606  {
607  T::Warn("Command value out of range (0-65535).");
608  return T::GetCurrentState();
609  }
610 
611  if (ptr[1]>0xffff)
612  {
613  T::Warn("Data value out of range (0-65535).");
614  return T::GetCurrentState();
615  }
616 
617  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
618  i->second->PostCmd(ptr[0], ptr[1]);
619 
620  return T::GetCurrentState();
621  }
622 
623  int CmdEnable(const EventImp &evt, FAD::Enable command)
624  {
625  if (!CheckEventSize(evt.GetSize(), "CmdEnable", 1))
626  return T::kSM_FatalError;
627 
628  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
629  i->second->Cmd(command, evt.GetBool());
630 
631  return T::GetCurrentState();
632  }
633 
634  bool Check(const uint32_t *dat, uint32_t maxaddr, uint32_t maxval)
635  {
636  if (dat[0]>maxaddr)
637  {
638  ostringstream msg;
639  msg << hex << "Address " << dat[0] << " out of range, max=" << maxaddr << ".";
640  T::Error(msg);
641  return false;
642  }
643 
644  if (dat[1]>maxval)
645  {
646  ostringstream msg;
647  msg << hex << "Value " << dat[1] << " out of range, max=" << maxval << ".";
648  T::Error(msg);
649  return false;
650  }
651 
652  return true;
653  }
654 
655  int SetRegister(const EventImp &evt)
656  {
657  if (!CheckEventSize(evt.GetSize(), "SetRegister", 8))
658  return T::kSM_FatalError;
659 
660  const uint32_t *dat = evt.Ptr<uint32_t>();
661 
662  if (!Check(dat, FAD::kMaxRegAddr, FAD::kMaxRegValue))
663  return T::GetCurrentState();
664 
665  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
666  i->second->CmdSetRegister(dat[0], dat[1]);
667 
668  return T::GetCurrentState();
669  }
670 
671  int SetRoi(const EventImp &evt)
672  {
673  if (!CheckEventSize(evt.GetSize(), "SetRoi", 8))
674  return T::kSM_FatalError;
675 
676  const int32_t *dat = evt.Ptr<int32_t>();
677 
678  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
679  if (!i->second->CmdSetRoi(dat[0], dat[1]))
680  {
681  ostringstream msg;
682  msg << hex << "Channel " << dat[0] << " or Value " << dat[1] << " out of range.";
683  T::Error(msg);
684  return T::GetCurrentState();
685  }
686 
687 
688  return T::GetCurrentState();
689  }
690 
691  int SetDac(const EventImp &evt)
692  {
693  if (!CheckEventSize(evt.GetSize(), "SetDac", 8))
694  return T::kSM_FatalError;
695 
696  const int32_t *dat = evt.Ptr<int32_t>();
697 
698  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
699  if (!i->second->CmdSetDacValue(dat[0], dat[1]))
700  {
701  ostringstream msg;
702  msg << hex << "Channel " << dat[0] << " or Value " << dat[1] << " out of range.";
703  T::Error(msg);
704  return T::GetCurrentState();
705  }
706 
707  return T::GetCurrentState();
708  }
709 
710  int Trigger(int n)
711  {
712  for (int nn=0; nn<n; nn++)
713  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
714  i->second->Cmd(FAD::kCmdSingleTrigger);
715 
716  return T::GetCurrentState();
717  }
718 
719  int SendTriggers(const EventImp &evt)
720  {
721  if (!CheckEventSize(evt.GetSize(), "SendTriggers", 4))
722  return T::kSM_FatalError;
723 
724  Trigger(evt.GetUInt());
725 
726  return T::GetCurrentState();
727  }
728 /*
729  int StartRun(const EventImp &evt, bool start)
730  {
731  if (!CheckEventSize(evt.GetSize(), "StartRun", 0))
732  return T::kSM_FatalError;
733 
734  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
735  i->second->Cmd(FAD::kCmdRun, start);
736 
737  return T::GetCurrentState();
738  }
739 */
740  int PhaseShift(const EventImp &evt)
741  {
742  if (!CheckEventSize(evt.GetSize(), "PhaseShift", 2))
743  return T::kSM_FatalError;
744 
745  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
746  i->second->CmdPhaseShift(evt.GetShort());
747 
748  return T::GetCurrentState();
749  }
750 
751  int SetTriggerRate(const EventImp &evt)
752  {
753  if (!CheckEventSize(evt.GetSize(), "SetTriggerRate", 4))
754  return T::kSM_FatalError;
755 
756  if (evt.GetUInt()>0xffff)
757  {
758  ostringstream msg;
759  msg << hex << "Value " << evt.GetUShort() << " out of range, max=" << 0xffff << "(?)";
760  T::Error(msg);
761  return T::GetCurrentState();
762  }
763 
764  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
765  i->second->CmdSetTriggerRate(evt.GetUInt());
766 
767  return T::GetCurrentState();
768  }
769 
770  int SetRunNumber(const EventImp &evt)
771  {
772  if (!CheckEventSize(evt.GetSize(), "SetRunNumber", 8))
773  return T::kSM_FatalError;
774 
775  const uint64_t num = evt.GetUXtra();
776 
777  if (num<=0 || num>FAD::kMaxRunNumber)
778  {
779  ostringstream msg;
780  msg << "Run number " << num << " out of range [1;" << FAD::kMaxRunNumber << "]";
781  T::Error(msg);
782  return T::GetCurrentState();
783  }
784 
785  if (!IncreaseRunNumber(num))
786  return T::GetCurrentState();
787 
788  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
789  i->second->CmdSetRunNumber(GetRunNumber());
790 
791  return T::GetCurrentState();
792  }
793 
794  int SetMaxMemoryBuffer(const EventImp &evt)
795  {
796  if (!CheckEventSize(evt.GetSize(), "SetMaxMemoryBuffer", 2))
797  return T::kSM_FatalError;
798 
799  const int16_t mem = evt.GetShort();
800 
801  if (mem<=0)
802  {
803  ostringstream msg;
804  msg << hex << "Value " << mem << " out of range.";
805  T::Error(msg);
806  return T::GetCurrentState();
807  }
808 
809  SetMaxMemory(mem);
810 
811  return T::GetCurrentState();
812  }
813 
814  int SetEventTimeoutSec(const EventImp &evt)
815  {
816  if (!CheckEventSize(evt.GetSize(), "SetEventTimeoutSec", 2))
817  return T::kSM_FatalError;
818 
819  const int16_t sec = evt.GetShort();
820 
821  if (sec<=0)
822  {
823  ostringstream msg;
824  msg << hex << "Value " << sec << " out of range.";
825  T::Error(msg);
826  return T::GetCurrentState();
827  }
828 
829  SetEventTimeout(sec);
830 
831  return T::GetCurrentState();
832  }
833 
834  int SetFileFormat(const EventImp &evt)
835  {
836  if (!CheckEventSize(evt.GetSize(), "SetFileFormat", 2))
837  return T::kSM_FatalError;
838 
839  const uint16_t fmt = evt.GetUShort();
840 
841  // A simple way to make sure that no invalid file format
842  // is passed to the event builder
843  switch (fmt)
844  {
845  case FAD::kNone:
846  case FAD::kDebug:
847  case FAD::kFits:
848  case FAD::kZFits:
849  case FAD::kCfitsio:
850  case FAD::kRaw:
851  case FAD::kCalib:
852  SetOutputFormat(FAD::FileFormat_t(fmt));
853  break;
854  default:
855  T::Error("File format unknonw.");
856  return T::GetCurrentState();
857  }
858 
859  return T::GetCurrentState();
860  }
861 
863  {
864  SetOutputFormat(FAD::kCalib);
865  return T::GetCurrentState();
866  }
867 
869  {
871  return T::GetCurrentState();
872  }
873 
874  int LoadDrsCalibration(const EventImp &evt)
875  {
877  return T::GetCurrentState();
878  }
879 /*
880  int Test(const EventImp &evt)
881  {
882  if (!CheckEventSize(evt.GetSize(), "Test", 2))
883  return T::kSM_FatalError;
884 
885 
886  SetMode(evt.GetShort());
887 
888  return T::GetCurrentState();
889  }*/
890 
891 
892  int SetVerbosity(const EventImp &evt)
893  {
894  if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
895  return T::kSM_FatalError;
896 
897  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
898  i->second->SetVerbose(evt.GetBool());
899 
900  return T::GetCurrentState();
901  }
902 
903  int SetHexOutput(const EventImp &evt)
904  {
905  if (!CheckEventSize(evt.GetSize(), "SetHexOutput", 1))
906  return T::kSM_FatalError;
907 
908  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
909  i->second->SetHexOutput(evt.GetBool());
910 
911  return T::GetCurrentState();
912  }
913 
914  int SetDataOutput(const EventImp &evt)
915  {
916  if (!CheckEventSize(evt.GetSize(), "SetDataOutput", 1))
917  return T::kSM_FatalError;
918 
919  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
920  i->second->SetDataOutput(evt.GetBool());
921 
922  return T::GetCurrentState();
923  }
924 
925  int SetDebugTx(const EventImp &evt)
926  {
927  if (!CheckEventSize(evt.GetSize(), "SetDebugTx", 1))
928  return T::kSM_FatalError;
929 
930  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
931  i->second->SetDebugTx(evt.GetBool());
932 
933  return T::GetCurrentState();
934  }
935 
936  const BoardList::iterator GetSlot(uint16_t slot)
937  {
938  const BoardList::iterator it=fBoards.find(slot);
939  if (it==fBoards.end())
940  {
941  ostringstream str;
942  str << "Slot " << slot << " not found.";
943  T::Warn(str);
944  }
945 
946  return it;
947  }
948 
949  int PrintEvent(const EventImp &evt)
950  {
951  if (!CheckEventSize(evt.GetSize(), "PrintEvent", 2))
952  return T::kSM_FatalError;
953 
954  const int16_t slot = evt.Get<int16_t>();
955 
956  if (slot<0)
957  {
958  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
959  i->second->PrintEvent();
960  }
961  else
962  {
963  const BoardList::iterator it=GetSlot(slot);
964  if (it!=fBoards.end())
965  it->second->PrintEvent();
966  }
967 
968  return T::GetCurrentState();
969  }
970 
972  {
973  if (!CheckEventSize(evt.GetSize(), "SetBlockTransmission", 3))
974  return T::kSM_FatalError;
975 
976  const int16_t slot = evt.Get<int32_t>();
977 
978  const BoardList::iterator it=GetSlot(slot);
979  if (it!=fBoards.end())
980  it->second->SetBlockTransmission(evt.Get<uint8_t>(2));
981 
982  return T::GetCurrentState();
983  }
984 
986  {
987  if (!CheckEventSize(evt.GetSize(), "SetBlockTransmissionRange", 5))
988  return T::kSM_FatalError;
989 
990  const int16_t *slot = evt.Ptr<int16_t>();
991  const bool block = evt.Get<uint8_t>(4);
992 
993  for (int i=slot[0]; i<=slot[1]; i++)
994  {
995  const BoardList::iterator it=GetSlot(i);
996  if (it!=fBoards.end())
997  it->second->SetBlockTransmission(block);
998  }
999 
1000  return T::GetCurrentState();
1001  }
1002 
1003  int SetIgnoreSlot(const EventImp &evt)
1004  {
1005  if (!CheckEventSize(evt.GetSize(), "SetIgnoreSlot", 3))
1006  return T::kSM_FatalError;
1007 
1008  const uint16_t slot = evt.Get<uint16_t>();
1009 
1010  if (slot>39)
1011  {
1012  T::Warn("Slot out of range (0-39).");
1013  return T::GetCurrentState();
1014  }
1015 
1016  SetIgnore(slot, evt.Get<uint8_t>(2));
1017 
1018  return T::GetCurrentState();
1019  }
1020 
1021  int SetIgnoreSlots(const EventImp &evt)
1022  {
1023  if (!CheckEventSize(evt.GetSize(), "SetIgnoreSlots", 5))
1024  return T::kSM_FatalError;
1025 
1026  const int16_t *slot = evt.Ptr<int16_t>();
1027  const bool block = evt.Get<uint8_t>(4);
1028 
1029  if (slot[0]<0 || slot[1]>39 || slot[0]>slot[1])
1030  {
1031  T::Warn("Slot out of range.");
1032  return T::GetCurrentState();
1033  }
1034 
1035  for (int i=slot[0]; i<=slot[1]; i++)
1036  SetIgnore(i, block);
1037 
1038  return T::GetCurrentState();
1039  }
1040 
1041  int StartConfigure(const EventImp &evt)
1042  {
1043  const string name = evt.Ptr<char>(16);
1044 
1045  fTargetConfig = fConfigs.find(name);
1046  if (fTargetConfig==fConfigs.end())
1047  {
1048  T::Error("StartConfigure - Run-type '"+name+"' not found.");
1049  return T::GetCurrentState();
1050  }
1051 
1052  // FIXME: What about an error state?
1053  const uint32_t runno = StartNewRun(evt.Get<int64_t>(), evt.Get<int64_t>(8), *fTargetConfig);
1054  if (runno==0)
1055  return FAD::State::kConnected;
1056 
1057  ostringstream str;
1058  str << "Starting configuration for run " << runno << " (" << name << ")";
1059  T::Message(str.str());
1060 
1061  if (runno>=1000)
1062  T::Warn("Run number exceeds logical maximum of 999 - this is no problem for writing but might give raise to problems in the analysis.");
1063 
1064  const FAD::Configuration &conf = fTargetConfig->second;
1065 
1066  for (BoardList::iterator it=fBoards.begin(); it!=fBoards.end(); it++)
1067  {
1068  ConnectionFAD &fad = *it->second;
1069 
1070  fad.Cmd(FAD::kCmdBusyOn, true); // continously on
1071  fad.Cmd(FAD::kCmdTriggerLine, false);
1072  fad.Cmd(FAD::kCmdContTrigger, false);
1073  fad.Cmd(FAD::kCmdSocket, true);
1074  fad.Cmd(FAD::kCmdBusyOff, false); // normal when BusyOn==0
1075 
1076  fad.Cmd(FAD::kCmdDwrite, conf.fDwrite);
1077  fad.Cmd(FAD::kCmdDrsEnable, conf.fDenable);
1078 
1079  for (int i=0; i<FAD::kNumDac; i++)
1080  fad.CmdSetDacValue(i, conf.fDac[i]);
1081 
1082  for (int i=0; i<FAD::kNumChips; i++)
1083  for (int j=0; j<FAD::kNumChannelsPerChip; j++)
1084  fad.CmdSetRoi(i*FAD::kNumChannelsPerChip+j, conf.fRoi[j]);
1085 
1086  fad.CmdSetTriggerRate(conf.fTriggerRate);
1087  fad.CmdSetRunNumber(runno);
1089  fad.Cmd(FAD::kCmdTriggerLine, true);
1090  //fad.Cmd(FAD::kCmdSingleTrigger);
1091  //fad.Cmd(FAD::kCmdTriggerLine, true);
1092  }
1093 
1094  // Now the old run is stopped already. So all other servers can start a new run
1095  // (Note that we might need another step which only checks if the continous trigger
1096  // is wwitched off, too)
1097  const int64_t runs[2] = { runno, runno+1 };
1098  fDimStartRun.Update(runs);
1099 
1101  }
1102 
1104  {
1105  const int64_t runs[2] = { -1, GetRunNumber() };
1106  fDimStartRun.Update(runs);
1107 
1108  return FAD::State::kConnected;
1109  }
1110 
1111  void CloseRun(uint32_t runid)
1112  {
1113  if (runid==GetRunNumber()-1)
1114  ResetConfig();
1115  }
1116 
1117  int AddAddress(const EventImp &evt)
1118  {
1119  const string addr = Tools::Trim(evt.GetText());
1120 
1121  const tcp::endpoint endpoint = GetEndpoint(addr);
1122  if (endpoint==tcp::endpoint())
1123  return T::GetCurrentState();
1124 
1125  for (BoardList::const_iterator i=fBoards.begin(); i!=fBoards.end(); i++)
1126  {
1127  if (i->second->GetEndpoint()==endpoint)
1128  {
1129  T::Warn("Address "+addr+" already known.... ignored.");
1130  return T::GetCurrentState();
1131  }
1132  }
1133 
1134  AddEndpoint(endpoint);
1135 
1136  return T::GetCurrentState();
1137  }
1138 
1139  int RemoveSlot(const EventImp &evt)
1140  {
1141  if (!CheckEventSize(evt.GetSize(), "RemoveSlot", 2))
1142  return T::kSM_FatalError;
1143 
1144  const int16_t slot = evt.GetShort();
1145 
1146  const BoardList::iterator it = GetSlot(slot);
1147 
1148  if (it==fBoards.end())
1149  return T::GetCurrentState();
1150 
1151  ConnectSlot(slot, tcp::endpoint());
1152 
1153  delete it->second;
1154  fBoards.erase(it);
1155 
1156  return T::GetCurrentState();
1157  }
1158 
1160  {
1161  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
1162  {
1163  const int &idx = i->first;
1164  const ConnectionFAD *fad = i->second;
1165 
1166  ostringstream str;
1167  str << "Slot " << setw(2) << idx << ": " << fad->GetEndpoint();
1168 
1169  if (fad->IsConnecting())
1170  str << " (0:connecting, ";
1171  else
1172  {
1173  if (fad->IsClosed())
1174  str << " (0:disconnected, ";
1175  if (fad->IsConnected())
1176  str << " (0:connected, ";
1177  }
1178 
1179  switch (fStatus2[idx])
1180  {
1181  case 0: str << "1:disconnected)"; break;
1182  case 8: str << "1:connected)"; break;
1183  default: str << "1:connecting)"; break;
1184  }
1185 
1186  if (fad->IsTransmissionBlocked())
1187  str << " [cmd_blocked]";
1188 
1189  if (fStatus2[idx]==8 && IsIgnored(idx))
1190  str << " [data_ignored]";
1191 
1192  if (fad->IsConnected() && fStatus2[idx]==8 && fad->IsConfigured())
1193  str << " [configured]";
1194 
1195  T::Out() << str.str() << endl;
1196  }
1197 
1198  T::Out() << "Event builder thread:";
1199  if (!IsThreadRunning())
1200  T::Out() << " not";
1201  T::Out() << " running" << endl;
1202 
1203  // FIXME: Output state
1204 
1205  return T::GetCurrentState();
1206  }
1207 
1208  void EnableConnection(ConnectionFAD *ptr, bool enable=true)
1209  {
1210  if (!enable)
1211  {
1212  ptr->PostClose(false);
1213  return;
1214  }
1215 
1216  if (!ptr->IsDisconnected())
1217  {
1218  ostringstream str;
1219  str << ptr->GetEndpoint();
1220 
1221  T::Warn("Connection to "+str.str()+" already in progress.");
1222  return;
1223  }
1224 
1225  ptr->StartConnect();
1226  }
1227 
1228  void EnableAll(bool enable=true)
1229  {
1230  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
1231  EnableConnection(i->second, enable);
1232  }
1233 
1235  {
1237  return T::GetCurrentState();
1238  }
1239 
1240  int EnableSlot(const EventImp &evt, bool enable)
1241  {
1242  if (!CheckEventSize(evt.GetSize(), "EnableSlot", 2))
1243  return T::kSM_FatalError;
1244 
1245  const int16_t slot = evt.GetShort();
1246 
1247  const BoardList::iterator it = GetSlot(slot);
1248  if (it==fBoards.end())
1249  return T::GetCurrentState();
1250 
1251  EnableConnection(it->second, enable);
1252  ConnectSlot(it->first, enable ? it->second->GetEndpoint() : tcp::endpoint());
1253 
1254  return T::GetCurrentState();
1255  }
1256 
1257  int ToggleSlot(const EventImp &evt)
1258  {
1259  if (!CheckEventSize(evt.GetSize(), "ToggleSlot", 2))
1260  return T::kSM_FatalError;
1261 
1262  const int16_t slot = evt.GetShort();
1263 
1264  const BoardList::iterator it = GetSlot(slot);
1265  if (it==fBoards.end())
1266  return T::GetCurrentState();
1267 
1268  const bool enable = it->second->IsDisconnected();
1269 
1270  EnableConnection(it->second, enable);
1271  ConnectSlot(it->first, enable ? it->second->GetEndpoint() : tcp::endpoint());
1272 
1273  return T::GetCurrentState();
1274  }
1275 
1277  {
1278  vector<tcp::endpoint> addr(40);
1279 
1280  for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
1281  addr[i->first] = i->second->GetEndpoint();
1282 
1283  StartThread(addr);
1284  EnableAll(true);
1285 
1286  return T::GetCurrentState();
1287  }
1288 
1290  {
1291  Exit();
1292  EnableAll(false);
1293  return T::GetCurrentState();
1294  }
1295 
1297  {
1298  Abort();
1299  EnableAll(false);
1300  return T::GetCurrentState();
1301  }
1302 
1303  int Reset(bool soft)
1304  {
1305  ResetThread(soft);
1306  return T::GetCurrentState();
1307  }
1308 
1309  // ============================================================================
1310 
1311  int SetupZFits(const EventImp &evt, const std::function<void(int32_t)> &func)
1312  {
1313  if (!CheckEventSize(evt.GetSize(), "SetupZFits", 2))
1314  return T::kSM_FatalError;
1315 
1316  func(evt.GetShort());
1317  return T::GetCurrentState();
1318  }
1319 
1320 
1321  // ============================================================================
1322 /*
1323  bool ProcessReconnection(const list<ReconnectionSlot>::iterator &it)
1324  {
1325  auto board = GetSlot(it->slot);
1326  if (board==fBoards.end())
1327  return false;
1328 
1329  ConnectionFAD *fad = board->second;
1330 
1331  // ----------------------------------------------
1332  // Disconnect
1333  // ----------------------------------------------
1334  if (it->state==0)
1335  {
1336  if (!fad->IsConnected())
1337  return false;
1338 
1339  EnableConnection(fad, false);
1340  ConnectSlot(it->slot, tcp::endpoint());
1341 
1342  it->time = Time();
1343  it->state = 1;
1344 
1345  return true;
1346  }
1347 
1348  // ----------------------------------------------
1349  // Wait for disconnect or timeout
1350  // ----------------------------------------------
1351  if (it->state==1)
1352  {
1353  if (!fad->IsDisconnected() && it->time+boost::posix_time::seconds(10)>Time())
1354  return true;
1355 
1356  it->time = Time();
1357  it->state = 2;
1358 
1359  return true;
1360  }
1361 
1362  // ----------------------------------------------
1363  // Wait for timeout after disconnect / Re-connect
1364  // ----------------------------------------------
1365  if (it->state==2)
1366  {
1367  if (it->time+boost::posix_time::seconds(3)>Time())
1368  return true;
1369 
1370  EnableConnection(fad, true);
1371  ConnectSlot(it->slot, fad->GetEndpoint());
1372 
1373  it->time = Time();
1374  it->state = 3;
1375 
1376  return true;
1377  }
1378 
1379  // ----------------------------------------------
1380  // Wait for connect or timeout / Re-start
1381  // ----------------------------------------------
1382  if (!fad->IsConnected() && it->time+boost::posix_time::seconds(10)>Time())
1383  return true;
1384 
1385  // 'Fix' the information which got lost during re-connection
1386  fad->Cmd(FAD::kCmdBusyOff, false);
1387  fad->Cmd(FAD::kCmdSocket, false);
1388  fad->Cmd(FAD::kCmdTriggerLine, true);
1389 
1390  return false;
1391  }
1392 */
1393  // ============================================================================
1394 
1395  vector<uint8_t> fStatus1;
1396  vector<uint8_t> fStatus2;
1397  bool fStatusT;
1398 
1399  int Execute()
1400  {
1401  // ===== Evaluate connection status =====
1402 
1403  uint16_t nclosed1 = 0;
1404  uint16_t nconnecting1 = 0;
1405  uint16_t nconnecting2 = 0;
1406  uint16_t nconnected1 = 0;
1407  uint16_t nconnected2 = 0;
1408  uint16_t nconfigured = 0;
1409 
1410  vector<uint8_t> stat1(40);
1411  vector<uint8_t> stat2(40);
1412 
1413  int cnt = 0; // counter for enabled board
1414 
1415  const bool runs = IsThreadRunning();
1416 
1417  for (int idx=0; idx<40; idx++)
1418  {
1419  // ----- Command socket -----
1420  const BoardList::const_iterator &slot = fBoards.find(idx);
1421  if (slot!=fBoards.end())
1422  {
1423  const ConnectionFAD *c = slot->second;
1424  if (c->IsDisconnected())
1425  {
1426  stat1[idx] = 0;
1427  nclosed1++;
1428 
1429  //DisconnectSlot(idx);
1430  }
1431  if (c->IsConnecting())
1432  {
1433  stat1[idx] = 1;
1434  nconnecting1++;
1435  }
1436  if (c->IsConnected())
1437  {
1438  stat1[idx] = 2;
1439  nconnected1++;
1440 
1441  if (c->IsConfigured())
1442  {
1443  stat1[idx] = 3;
1444  nconfigured++;
1445  }
1446  }
1447 
1448  cnt++;
1449  }
1450 
1451  // ----- Event builder -----
1452 
1453  stat2[idx] = 0; // disconnected
1454  if (!runs)
1455  continue;
1456 
1457  if (IsConnecting(idx))
1458  {
1459  nconnecting2++;
1460  stat2[idx] = 1; // connecting
1461  }
1462 
1463  if (IsConnected(idx))
1464  {
1465  nconnected2++;
1466  stat2[idx] = 8; // connected
1467  }
1468  }
1469 
1470  // ===== Send connection status via dim =====
1471 
1472  if (fStatus1!=stat1 || fStatus2!=stat2 || fStatusT!=runs)
1473  {
1474  fStatus1 = stat1;
1475  fStatus2 = stat2;
1476  fStatusT = runs;
1477  UpdateConnectionStatus(stat1, stat2, runs);
1478  }
1479 
1480  // ===== Return connection status =====
1481 
1482  // Keep the state during reconnection (theoretically, can only be WritingData)
1483 /* if (fReconnectionList.size()>0)
1484  {
1485  bool isnew = true;
1486  for (auto it=fReconnectionList.begin(); it!=fReconnectionList.end(); it++)
1487  if (it->state>0)
1488  {
1489  isnew = false;
1490  break;
1491  }
1492 
1493  if (isnew)
1494  {
1495  for (BoardList::iterator it=fBoards.begin(); it!=fBoards.end(); it++)
1496  it->second->Cmd(FAD::kCmdBusyOn, true); // continously on
1497  }
1498 
1499  // Loop over all scheduled re-connections
1500  for (auto it=fReconnectionList.begin(); it!=fReconnectionList.end(); it++)
1501  {
1502  if (ProcessReconnection(it))
1503  continue;
1504 
1505  const lock_guard<mutex> guard(fMutexReconnect);
1506  fReconnectionList.erase(it);
1507  }
1508 
1509  if (fReconnectionList.size()==0)
1510  {
1511  for (BoardList::iterator it=fBoards.begin(); it!=fBoards.end(); it++)
1512  it->second->Cmd(FAD::kCmdBusyOff, false);
1513  }
1514 
1515  return T::GetCurrentState();
1516  }
1517 */
1518  // fadctrl: Always connecting if not disabled
1519  // event builder:
1520  if (nconnecting1==0 && nconnected1>0 && nconnected2==nconnected1)
1521  {
1522  if (T::GetCurrentState()==FAD::State::kConfiguring1)
1523  {
1524  // Wait until the configuration commands to all boards
1525  // have been sent and achknowledged
1526  for (BoardList::iterator it=fBoards.begin(); it!=fBoards.end(); it++)
1527  if (!it->second->IsTxQueueEmpty())
1529 
1530  // Note that if there are less than 40 boards, this
1531  // can be so fast that the single trigger still
1532  // comes to early, and a short watiting is necessary :(
1533 
1534  // Now we can sent the trigger
1535  for (BoardList::iterator it=fBoards.begin(); it!=fBoards.end(); it++)
1536  it->second->Cmd(FAD::kCmdSingleTrigger);
1537 
1539  }
1540 
1541  // If all boards are configured and we are configuring
1542  // go on and start the FADs
1543  if (T::GetCurrentState()==FAD::State::kConfiguring2)
1544  {
1545  // If not all boards have yet received the proper
1546  // configuration
1547  if (nconfigured!=nconnected1)
1549 
1550  // FIXME: Distinguish between not all boards have received
1551  // the configuration and the configuration is not consistent
1552 
1553  for (BoardList::iterator it=fBoards.begin(); it!=fBoards.end(); it++)
1554  {
1555  ConnectionFAD &fad = *it->second;
1556 
1557  // Make sure that after switching on the trigger line
1558  // there needs to be some waiting before all boards
1559  // can be assumed to be listening
1561  fad.Cmd(FAD::kCmdSocket, false);
1562  //fad.Cmd(FAD::kCmdTriggerLine, true);
1563  if (fTargetConfig->second.fContinousTrigger)
1564  fad.Cmd(FAD::kCmdContTrigger, true);
1565  fad.Cmd(FAD::kCmdBusyOn, false); // continously on
1566 
1567  // FIXME: How do we find out when the FADs
1568  // successfully enabled the trigger lines?
1569  }
1570 
1571 // const lock_guard<mutex> guard(fMutexReconnect);
1572 // fReconnectionList.clear();
1573 
1575  }
1576 
1577  if (T::GetCurrentState()==FAD::State::kConfiguring3)
1578  {
1579  // Wait until the configuration commands to all boards
1580  // have been sent and achknowledged
1581  for (BoardList::iterator it=fBoards.begin(); it!=fBoards.end(); it++)
1582  if (!it->second->IsTxQueueEmpty())
1584 
1585  return FAD::State::kConfigured;
1586  }
1587 
1588  if (T::GetCurrentState()==FAD::State::kConfigured)
1589  {
1590  // Stay in Configured as long as we have a valid
1591  // configuration and the run has not yet been started
1592  // (means the the event builder has received its
1593  // first event)
1594  if (IsRunWaiting() && nconfigured==nconnected1)
1595  return FAD::State::kConfigured;
1596 
1597  if (!IsRunWaiting())
1598  T::Message("Run successfully started... first data received.");
1599  if (nconfigured!=nconnected1)
1600  T::Message("Configuration of some boards changed.");
1601  }
1602 
1603  // FIXME: Rename WritingData to TakingData
1604  return IsRunInProgress() ? FAD::State::kRunInProgress : FAD::State::kConnected;
1605  }
1606 
1607  if (nconnecting1>0 || nconnecting2>0 || nconnected1!=nconnected2)
1608  return FAD::State::kConnecting;
1609 
1610  // nconnected1 == nconnected2 == 0
1611  return runs ? FAD::State::kDisconnected : FAD::State::kOffline;
1612  }
1613 
1614  void AddEndpoint(const tcp::endpoint &addr)
1615  {
1616  int i=0;
1617  while (i<40)
1618  {
1619  if (fBoards.find(i)==fBoards.end())
1620  break;
1621  i++;
1622  }
1623 
1624  if (i==40)
1625  {
1626  T::Warn("Not more than 40 slots allowed.");
1627  return;
1628  }
1629 
1630  ConnectionFAD *fad = new ConnectionFAD(*this, *this, i);
1631 
1632  fad->SetEndpoint(addr);
1633  fad->SetVerbose(fIsVerbose);
1634  fad->SetHexOutput(fIsHexOutput);
1635  fad->SetDataOutput(fIsDataOutput);
1636  fad->SetDebugTx(fDebugTx);
1637 
1638  fBoards[i] = fad;
1639  }
1640 
1641 
1644 
1645  void UpdateConnectionStatus(const vector<uint8_t> &stat1, const vector<uint8_t> &stat2, bool thread)
1646  {
1647  vector<uint8_t> stat(41);
1648 
1649  for (int i=0; i<40; i++)
1650  stat[i] = stat1[i]|(stat2[i]<<3);
1651 
1652  stat[40] = thread;
1653 
1654  fDimConnection.Update(stat);
1655  }
1656 
1657 public:
1658  StateMachineFAD(ostream &out=cout) :
1659  StateMachineAsio<T>(out, "FAD_CONTROL"),
1660  EventBuilderWrapper(*static_cast<MessageImp*>(this)),
1661  fStatus1(40), fStatus2(40), fStatusT(false),
1662  fDimStartRun("FAD_CONTROL/START_RUN", "X:1;X:1",
1663  "Run numbers"
1664  "|run[idx]:Run no of last conf'd run (-1 if reset or none config'd yet)"
1665  "|next[idx]:Run number which will be assigned to next configuration"),
1666  fDimConnection("FAD_CONTROL/CONNECTIONS", "C:40;C:1",
1667  "Connection status of FAD boards"
1668  "|status[bitpattern]:lower bits stat1, upper bits stat2, for every board. 40=thread"
1669  "|thread[bool]:true or false whether the event builder threads are running")
1670  {
1671  ResetConfig();
1672  SetOutputFormat(FAD::kNone);
1673 
1674  // State names
1675  T::AddStateName(FAD::State::kOffline, "Disengaged",
1676  "All enabled FAD boards are disconnected and the event-builer thread is not running.");
1677 
1678  T::AddStateName(FAD::State::kDisconnected, "Disconnected",
1679  "All enabled FAD boards are disconnected, but the event-builder thread is running.");
1680 
1681  T::AddStateName(FAD::State::kConnecting, "Connecting",
1682  "Only some enabled FAD boards are connected.");
1683 
1684  T::AddStateName(FAD::State::kConnected, "Connected",
1685  "All enabled FAD boards are connected..");
1686 
1687  T::AddStateName(FAD::State::kConfiguring1, "Configuring1",
1688  "Waiting 3 seconds for all FADs to be configured before requesting configuration.");
1689 
1690  T::AddStateName(FAD::State::kConfiguring2, "Configuring2",
1691  "Waiting until all boards returned their configuration and they are valid.");
1692 
1693  T::AddStateName(FAD::State::kConfiguring3, "Configuring3",
1694  "Waiting until 'enable trigger line' was sent to all boards.");
1695 
1696  T::AddStateName(FAD::State::kConfigured, "Configured",
1697  "The configuration of all boards was successfully cross checked. Waiting for events with a new run number to receive.");
1698 
1699  T::AddStateName(FAD::State::kRunInProgress, "RunInProgress",
1700  "Events currently received by the event builder will be flagged to be written, no end-of-run event occured yet.");
1701 
1702  // FAD Commands
1703  T::AddEvent("SEND_CMD", "I:1", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1704  (bind(&StateMachineFAD::SendCmd, this, placeholders::_1))
1705  ("Send a command to the FADs. Values between 0 and 0xffff are allowed."
1706  "|command[uint16]:Command to be transmittted.");
1707  T::AddEvent("SEND_DATA", "I:2", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1708  (bind(&StateMachineFAD::SendCmdData, this, placeholders::_1))
1709  ("Send a command with data to the FADs. Values between 0 and 0xffff are allowed."
1710  "|command[uint16]:Command to be transmittted."
1711  "|data[uint16]:Data to be sent with the command.");
1712 
1713  T::AddEvent("ENABLE_SRCLK", "B:1", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1714  (bind(&StateMachineFAD::CmdEnable, this, placeholders::_1, FAD::kCmdSrclk))
1715  ("Set SRCLK");
1716  T::AddEvent("ENABLE_BUSY_OFF", "B:1", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1717  (bind(&StateMachineFAD::CmdEnable, this, placeholders::_1, FAD::kCmdBusyOff))
1718  ("Set BUSY continously low");
1719  T::AddEvent("ENABLE_BUSY_ON", "B:1", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1720  (bind(&StateMachineFAD::CmdEnable, this, placeholders::_1, FAD::kCmdBusyOn))
1721  ("Set BUSY constantly high (has priority over BUSY_OFF)");
1722  T::AddEvent("ENABLE_SCLK", "B:1", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1723  (bind(&StateMachineFAD::CmdEnable, this, placeholders::_1, FAD::kCmdSclk))
1724  ("Set SCLK");
1725  T::AddEvent("ENABLE_DRS", "B:1", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1726  (bind(&StateMachineFAD::CmdEnable, this, placeholders::_1, FAD::kCmdDrsEnable))
1727  ("Switch Domino wave");
1728  T::AddEvent("ENABLE_DWRITE", "B:1", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1729  (bind(&StateMachineFAD::CmdEnable, this, placeholders::_1, FAD::kCmdDwrite))
1730  ("Set Dwrite (possibly high / always low)");
1731  T::AddEvent("ENABLE_CONTINOUS_TRIGGER", "B:1", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1732  (bind(&StateMachineFAD::CmdEnable, this, placeholders::_1, FAD::kCmdContTrigger))
1733  ("Enable continous (internal) trigger.");
1734  T::AddEvent("ENABLE_TRIGGER_LINE", "B:1", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1735  (bind(&StateMachineFAD::CmdEnable, this, placeholders::_1, FAD::kCmdTriggerLine))
1736  ("Incoming triggers can be accepted/will not be accepted");
1737  T::AddEvent("ENABLE_COMMAND_SOCKET_MODE", "B:1", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1738  (bind(&StateMachineFAD::CmdEnable, this, placeholders::_1, FAD::kCmdSocket))
1739  ("Set debug mode (yes: dump events through command socket, no=dump events through other sockets)");
1740 
1741  T::AddEvent("SET_TRIGGER_RATE", "I:1", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1742  (bind(&StateMachineFAD::SetTriggerRate, this, placeholders::_1))
1743  ("Enable continous trigger");
1744  T::AddEvent("SEND_SINGLE_TRIGGER")
1745  (bind(&StateMachineFAD::Trigger, this, 1))
1746  ("Issue software triggers");
1747  T::AddEvent("SEND_N_TRIGGERS", "I", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1748  (bind(&StateMachineFAD::SendTriggers, this, placeholders::_1))
1749  ("Issue N software triggers (note that these are the triggers sent, not the triggers executed)"
1750  "|N[int]: Number of triggers to be sent to the board.");
1751  /*
1752  T::AddEvent("START_RUN", "", FAD::kConnecting, FAD::kConnected, FAD::kRunInProgress)
1753  (bind(&StateMachineFAD::StartRun, this, placeholders::_1, true))
1754  ("Set FAD DAQ mode. when started, no configurations must be send.");
1755  T::AddEvent("STOP_RUN", FAD::kConnecting, FAD::kConnected, FAD::kRunInProgress)
1756  (bind(&StateMachineFAD::StartRun, this, placeholders::_1, false))
1757  ("");
1758  */
1759  T::AddEvent("PHASE_SHIFT", "S:1", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1760  (bind(&StateMachineFAD::PhaseShift, this, placeholders::_1))
1761  ("Adjust ADC phase (in 'steps')"
1762  "|phase[short]");
1763 
1764  T::AddEvent("RESET_EVENT_COUNTER", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1766  ("Reset the FAD boards' event counter to 0.");
1767 
1768  T::AddEvent("SET_RUN_NUMBER", "X:1", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1769  (bind(&StateMachineFAD::SetRunNumber, this, placeholders::_1))
1770  ("Sent a new run-number to the boards"
1771  "|num[int]:Run number");
1772 
1773  T::AddEvent("SET_MAX_MEMORY", "S:1")
1774  (bind(&StateMachineFAD::SetMaxMemoryBuffer, this, placeholders::_1))
1775  ("Set maximum memory buffer size allowed to be consumed by the EventBuilder to buffer events."
1776  "|memory[short]:Buffer size in Mega-bytes.");
1777 
1778  T::AddEvent("SET_EVENT_TIMEOUT", "S:1")
1779  (bind(&StateMachineFAD::SetEventTimeoutSec, this, placeholders::_1))
1780  ("Set the timeout after which an event expires which was not completely received yet."
1781  "|timeout[sec]:Timeout in seconds [1;32767]");
1782 
1783  T::AddEvent("SET_REGISTER", "I:2", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1784  (bind(&StateMachineFAD::SetRegister, this, placeholders::_1))
1785  ("set register to value"
1786  "|addr[short]:Address of register"
1787  "|val[short]:Value to be set");
1788 
1789  // FIXME: Maybe add a mask which channels should be set?
1790  T::AddEvent("SET_REGION_OF_INTEREST", "I:2", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1791  (bind(&StateMachineFAD::SetRoi, this, placeholders::_1))
1792  ("Set region-of-interest to value"
1793  "|channel[short]:Channel on each chip for which the ROI is set (0-8), -1 for all"
1794  "|val[short]:Value to be set");
1795 
1796  // FIXME: Maybe add a mask which channels should be set?
1797  T::AddEvent("SET_DAC_VALUE", "I:2", FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1798  (bind(&StateMachineFAD::SetDac, this, placeholders::_1))
1799  ("Set DAC numbers in range to value"
1800  "|addr[short]:Address of register (-1 for all)"
1801  "|val[short]:Value to be set");
1802 
1803  T::AddEvent("CONFIGURE", "X:2;C", FAD::State::kConnected, FAD::State::kConfigured, FAD::State::kRunInProgress)
1804  (bind(&StateMachineFAD::StartConfigure, this, placeholders::_1))
1805  ("Configure a new run. If the internla trigger is enabled this might even start a new run."
1806  "|time_max[s]:Maximum time before the run is closed in seconds (0: unlimited)"
1807  "|num_max[int]:Maximum number of events before the run is closed in seconds (0: unlimited)"
1808  "|run_type[string]:Run type which describes the runs");
1809 
1811  (bind(&StateMachineFAD::ResetConfig, this))
1812  ("If configuration failed and the fadctrl is waiting for something, use this to reset the state.");
1813 
1814  // Verbosity commands
1815  T::AddEvent("SET_VERBOSE", "B:1")
1816  (bind(&StateMachineFAD::SetVerbosity, this, placeholders::_1))
1817  ("Set verbosity state"
1818  "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
1819 
1820  T::AddEvent("SET_HEX_OUTPUT", "B:1")
1821  (bind(&StateMachineFAD::SetHexOutput, this, placeholders::_1))
1822  ("Enable or disable hex output for received data"
1823  "|hexout[bool]:disable or enable hex output for received data (yes/no)");
1824 
1825  T::AddEvent("SET_DATA_OUTPUT", "B:1")
1826  (bind(&StateMachineFAD::SetDataOutput, this, placeholders::_1))
1827  ("Enable or disable printing of the received adc data to the console"
1828  "|dataout[bool]:disable or enable data output for received data (yes/no)");
1829 
1830  T::AddEvent("SET_DEBUG_TX", "B:1")
1831  (bind(&StateMachineFAD::SetDebugTx, this, placeholders::_1))
1832  ("Enable or disable the output of messages in case of successfull data transmission to the boards."
1833  "|debug[bool]:disable or enable debug output for transmitted data (yes/no)");
1834 
1835  T::AddEvent("PRINT_EVENT", "S:1")
1836  (bind(&StateMachineFAD::PrintEvent, this, placeholders::_1))
1837  ("Print (last) event"
1838  "|board[short]:slot from which the event should be printed (-1 for all)");
1839 
1840  T::AddEvent("BLOCK_TRANSMISSION", "S:1;B:1")
1841  (bind(&StateMachineFAD::SetBlockTransmission, this, placeholders::_1))
1842  ("Blocks the transmission of commands to the given slot. Use with care! For debugging pupose only!"
1843  "|slot[short]:Slot to which the command transmission should be blocked (0-39)"
1844  "|enable[bool]:Whether the command transmission should be blockes (yes) or allowed (no)");
1845 
1846  T::AddEvent("BLOCK_TRANSMISSION_RANGE", "S:2;B:1")
1847  (bind(&StateMachineFAD::SetBlockTransmissionRange, this, placeholders::_1))
1848  ("Blocks the transmission of commands to the given range of slots. Use with care! For debugging pupose only!"
1849  "|first[short]:First slot to which the command transmission should be blocked (0-39)"
1850  "|last[short]:Last slot to which the command transmission should be blocked (0-39)"
1851  "|enable[bool]:Whether the command transmission should be blockes (yes) or allowed (no)");
1852 
1853  T::AddEvent("IGNORE_EVENTS", "S:1;B:1")
1854  (bind(&StateMachineFAD::SetIgnoreSlot, this, placeholders::_1))
1855  ("Instructs the event-builder to ignore events from the given slot but still read the data from the socket."
1856  "|slot[short]:Slot from which the data should be ignored when building events"
1857  "|enable[bool]:Whether the event builder should ignore data from this slot (yes) or allowed (no)");
1858 
1859  T::AddEvent("IGNORE_EVENTS_RANGE", "S:2;B:1")
1860  (bind(&StateMachineFAD::SetIgnoreSlots, this, placeholders::_1))
1861  ("Instructs the event-builder to ignore events from the given slot but still read the data from the socket."
1862  "|first[short]:First slot from which the data should be ignored when building events"
1863  "|last[short]:Last slot from which the data should be ignored when building events"
1864  "|enable[bool]:Whether the event builder should ignore data from this slot (yes) or allowed (no)");
1865 
1866  T::AddEvent("CLOSE_OPEN_FILES", FAD::State::kDisconnected, FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1867  (bind(&StateMachineFAD::CloseOpenFiles, this))
1868  ("Close all run files opened by the EventBuilder.");
1869 
1870  //T::AddEvent("TEST", "S:1")
1871  // (bind(&StateMachineFAD::Test, this, placeholders::_1))
1872  // ("");
1873 
1874 
1875 
1876  // Conenction commands
1877  T::AddEvent("START", FAD::State::kOffline)
1878  (bind(&StateMachineFAD::StartConnection, this))
1879  ("Start EventBuilder thread and connect all valid slots.");
1880 
1881  T::AddEvent("STOP", FAD::State::kDisconnected, FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1882  (bind(&StateMachineFAD::StopConnection, this))
1883  ("Stop EventBuilder thread (still write buffered events) and disconnect all slots.");
1884 
1885  T::AddEvent("ABORT", FAD::State::kDisconnected, FAD::State::kConnecting, FAD::State::kConnected, FAD::State::kRunInProgress)
1886  (bind(&StateMachineFAD::AbortConnection, this))
1887  ("Immediately abort EventBuilder thread and disconnect all slots.");
1888 
1889  T::AddEvent("SOFT_RESET", FAD::State::kConnected, FAD::State::kRunInProgress)
1890  (bind(&StateMachineFAD::Reset, this, true))
1891  ("Wait for buffers to drain, close all files and reinitialize event builder thread.");
1892 
1893  T::AddEvent("HARD_RESET", FAD::State::kConnected, FAD::State::kRunInProgress)
1894  (bind(&StateMachineFAD::Reset, this, false))
1895  ("Free all buffers, close all files and reinitialize event builder thread.");
1896 
1898  (bind(&StateMachineFAD::EnableSlot, this, placeholders::_1, true))
1899  ("Connect a disconnected slot.");
1900 
1901  T::AddEvent("DISCONNECT", "S:1", FAD::State::kConnecting, FAD::State::kConnected)
1902  (bind(&StateMachineFAD::EnableSlot, this, placeholders::_1, false))
1903  ("Disconnect a connected slot.");
1904 
1906  (bind(&StateMachineFAD::ToggleSlot, this, placeholders::_1))
1907  ("Toggle the status of a slot.");
1908 
1909  T::AddEvent("SET_FILE_FORMAT", "S:1")
1910  (bind(&StateMachineFAD::SetFileFormat, this, placeholders::_1))
1911  ("Set the output file format (see FAD::FileFormat_t)");
1912 
1913  T::AddEvent("START_DRS_CALIBRATION")
1915  ("Start a drs calibration (shortcut for SET_FILEFORMAT 4)");
1916 
1917  T::AddEvent("RESET_SECONDARY_DRS_BASELINE")
1919  ("Reset the secondary drs baseline (e.g. to change roi)");
1920 
1921  T::AddEvent("LOAD_DRS_CALIBRATION", "C")
1922  (bind(&StateMachineFAD::LoadDrsCalibration, this, placeholders::_1))
1923  ("Load a DRS calibration file"
1924  "|absolute path");
1925 
1926 
1927  // --------- Setup compression of FITS files -----------
1928  T::AddEvent("SET_ZFITS_DEFAULT_NUM_THREADS", "S")
1929  (bind(&StateMachineFAD::SetupZFits, this, placeholders::_1, zofits::DefaultNumThreads))
1930  ("Set the number of compression threads to use (+1 for writing)"
1931  "|num[int]:Number of threads");
1932  T::AddEvent("SET_ZFITS_DEFAULT_MAX_MEMORY", "S")
1933  (bind(&StateMachineFAD::SetupZFits, this, placeholders::_1, zofits::DefaultMaxMemory))
1934  ("Set the maximum amount of memory zfits will use for compression"
1935  "|mem[int]:Memory in MB");
1936  T::AddEvent("SET_ZFITS_DEFAULT_NUM_TILES", "S")
1937  (bind(&StateMachineFAD::SetupZFits, this, placeholders::_1, zofits::DefaultMaxNumTiles))
1938  ("Set the number of tiles with which the catalog is initialized"
1939  "|num[int]:Number of tiles");
1940  T::AddEvent("SET_ZFITS_DEFAULT_ROWS_PER_TILE", "S")
1941  (bind(&StateMachineFAD::SetupZFits, this, placeholders::_1, zofits::DefaultNumRowsPerTile))
1942  ("Set the number of rows which are compressed into one tile"
1943  "|num[int]:Number of rows per tile");
1944 
1945 
1946  T::AddEvent("ADD_ADDRESS", "C", FAD::State::kOffline)
1947  (bind(&StateMachineFAD::AddAddress, this, placeholders::_1))
1948  ("Add the address of a DRS4 board to the first free slot"
1949  "|IP[string]:address in the format <address:port>");
1950  T::AddEvent("REMOVE_SLOT", "S:1", FAD::State::kOffline)
1951  (bind(&StateMachineFAD::RemoveSlot, this, placeholders::_1))
1952  ("Remove the Iaddress in slot n. For a list see LIST"
1953  "|slot[short]:Remove the address in slot n from the list");
1954  T::AddEvent("LIST_SLOTS")
1955  (bind(&StateMachineFAD::ListSlots, this))
1956  ("Print a list of all available board addressesa and whether they are enabled");
1957  }
1958 
1960  {
1961  for (BoardList::const_iterator i=fBoards.begin(); i!=fBoards.end(); i++)
1962  delete i->second;
1963  fBoards.clear();
1964  }
1965 
1966  tcp::endpoint GetEndpoint(const string &base)
1967  {
1968  const size_t p0 = base.find_first_of(':');
1969  const size_t p1 = base.find_last_of(':');
1970 
1971  if (p0==string::npos || p0!=p1)
1972  {
1973  T::Out() << kRed << "GetEndpoint - Wrong format ('host:port' expected)" << endl;
1974  return tcp::endpoint();
1975  }
1976 
1977  tcp::resolver resolver(StateMachineAsio<T>::get_io_service());
1978 
1979  boost::system::error_code ec;
1980 
1981  const tcp::resolver::query query(base.substr(0, p0), base.substr(p0+1));
1982  const tcp::resolver::iterator iterator = resolver.resolve(query, ec);
1983 
1984  if (ec)
1985  {
1986  T::Out() << kRed << "GetEndpoint - Couldn't resolve endpoint '" << base << "': " << ec.message();
1987  return tcp::endpoint();
1988  }
1989 
1990  return *iterator;
1991  }
1992 
1993  typedef map<string, FAD::Configuration> Configs;
1994  Configs fConfigs;
1995  Configs::const_iterator fTargetConfig;
1996 
1997 
1998  template<class V>
1999  bool CheckConfigVal(Configuration &conf, V max, const string &name, const string &sub)
2000  {
2001  if (!conf.HasDef(name, sub))
2002  {
2003  T::Error("Neither "+name+"default nor "+name+sub+" found.");
2004  return false;
2005  }
2006 
2007  const V val = conf.GetDef<V>(name, sub);
2008 
2009  if (val<=max)
2010  return true;
2011 
2012  ostringstream str;
2013  str << name << sub << "=" << val << " exceeds allowed maximum of " << max << "!";
2014  T::Error(str);
2015 
2016  return false;
2017  }
2018 
2020  {
2021  // ---------- General setup ---------
2022  fIsVerbose = !conf.Get<bool>("quiet");
2023  fIsHexOutput = conf.Get<bool>("hex-out");
2024  fIsDataOutput = conf.Get<bool>("data-out");
2025  fDebugTx = conf.Get<bool>("debug-tx");
2026 
2027  // --------- Setup compression of FITS files -----------
2028  if (conf.Has("zfits.num-threads"))
2029  zofits::DefaultNumThreads(conf.Get<int32_t>("zfits.num-threads"));
2030  if (conf.Has("zfits.max-mem"))
2031  zofits::DefaultMaxMemory(conf.Get<uint32_t>("zfits.max-mem")*1000);
2032  if (conf.Has("zfits.num-tiles"))
2033  zofits::DefaultMaxNumTiles(conf.Get<uint32_t>("zfits.num-tiles"));
2034  if (conf.Has("zfits.num-rows"))
2035  zofits::DefaultNumRowsPerTile(conf.Get<uint32_t>("zfits.num-rows"));
2036 
2037  // ---------- Setup event builder ---------
2038  SetMaxMemory(conf.Get<unsigned int>("max-mem"));
2039  SetEventTimeout(conf.Get<uint16_t>("event-timeout"));
2040 
2041  if (!InitRunNumber(conf.Get<string>("destination-folder")))
2042  return 1;
2043 
2044  // ---------- Setup run types ---------
2045  const vector<string> types = conf.Vec<string>("run-type");
2046  if (types.size()==0)
2047  T::Warn("No run-types defined.");
2048  else
2049  T::Message("Defining run-types");
2050  for (vector<string>::const_iterator it=types.begin();
2051  it!=types.end(); it++)
2052  {
2053  T::Message(" -> "+ *it);
2054 
2055  if (fConfigs.count(*it)>0)
2056  {
2057  T::Error("Run-type "+*it+" defined twice.");
2058  return 2;
2059  }
2060 
2061  FAD::Configuration target;
2062 
2063  if (!CheckConfigVal<bool>(conf, true, "enable-drs.", *it) ||
2064  !CheckConfigVal<bool>(conf, true, "enable-dwrite.", *it) ||
2065  !CheckConfigVal<bool>(conf, true, "enable-continous-trigger.", *it))
2066  return 3;
2067 
2068  target.fDenable = conf.GetDef<bool>("enable-drs.", *it);
2069  target.fDwrite = conf.GetDef<bool>("enable-dwrite.", *it);
2070  target.fContinousTrigger = conf.GetDef<bool>("enable-continous-trigger.", *it);
2071 
2072  target.fTriggerRate = 0;
2073  //if (target.fContinousTrigger)
2074  {
2075  if (!CheckConfigVal<uint16_t>(conf, 0xffff, "trigger-rate.", *it))
2076  return 4;
2077 
2078  target.fTriggerRate = conf.GetDef<uint16_t>("trigger-rate.", *it);
2079  }
2080 
2081  for (int i=0; i<FAD::kNumChannelsPerChip; i++)
2082  {
2083  ostringstream str;
2084  str << "roi-ch" << i << '.';
2085 
2086  if (!CheckConfigVal<uint16_t>(conf, FAD::kMaxRoiValue, "roi.", *it) &&
2087  !CheckConfigVal<uint16_t>(conf, FAD::kMaxRoiValue, str.str(), *it))
2088  return 5;
2089 
2090  target.fRoi[i] = conf.HasDef(str.str(), *it) ?
2091  conf.GetDef<uint16_t>(str.str(), *it) :
2092  conf.GetDef<uint16_t>("roi.", *it);
2093  }
2094 
2095  for (int i=0; i<FAD::kNumDac; i++)
2096  {
2097  ostringstream str;
2098  str << "dac-" << i << '.';
2099 
2100  if (!CheckConfigVal<uint16_t>(conf, FAD::kMaxDacValue, "dac.", *it) &&
2101  !CheckConfigVal<uint16_t>(conf, FAD::kMaxDacValue, str.str(), *it))
2102  return 6;
2103 
2104  target.fDac[i] = conf.HasDef(str.str(), *it) ?
2105  conf.GetDef<uint16_t>(str.str(), *it) :
2106  conf.GetDef<uint16_t>("dac.", *it);
2107  }
2108 
2109  fConfigs[*it] = target;
2110  }
2111 
2112  // FIXME: Add a check about unsused configurations
2113 
2114  // ---------- Setup board addresses for fake-fad ---------
2115 
2116  if (conf.Has("debug-addr"))
2117  {
2118  const string addr = conf.Get<string>("debug-addr");
2119  const int num = conf.Get<unsigned int>("debug-num");
2120 
2121  const tcp::endpoint endpoint = GetEndpoint(addr);
2122  if (endpoint==tcp::endpoint())
2123  return 7;
2124 
2125  for (int i=0; i<num; i++)
2126  AddEndpoint(tcp::endpoint(endpoint.address(), endpoint.port()+8*i));
2127 
2128  if (conf.Get<bool>("start"))
2129  StartConnection();
2130  return -1;
2131  }
2132 
2133  // ---------- Setup board addresses for the real camera ---------
2134 
2135  if (conf.Has("base-addr"))
2136  {
2137  string base = conf.Get<string>("base-addr");
2138 
2139  if (base=="def" || base =="default")
2140  base = "10.0.128.128:31919";
2141 
2142  const tcp::endpoint endpoint = GetEndpoint(base);
2143  if (endpoint==tcp::endpoint())
2144  return 8;
2145 
2146  const ba::ip::address_v4::bytes_type ip = endpoint.address().to_v4().to_bytes();
2147 
2148  if (ip[2]>250 || ip[3]>244)
2149  {
2150  T::Out() << kRed << "EvalConfiguration - IP address given by --base-addr out-of-range." << endl;
2151  return 9;
2152  }
2153 
2154  for (int crate=0; crate<4; crate++)
2155  for (int board=0; board<10; board++)
2156  {
2157  ba::ip::address_v4::bytes_type target = endpoint.address().to_v4().to_bytes();
2158  target[2] += crate;
2159  target[3] += board;
2160 
2161  AddEndpoint(tcp::endpoint(ba::ip::address_v4(target), endpoint.port()));
2162  }
2163 
2164  if (conf.Get<bool>("start"))
2165  StartConnection();
2166  return -1;
2167 
2168  }
2169 
2170  // ---------- Setup board addresses one by one ---------
2171 
2172  if (conf.Has("addr"))
2173  {
2174  const vector<string> addrs = conf.Vec<string>("addr");
2175  for (vector<string>::const_iterator i=addrs.begin(); i<addrs.end(); i++)
2176  {
2177  const tcp::endpoint endpoint = GetEndpoint(*i);
2178  if (endpoint==tcp::endpoint())
2179  return 10;
2180 
2181  AddEndpoint(endpoint);
2182  }
2183 
2184  if (conf.Get<bool>("start"))
2185  StartConnection();
2186  return -1;
2187  }
2188  return -1;
2189  }
2190 
2191 };
2192 
2193 // ------------------------------------------------------------------------
2194 
2195 #include "Main.h"
2196 
2197 template<class T, class S>
2199 {
2200  return Main::execute<T, StateMachineFAD<S>>(conf);
2201 }
2202 
2204 {
2205  po::options_description control("FAD control options");
2206  control.add_options()
2207  ("quiet,q", po_bool(true), "Disable printing contents of all received messages in clear text.")
2208  ("hex-out", po_bool(), "Enable printing contents of all printed messages also as hex data.")
2209  ("data-out", po_bool(), "Enable printing received event data.")
2210  ("debug-tx", po_bool(), "Enable debugging of ethernet transmission.")
2211  ;
2212 
2213  po::options_description connect("FAD connection options");
2214  connect.add_options()
2215  ("addr", vars<string>(), "Network address of FAD")
2216  ("base-addr", var<string>(), "Base address of all FAD")
2217  ("debug-num,n", var<unsigned int>(40), "Sets the number of fake boards to be connected locally")
2218  ("debug-addr", var<string>(), "")
2219  ("start", po_bool(false), "Start the connction immediately after boot")
2220  ;
2221 
2222  po::options_description builder("Event builder options");
2223  builder.add_options()
2224  ("max-mem", var<unsigned int>(100), "Maximum memory the event builder thread is allowed to consume for its event buffer")
2225  ("event-timeout", var<uint16_t>(30), "After how many seconds is an event considered to be timed out? (<=0: disabled)")
2226  ("destination-folder", var<string>(""), "Destination folder (base folder) for the event builder binary data files.")
2227  ;
2228 
2229  po::options_description zfits("FITS compression options");
2230  zfits.add_options()
2231  ("zfits.num-threads", var<int32_t>(), "Number of threads to spawn writing compressed FITS files")
2232  ("zfits.max-mem", var<uint32_t>(), "Maximum amount of memory to be allocated by FITS compression in MB")
2233  ("zfits.num-tiles", var<uint32_t>(), "Maximum number of tiles in the catalog")
2234  ("zfits.num-rows", var<uint32_t>(), "Maximum number of rows per tile")
2235  ;
2236 
2237  po::options_description runtype("Run type configuration");
2238  runtype.add_options()
2239  ("run-type", vars<string>(), "Run type, e.g. data, pedestal, drs-calibration, light-pulser")
2240  ("enable-dwrite.*", var<bool>(), "")
2241  ("enable-drs.*", var<bool>(), "")
2242  ("enable-continous-trigger.*", var<bool>(), "")
2243  ("trigger-rate.*", var<uint16_t>(), "")
2244  ("dac.*", var<uint16_t>(), "")
2245  ("dac-0.*", var<uint16_t>(), "")
2246  ("dac-1.*", var<uint16_t>(), "")
2247  ("dac-2.*", var<uint16_t>(), "")
2248  ("dac-3.*", var<uint16_t>(), "")
2249  ("dac-4.*", var<uint16_t>(), "")
2250  ("dac-5.*", var<uint16_t>(), "")
2251  ("dac-6.*", var<uint16_t>(), "")
2252  ("dac-7.*", var<uint16_t>(), "")
2253  ("roi.*", var<uint16_t>(), "")
2254  ("roi-ch0.*", var<uint16_t>(), "")
2255  ("roi-ch1.*", var<uint16_t>(), "")
2256  ("roi-ch2.*", var<uint16_t>(), "")
2257  ("roi-ch3.*", var<uint16_t>(), "")
2258  ("roi-ch4.*", var<uint16_t>(), "")
2259  ("roi-ch5.*", var<uint16_t>(), "")
2260  ("roi-ch6.*", var<uint16_t>(), "")
2261  ("roi-ch7.*", var<uint16_t>(), "")
2262  ("roi-ch8.*", var<uint16_t>(), "")
2263  ;
2264 
2265  conf.AddEnv("dns", "DIM_DNS_NODE");
2266  conf.AddEnv("host", "DIM_HOST_NODE");
2267 
2268  conf.AddOptions(control);
2269  conf.AddOptions(connect);
2270  conf.AddOptions(builder);
2271  conf.AddOptions(zfits);
2272  conf.AddOptions(runtype);
2273 }
2274 
2276 {
2277  cout <<
2278  "The fadctrl controls the FAD boards.\n"
2279  "\n"
2280  "The default is that the program is started without user intercation. "
2281  "All actions are supposed to arrive as DimCommands. Using the -c "
2282  "option, a local shell can be initialized. With h or help a short "
2283  "help message about the usuage can be brought to the screen.\n"
2284  "\n"
2285  "Usage: fadctrl [-c type] [OPTIONS]\n"
2286  " or: fadctrl [OPTIONS]\n";
2287  cout << endl;
2288 }
2289 
2291 {
2292  Main::PrintHelp<StateMachineFAD<StateMachine>>();
2293 
2294  /* Additional help text which is printed after the configuration
2295  options goes here */
2296 }
2297 
2298 int main(int argc, const char* argv[])
2299 {
2300  Configuration conf(argv[0]);
2301  conf.SetPrintUsage(PrintUsage);
2303  SetupConfiguration(conf);
2304 
2305  if (!conf.DoParse(argc, argv, PrintHelp))
2306  return 127;
2307 
2308 // try
2309  {
2310  // No console access at all
2311  if (!conf.Has("console"))
2312  {
2313 // if (conf.Get<bool>("no-dim"))
2314 // return RunShell<LocalStream, StateMachine>(conf);
2315 // else
2316  return RunShell<LocalStream, StateMachineDim>(conf);
2317  }
2318 
2319  // Cosole access w/ and w/o Dim
2320 /* if (conf.Get<bool>("no-dim"))
2321  {
2322  if (conf.Get<int>("console")==0)
2323  return RunShell<LocalShell, StateMachine>(conf);
2324  else
2325  return RunShell<LocalConsole, StateMachine>(conf);
2326  }
2327  else
2328 */ {
2329  if (conf.Get<int>("console")==0)
2330  return RunShell<LocalShell, StateMachineDim>(conf);
2331  else
2332  return RunShell<LocalConsole, StateMachineDim>(conf);
2333  }
2334  }
2335 /* catch (std::exception& e)
2336  {
2337  cerr << "Exception: " << e.what() << endl;
2338  return -1;
2339  }*/
2340 
2341  return 0;
2342 }
void SetDebugTx(bool b=true)
Definition: Connection.h:149
uint16_t fRegionOfInterest
Definition: HeadersFAD.h:95
int RunShell(Configuration &conf)
Definition: fadctrl.cc:2198
FAD::EventHeader fBufEventHeader
Definition: fadctrl.cc:50
int StartConnection()
Definition: fadctrl.cc:1276
int StartDrsCalibration()
Definition: fadctrl.cc:862
int StopConnection()
Definition: fadctrl.cc:1289
int SendTriggers(const EventImp &evt)
Definition: fadctrl.cc:719
int SetDac(const EventImp &evt)
Definition: fadctrl.cc:691
uint16_t fSlot
Definition: fadctrl.cc:33
bool fIsDataOutput
Definition: fadctrl.cc:559
int SendCmd(const EventImp &evt)
Definition: fadctrl.cc:581
vector< uint16_t > fTargetRoi
Definition: fadctrl.cc:51
int SetMaxMemoryBuffer(const EventImp &evt)
Definition: fadctrl.cc:794
void ConnectionEstablished()
Definition: fadctrl.cc:280
virtual void UpdateChannelHeaders()
Definition: fadctrl.cc:114
bool fIsDataOutput
Definition: fadctrl.cc:45
int main(int argc, const char *argv[])
Definition: fadctrl.cc:2298
bool Check(const uint32_t *dat, uint32_t maxaddr, uint32_t maxval)
Definition: fadctrl.cc:634
void PostClose(bool restart=true)
Definition: Connection.cc:125
bool HasCorrectHeader() const
Definition: fadctrl.cc:525
A general base-class describing events issues in a state machine.
Definition: EventImp.h:11
const char * GetText() const
Definition: EventImp.h:88
void CmdSetRegister(uint8_t addr, uint16_t val)
Definition: fadctrl.cc:421
bool IsDisconnected() const
Definition: Connection.h:144
bool fBlockTransmission
Definition: fadctrl.cc:46
bool fIsVerbose
Definition: fadctrl.cc:43
BoardList fBoards
Definition: fadctrl.cc:555
map< string, FAD::Configuration > Configs
Definition: fadctrl.cc:1993
void PrintHelp()
Definition: fadctrl.cc:2290
bool CmdSetRoi(uint16_t val)
Definition: fadctrl.cc:478
void SetupConfiguration(Configuration &conf)
Definition: Main.h:25
int CloseOpenFiles()
Definition: fadctrl.cc:1234
int i
Definition: db_dim_client.c:21
The base implementation of a distributed messaging system.
Definition: MessageImp.h:10
int SendCmdData(const EventImp &evt)
Definition: fadctrl.cc:598
void PostCmd(uint16_t cmd, uint16_t data)
Definition: fadctrl.cc:340
vector< uint8_t > fStatus1
Definition: fadctrl.cc:1395
virtual void UpdateFirstHeader()
Definition: fadctrl.cc:103
int SetIgnoreSlots(const EventImp &evt)
Definition: fadctrl.cc:1021
char str[80]
Definition: test_client.c:7
void SetPrintUsage(const std::function< void(void)> &func)
T Get(const std::string &var)
int SetBlockTransmissionRange(const EventImp &evt)
Definition: fadctrl.cc:985
Set color Red.
Definition: WindowLog.h:17
void AddEndpoint(const tcp::endpoint &addr)
Definition: fadctrl.cc:1614
int ResetSecondaryDrsBaseline()
Definition: fadctrl.cc:868
int SetDataOutput(const EventImp &evt)
Definition: fadctrl.cc:914
void SetupConfiguration(Configuration &conf)
Definition: fadctrl.cc:2203
Configs fConfigs
Definition: fadctrl.cc:1994
bool IsConnected() const
Definition: Connection.h:145
STL namespace.
bool IsTransmissionBlocked() const
Definition: fadctrl.cc:500
bool fIsHexOutput
Definition: fadctrl.cc:558
static uint32_t DefaultMaxMemory(const uint32_t &_n=0)
Definition: zofits.h:93
void AddEnv(const std::string &conf, const std::string &env)
Enable
Definition: HeadersFAD.h:17
std::vector< T > Vec(const std::string &var)
int CmdEnable(const EventImp &evt, FAD::Enable command)
Definition: fadctrl.cc:623
void PostCmd(std::vector< uint16_t > cmd)
Definition: fadctrl.cc:308
void PrintEvent()
Definition: fadctrl.cc:505
void CmdSetRunNumber(uint32_t num)
Definition: fadctrl.cc:412
int ToggleSlot(const EventImp &evt)
Definition: fadctrl.cc:1257
bool IsConnecting() const
Definition: Connection.h:146
int SetHexOutput(const EventImp &evt)
Definition: fadctrl.cc:903
static uint32_t DefaultMaxNumTiles(const uint32_t &_n=0)
Definition: zofits.h:94
void SetEndpoint(const std::string &addr, int port)
void debugHead(const FAD::EventHeader &h)
int SetIgnoreSlot(const EventImp &evt)
Definition: fadctrl.cc:1003
uint64_t fCounter
Definition: fadctrl.cc:48
virtual int ResetSecondaryDrsBaseline()
void SetBlockTransmission(bool b)
Definition: fadctrl.cc:495
uint16_t GetUShort() const
Definition: EventImp.h:92
static uint32_t DefaultNumThreads(const uint32_t &_n=-2)
static setter for the default number of threads to use. -1 means all available physical cores ...
Definition: zofits.h:92
int Cmd(FAD::Enable command)
Definition: fadctrl.cc:573
int Reset(bool soft)
Definition: fadctrl.cc:1303
bool CmdSetTriggerRate(int32_t val)
Definition: fadctrl.cc:400
virtual void StartConnect()
Definition: Connection.cc:352
bool Has(const std::string &var)
T GetDef(const std::string &var, const S &val)
vector< uint16_t > fBuffer
Definition: fadctrl.cc:36
void SetVerbose(bool b)
Definition: fadctrl.cc:480
int AddAddress(const EventImp &evt)
Definition: fadctrl.cc:1117
void AddOptions(const po::options_description &opt, bool visible=true)
Definition: Configuration.h:92
bool CmdSetRoi(int8_t addr, uint16_t val)
Definition: fadctrl.cc:452
int type
int LoadDrsCalibration(const EventImp &evt)
Definition: fadctrl.cc:874
void EnableAll(bool enable=true)
Definition: fadctrl.cc:1228
uint16_t fStartCell
Definition: HeadersFAD.h:94
DimDescribedService fDimStartRun
Definition: fadctrl.cc:1642
int SetBlockTransmission(const EventImp &evt)
Definition: fadctrl.cc:971
void PrintChannelHeaders()
Definition: fadctrl.cc:62
int SetupZFits(const EventImp &evt, const std::function< void(int32_t)> &func)
Definition: fadctrl.cc:1311
int PrintEvent(const EventImp &evt)
Definition: fadctrl.cc:949
int SetTriggerRate(const EventImp &evt)
Definition: fadctrl.cc:751
double end
int SetRunNumber(const EventImp &evt)
Definition: fadctrl.cc:770
Commandline parsing, resource file parsing and database access.
Definition: Configuration.h:9
void EnableConnection(ConnectionFAD *ptr, bool enable=true)
Definition: fadctrl.cc:1208
map< uint8_t, ConnectionFAD * > BoardList
Definition: fadctrl.cc:553
int buffer[BUFFSIZE]
Definition: db_dim_client.c:14
ConnectionFAD(ba::io_service &ioservice, MessageImp &imp, uint16_t slot)
Definition: fadctrl.cc:357
int SetRegister(const EventImp &evt)
Definition: fadctrl.cc:655
const BoardList::iterator GetSlot(uint16_t slot)
Definition: fadctrl.cc:936
int ResetConfig()
Definition: fadctrl.cc:1103
int SetEventTimeoutSec(const EventImp &evt)
Definition: fadctrl.cc:814
int size
Definition: db_dim_server.c:17
uint32_t GetUInt() const
Definition: EventImp.h:94
void CloseRun(uint32_t runid)
Definition: fadctrl.cc:1111
float data[4 *1440]
void PrintEventHeader()
Definition: fadctrl.cc:54
Definition: zfits.h:16
uint64_t GetUXtra() const
Definition: EventImp.h:96
void SetDataOutput(bool b)
Definition: fadctrl.cc:490
int SetVerbosity(const EventImp &evt)
Definition: fadctrl.cc:892
static uint32_t DefaultNumRowsPerTile(const uint32_t &_n=0)
Definition: zofits.h:95
virtual void HandleReadTimeout(const boost::system::error_code &)
Definition: Connection.h:138
FileFormat_t
Definition: HeadersFAD.h:74
void LoadDrsCalibration(const char *fname)
const boost::asio::ip::tcp::endpoint & GetEndpoint() const
Definition: Connection.h:153
int SetFileFormat(const EventImp &evt)
Definition: fadctrl.cc:834
DimDescribedService fDimConnection
Definition: fadctrl.cc:1643
bool CheckConfigVal(Configuration &conf, V max, const string &name, const string &sub)
Definition: fadctrl.cc:1999
Configs::const_iterator fTargetConfig
Definition: fadctrl.cc:1995
void clear()
Definition: HeadersFTM.h:216
bool GetBool() const
Definition: EventImp.h:90
virtual void UpdateEventHeader()
Definition: fadctrl.cc:107
int PhaseShift(const EventImp &evt)
Definition: fadctrl.cc:740
vector< uint8_t > fStatus2
Definition: fadctrl.cc:1396
Error()
Definition: HeadersFTM.h:197
int RemoveSlot(const EventImp &evt)
Definition: fadctrl.cc:1139
void CmdPhaseShift(int16_t val)
Definition: fadctrl.cc:392
void PostCmd(uint16_t cmd)
Definition: fadctrl.cc:325
std::string Trim(const std::string &str)
Definition: tools.cc:68
void PrintUsage()
Definition: fadctrl.cc:2275
Connection(boost::asio::io_service &io_service, std::ostream &out)
Definition: Connection.cc:454
static EventBuilderWrapper * This
po::typed_value< bool > * po_bool(bool def=false)
int16_t GetShort() const
Definition: EventImp.h:91
int EnableSlot(const EventImp &evt, bool enable)
Definition: fadctrl.cc:1240
void HandleReceivedData(const bs::error_code &err, size_t bytes_received, int type)
Definition: fadctrl.cc:136
void UpdateConnectionStatus(const vector< uint8_t > &stat1, const vector< uint8_t > &stat2, bool thread)
Definition: fadctrl.cc:1645
void HandleReadTimeout(const bs::error_code &error)
Definition: fadctrl.cc:245
void SetHexOutput(bool b)
Definition: fadctrl.cc:485
T Get(size_t offset=0) const
Definition: EventImp.h:66
const FAD::EventHeader & GetConfiguration() const
Definition: fadctrl.cc:544
Maintains an ansynchronous TCP/IP client connection.
Definition: Connection.h:15
int SetRoi(const EventImp &evt)
Definition: fadctrl.cc:671
Definition: fad.cc:31
bool HasDef(const std::string &var, const T &val)
StateMachineFAD(ostream &out=cout)
Definition: fadctrl.cc:1658
bool DoParse(int argc, const char **argv, const std::function< void()> &func=std::function< void()>())
int IsClosed() const
Definition: Connection.h:142
bool CheckEventSize(size_t has, const char *name, size_t size)
Definition: fadctrl.cc:562
bool IsConfigured() const
Definition: fadctrl.cc:530
tcp::endpoint GetEndpoint(const string &base)
Definition: fadctrl.cc:1966
FAD::EventHeader fEventHeader
Definition: fadctrl.cc:39
virtual int CloseOpenFiles()
int SetDebugTx(const EventImp &evt)
Definition: fadctrl.cc:925
const T * Ptr(size_t offset=0) const
Definition: EventImp.h:74
virtual void UpdateData(const uint16_t *data, size_t sz)
Definition: fadctrl.cc:122
int EvalOptions(Configuration &conf)
Definition: fadctrl.cc:2019
bool fIsHexOutput
Definition: fadctrl.cc:44
void Cmd(FAD::Enable cmd, bool on=true)
Definition: fadctrl.cc:371
bool CmdSetDacValue(int8_t addr, uint16_t val)
Definition: fadctrl.cc:429
Set attribute Bold.
Definition: WindowLog.h:36
int Trigger(int n)
Definition: fadctrl.cc:710
int AbortConnection()
Definition: fadctrl.cc:1296
int StartConfigure(const EventImp &evt)
Definition: fadctrl.cc:1041
void PrintCheckHeader()
Definition: fadctrl.cc:535
virtual size_t GetSize() const
Definition: EventImp.h:55
bool HasCorrectRoi() const
Definition: fadctrl.cc:516