FACT++  1.0
ftmctrl.cc
Go to the documentation of this file.
1 #include <array>
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 
14 #include "tools.h"
15 
16 #include "HeadersFTM.h"
17 
18 
19 namespace ba = boost::asio;
20 namespace bs = boost::system;
21 
22 using namespace std;
23 
24 // ------------------------------------------------------------------------
25 
26 class ConnectionFTM : public Connection
27 {
28 public:
29  enum States
30  {
31  // State Machine states
35  kConfigured, // Returned if idle and fBufStaticData==fStaticData
37  };
38 
39 private:
40  vector<uint16_t> fBuffer;
41 
42  bool fHasHeader;
43 
44  bool fIsVerbose;
47 
48 protected:
49  map<uint16_t, uint32_t> fCounter;
50 
53  FTM::StaticData fStaticData; // fStaticBufferTx
56 
57  FTM::StaticData fBufStaticData; // fStaticBufferRx
58 
59  virtual void UpdateFirstHeader()
60  {
61  // FIXME: Message() ?
62  Out() << endl << kBold << "First header received:" << endl;
63  Out() << fHeader;
64  if (fIsHexOutput)
65  Out() << Converter::GetHex<uint16_t>(fHeader, 16) << endl;
66  }
67 
68  virtual void UpdateHeader()
69  {
70  // emit service with trigger counter from header
71  if (!fIsVerbose)
72  return;
73 
74  if (fHeader.fType==FTM::kDynamicData && !fIsDynamicOut)
75  return;
76 
77  Out() << endl << kBold << "Header received:" << endl;
78  Out() << fHeader;
79  if (fIsHexOutput)
80  Out() << Converter::GetHex<uint16_t>(fHeader, 16) << endl;
81  }
82 
83  virtual void UpdateFtuList()
84  {
85  if (!fIsVerbose)
86  return;
87 
88  Out() << endl << kBold << "FtuList received:" << endl;
89  Out() << fFtuList;
90  if (fIsHexOutput)
91  Out() << Converter::GetHex<uint16_t>(fFtuList, 16) << endl;
92  }
93 
94  virtual void UpdateStaticData()
95  {
96  if (!fIsVerbose)
97  return;
98 
99  Out() << endl << kBold << "Static data received:" << endl;
100  Out() << fStaticData;
101  if (fIsHexOutput)
102  Out() << Converter::GetHex<uint16_t>(fStaticData, 16) << endl;
103  }
104 
105  virtual void UpdateDynamicData()
106  {
107  if (!fIsDynamicOut)
108  return;
109 
110  Out() << endl << kBold << "Dynamic data received:" << endl;
111  Out() << fDynamicData;
112  if (fIsHexOutput)
113  Out() << Converter::GetHex<uint16_t>(fDynamicData, 16) << endl;
114  }
115 
116  virtual void UpdateError()
117  {
118  if (!fIsVerbose)
119  return;
120 
121  Out() << endl << kRed << "Error received:" << endl;
122  Out() << fError;
123  if (fIsHexOutput)
124  Out() << Converter::GetHex<uint16_t>(fError, 16) << endl;
125  }
126 
127  virtual void UpdateCounter()
128  {
129  if (!fIsVerbose)
130  return;
131 
132  if (!fIsDynamicOut)
133  return;
134 
135  Out() << "Received: ";
136  Out() << "H=" << fCounter[FTM::kHeader] << " ";
137  Out() << "S=" << fCounter[FTM::kStaticData] << " ";
138  Out() << "D=" << fCounter[FTM::kDynamicData] << " ";
139  Out() << "F=" << fCounter[FTM::kFtuList] << " ";
140  Out() << "E=" << fCounter[FTM::kErrorList] << " ";
141  Out() << "R=" << fCounter[FTM::kRegister] << endl;
142  }
143 
145  {
146  bool warn1 = false;
147  if (data.IsEnabled(FTM::StaticData::kPedestal) != (data.GetSequencePed() >0) ||
148  data.IsEnabled(FTM::StaticData::kLPint) != (data.GetSequenceLPint()>0) ||
150  {
151  warn1 = true;
155  }
156 
157  bool warn2 = false;
158  const uint16_t ref = data[0].fPrescaling;
159  for (int i=1; i<40; i++)
160  {
161  if (data[i].fPrescaling != ref)
162  {
163  warn2 = true;
164  data[i].fPrescaling = ref;
165  }
166  }
167 
168  bool warn3 = false;
169  for (int i=0; i<4; i++)
170  if (data.fActiveFTU[i]!=0x3ff)
171  {
172  warn3 = true;
173  data.fActiveFTU[i]=0x3ff;
174  }
175 
176 
177 
178  if (warn1)
179  Warn("GeneralSettings not consistent with trigger sequence.");
180  if (warn2)
181  Warn("Prescaling not consistent for all boards.");
182  if (warn3)
183  Warn("Not all FTUs are enabled - enable all FTUs.");
184 
185  return !warn1 && !warn2 && !warn3;
186  }
187 
188 private:
189  void HandleReceivedData(const bs::error_code& err, size_t bytes_received, int /*type*/)
190  {
191  // Do not schedule a new read if the connection failed.
192  if (bytes_received==0 || err)
193  {
194  if (err==ba::error::eof)
195  Warn("Connection closed by remote host (FTM).");
196 
197  // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
198  // 125: Operation canceled
199  if (err && err!=ba::error::eof && // Connection closed by remote host
200  err!=ba::error::basic_errors::not_connected && // Connection closed by remote host
201  err!=ba::error::basic_errors::operation_aborted) // Connection closed by us
202  {
203  ostringstream str;
204  str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
205  Error(str);
206  }
207  PostClose(err!=ba::error::basic_errors::operation_aborted);
208  return;
209  }
210 
211  // If we have not yet received a header we expect one now
212  // This could be moved to a HandleReceivedHeader function
213  if (!fHasHeader)
214  {
215  if (bytes_received!=sizeof(FTM::Header))
216  {
217  ostringstream str;
218  str << "Excepted " << sizeof(FTM::Header) << " bytes (FTM::Header) but received " << bytes_received << ".";
219  Error(str);
220  PostClose(false);
221  return;
222  }
223 
224  fHeader = fBuffer;
225 
226  // Check the data integrity
227  if (fHeader.fDelimiter!=FTM::kDelimiterStart)
228  {
229  ostringstream str;
230  str << "Invalid header received: start delimiter wrong, received ";
231  str << hex << fHeader.fDelimiter << ", expected " << FTM::kDelimiterStart << ".";
232  Error(str);
233  PostClose(false);
234  return;
235  }
236 
237  fHasHeader = true;
238 
239  // Convert FTM state into FtmCtrl state
240  if (++fCounter[FTM::kHeader]==1)
241  UpdateFirstHeader();
242 
243  UpdateCounter();
244  UpdateHeader();
245 
246  // Start reading of data
247  switch (fHeader.fType)
248  {
249  case FTM::kStaticData:
250  case FTM::kDynamicData:
251  case FTM::kFtuList:
252  case FTM::kRegister:
253  case FTM::kErrorList:
254  // This is not very efficient because the space is reallocated
255  // maybe we can check if the capacity of the std::vector
256  // is ever decreased. If not, everythign is fine.
257  fBuffer.resize(fHeader.fDataSize);
258  AsyncRead(ba::buffer(fBuffer));
259  AsyncWait(fInTimeout, 1000, &Connection::HandleReadTimeout);
260  return;
261 
262  default:
263  ostringstream str;
264  str << "Unknonw type " << fHeader.fType << " in received header." << endl;
265  Error(str);
266  PostClose(false);
267  return;
268  }
269 
270  return;
271  }
272 
273  // Check the data integrity (check end delimiter)
274  if (ntohs(fBuffer.back())!=FTM::kDelimiterEnd)
275  {
276  ostringstream str;
277  str << "Invalid data received: end delimiter wrong, received ";
278  str << hex << ntohs(fBuffer.back()) << ", expected " << FTM::kDelimiterEnd << ".";
279  Error(str);
280  PostClose(false);
281  return;
282  }
283 
284  // Remove end delimiter
285  fBuffer.pop_back();
286 
287  try
288  {
289  // If we have already received a header this is the data now
290  // This could be moved to a HandleReceivedData function
291 
292  fCounter[fHeader.fType]++;
293  UpdateCounter();
294 
295  switch (fHeader.fType)
296  {
297  case FTM::kFtuList:
298  fFtuList = fBuffer;
299  UpdateFtuList();
300  break;
301 
302  case FTM::kStaticData:
303  if (fCounter[FTM::kStaticData]==1)
304  {
305  // This check is only done at startup
306  FTM::StaticData data(fBuffer);
307  if (!CheckConsistency(data))
308  {
309  CmdSendStatDat(data);
310  CmdPing(); // FIXME: Only needed in case of warn3
311  break;
312  }
313  }
314 
315  fStaticData = fBuffer;
316 
317  // is this the first received static data block?
318  if (!fBufStaticData.valid())
319  fBufStaticData = fStaticData;
320 
321  UpdateStaticData();
322  break;
323 
324  case FTM::kDynamicData:
325  fDynamicData = fBuffer;
326  UpdateDynamicData();
327  break;
328 
329  case FTM::kRegister:
330  if (fIsVerbose)
331  {
332  Out() << endl << kBold << "Register received: " << endl;
333  Out() << "Addr: " << ntohs(fBuffer[0]) << endl;
334  Out() << "Value: " << ntohs(fBuffer[1]) << endl;
335  }
336  break;
337 
338  case FTM::kErrorList:
339  fError = fBuffer;
340  UpdateError();
341  break;
342 
343  default:
344  ostringstream str;
345  str << "Unknonw type " << fHeader.fType << " in header." << endl;
346  Error(str);
347  PostClose(false);
348  return;
349  }
350  }
351  catch (const logic_error &e)
352  {
353  ostringstream str;
354  str << "Exception converting buffer into data structure: " << e.what();
355  Error(str);
356  PostClose(false);
357  return;
358  }
359 
360  fInTimeout.cancel();
361 
362  //fHeader.clear();
363  fHasHeader = false;
364  fBuffer.resize(sizeof(FTM::Header)/2);
365  AsyncRead(ba::buffer(fBuffer));
366  }
367 
368  // This is called when a connection was established
370  {
371  fCounter.clear();
372  fBufStaticData.clear();
373 
374  fHeader.clear();
375  fHasHeader = false;
376  fBuffer.resize(sizeof(FTM::Header)/2);
377  AsyncRead(ba::buffer(fBuffer));
378 
379 // if (!fDefaultSetup.empty())
380 // LoadStaticData(fDefaultSetup);
381 
382  // Get a header and configdata!
383  CmdReqStatDat();
384 
385  // get the DNA of the FTUs
386  CmdPing();
387  }
388 
389  void HandleReadTimeout(const bs::error_code &error)
390  {
391  if (error==ba::error::basic_errors::operation_aborted)
392  return;
393 
394  if (error)
395  {
396  ostringstream str;
397  str << "Read timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
398  Error(str);
399 
400  PostClose();
401  return;
402 
403  }
404 
405  if (!is_open())
406  {
407  // For example: Here we could schedule a new accept if we
408  // would not want to allow two connections at the same time.
409  return;
410  }
411 
412  // Check whether the deadline has passed. We compare the deadline
413  // against the current time since a new asynchronous operation
414  // may have moved the deadline before this actor had a chance
415  // to run.
416  if (fInTimeout.expires_at() > ba::deadline_timer::traits_type::now())
417  return;
418 
419  Error("Timeout ("+to_simple_string(fInTimeout.expires_from_now())+") reading data from "+URL());
420 
421  PostClose();
422  }
423 
424  template<size_t N>
425  void PostCmd(array<uint16_t, N> dat, uint16_t u1=0, uint16_t u2=0, uint16_t u3=0, uint16_t u4=0)
426  {
427  array<uint16_t, 5> cmd = {{ '@', u1, u2, u3, u4 }};
428 
429  if (fIsVerbose)
430  {
431  ostringstream msg;
432  msg << "Sending command:" << hex;
433  msg << " 0x" << setw(4) << setfill('0') << cmd[0];
434  msg << " 0x" << setw(4) << setfill('0') << u1;
435  msg << " 0x" << setw(4) << setfill('0') << u2;
436  msg << " 0x" << setw(4) << setfill('0') << u3;
437  msg << " 0x" << setw(4) << setfill('0') << u4;
438  msg << " (+" << dec << dat.size() << " words)";
439  Message(msg);
440  }
441 
442  vector<uint16_t> out(cmd.size()+dat.size());
443 
444  transform(cmd.begin(), cmd.end(), out.begin(), htons);
445  transform(dat.begin(), dat.end(), out.begin()+cmd.size(), htons);
446 
447  PostMessage(out);
448  }
449 
450  void PostCmd(vector<uint16_t> dat, uint16_t u1=0, uint16_t u2=0, uint16_t u3=0, uint16_t u4=0)
451  {
452  array<uint16_t, 5> cmd = {{ '@', u1, u2, u3, u4 }};
453 
454  if (fIsVerbose)
455  {
456  ostringstream msg;
457  msg << "Sending command:" << hex;
458  msg << " 0x" << setw(4) << setfill('0') << cmd[0];
459  msg << " 0x" << setw(4) << setfill('0') << u1;
460  msg << " 0x" << setw(4) << setfill('0') << u2;
461  msg << " 0x" << setw(4) << setfill('0') << u3;
462  msg << " 0x" << setw(4) << setfill('0') << u4;
463  msg << " (+" << dec << dat.size() << " words)";
464  Message(msg);
465  }
466 
467  vector<uint16_t> out(cmd.size()+dat.size());
468 
469  transform(cmd.begin(), cmd.end(), out.begin(), htons);
470  copy(dat.begin(), dat.end(), out.begin()+cmd.size());
471 
472  PostMessage(out);
473  }
474 
475  void PostCmd(uint16_t u1=0, uint16_t u2=0, uint16_t u3=0, uint16_t u4=0)
476  {
477  PostCmd(array<uint16_t, 0>(), u1, u2, u3, u4);
478  }
479 public:
480 
481 // static const uint16_t kMaxAddr;
482 
483 public:
484  ConnectionFTM(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()),
485  fIsVerbose(true), fIsDynamicOut(true), fIsHexOutput(true)
486  {
487  SetLogStream(&imp);
488  }
489 
491  {
492  PostCmd(FTM::kCmdToggleLed);
493  }
494 
495  void CmdPing()
496  {
497  PostCmd(FTM::kCmdPing);
498  }
499 
501  {
503  }
504 
506  {
508  }
509 
511  {
512  fBufStaticData = data;
513 
514  PostCmd(data.HtoN(), FTM::kCmdWrite, FTM::kCmdStaticData);
515 
516  // Request the changed configuration to ensure the
517  // change is distributed in the network
518  CmdReqStatDat();
519  }
520 
521  void CmdStartRun(bool log=true)
522  {
524  CmdGetRegister(0);
525 
526  if (log)
527  Info("Sending start trigger.");
528  }
529 
530  void CmdStopRun()
531  {
532  PostCmd(FTM::kCmdStopRun);
533  CmdGetRegister(0);
534 
535  Info("Sending stop trigger.");
536  }
537 
538  void CmdTakeNevents(uint32_t n)
539  {
540  const array<uint16_t, 2> data = {{ uint16_t(n>>16), uint16_t(n&0xffff) }};
541  PostCmd(data, FTM::kCmdStartRun, FTM::kTakeNevents);
542 
543  // Update state information by requesting a new header
544  CmdGetRegister(0);
545  }
546 
547  bool CmdSetRegister(uint16_t addr, uint16_t val)
548  {
549  if (addr>FTM::StaticData::kMaxAddr)
550  return false;
551 
552  const array<uint16_t, 2> data = {{ addr, val }};
553  PostCmd(data, FTM::kCmdWrite, FTM::kCmdRegister);
554 
555  reinterpret_cast<uint16_t*>(&fBufStaticData)[addr] = val;
556 
557  // Request the changed configuration to ensure the
558  // change is distributed in the network
559  CmdReqStatDat();
560 
561  return true;
562  }
563 
564  bool CmdGetRegister(uint16_t addr)
565  {
566  if (addr>FTM::StaticData::kMaxAddr)
567  return false;
568 
569  const array<uint16_t, 1> data = {{ addr }};
570  PostCmd(data, FTM::kCmdRead, FTM::kCmdRegister);
571 
572  return true;
573  }
574 
575  bool CmdResetCrate(uint16_t addr)
576  {
577  if (addr>3)
578  return false;
579 
580  PostCmd(FTM::kCmdCrateReset, 1<<addr);
581  Info("Sending crate reset for crate "+to_string(addr));
582 
583  return true;
584  }
585 
587  {
592 
593  Info("Sending camera reset");
594 
595  return true;
596  }
597 
598  bool CmdDisableReports(bool b)
599  {
600  PostCmd(FTM::kCmdDisableReports, b ? uint16_t(0) : uint16_t(1));
601  return true;
602  }
603 
604 
605  void SetVerbose(bool b)
606  {
607  fIsVerbose = b;
608  }
609 
610  void SetHexOutput(bool b)
611  {
612  fIsHexOutput = b;
613  }
614 
615  void SetDynamicOut(bool b)
616  {
617  fIsDynamicOut = b;
618  }
619 /*
620  void SetDefaultSetup(const string &file)
621  {
622  fDefaultSetup = file;
623  }
624 */
625 
626  bool LoadStaticData(string name)
627  {
628  if (name.rfind(".bin")!=name.length()-4)
629  name += ".bin";
630 
631  ifstream fin(name);
632  if (!fin)
633  return false;
634 
636 
637  fin.read(reinterpret_cast<char*>(&data), sizeof(FTM::StaticData));
638 
639  if (fin.gcount()<streamsize(sizeof(FTM::StaticData)))
640  return false;
641 
642  if (fin.fail() || fin.eof())
643  return false;
644 
645  if (fin.peek()!=-1)
646  return false;
647 
648  CmdSendStatDat(data);
649 
650  return true;
651  }
652 
653  bool SaveStaticData(string name) const
654  {
655  if (name.rfind(".bin")!=name.length()-4)
656  name += ".bin";
657 
658  ofstream fout(name);
659  if (!fout)
660  return false;
661 
662  fout.write(reinterpret_cast<const char*>(&fStaticData), sizeof(FTM::StaticData));
663 
664  return !fout.bad();
665  }
666 
667  bool SetThreshold(int32_t patch, int32_t value)
668  {
670  return false;
671 
672  if (value<0 || value>FTM::StaticData::kMaxDAC)
673  return false;
674 
675  if (patch<0)
676  {
677  FTM::StaticData data(fBufStaticData);
678 
679  bool ident = true;
680  for (int i=0; i<=FTM::StaticData::kMaxPatchIdx; i++)
681  if (data[i/4].fDAC[i%4] != value)
682  {
683  ident = false;
684  break;
685  }
686 
687  if (ident)
688  return true;
689 
690  for (int i=0; i<=FTM::StaticData::kMaxPatchIdx; i++)
691  data[i/4].fDAC[i%4] = value;
692 
693  // Maybe move to a "COMMIT" command?
694  CmdSendStatDat(data);
695 
696  return true;
697  }
698 
699  /*
700  if (data[patch/4].fDAC[patch%4] == value)
701  return true;
702  */
703 
704  // Calculate offset in static data block
705  const uint16_t addr = (uintptr_t(&fStaticData[patch/4].fDAC[patch%4])-uintptr_t(&fStaticData))/2;
706 
707  // From CmdSetRegister
708  const array<uint16_t, 2> data = {{ addr, uint16_t(value) }};
709  PostCmd(data, FTM::kCmdWrite, FTM::kCmdRegister);
710 
711  reinterpret_cast<uint16_t*>(&fBufStaticData)[addr] = value;
712 
713  // Now execute change before the static data is requested back
714  PostCmd(FTM::kCmdConfigFTU, (patch/40) | (((patch/4)%10)<<8));
715 
716  //CmdGetRegister(addr);
717  CmdReqStatDat();
718 
719  return true;
720  }
721 
722  bool SetSelectedThresholds(const int32_t *th)
723  {
724  for (int i=0; i<FTM::StaticData::kMaxPatchIdx; i++)
725  if (th[i]>FTM::StaticData::kMaxDAC)
726  return false;
727 
728  FTM::StaticData data(fBufStaticData);
729 
730  for (int i=0; i<=FTM::StaticData::kMaxPatchIdx; i++)
731  {
732  if (th[i]<0 || fBufStaticData[i/4].fDAC[i%4]==th[i])
733  continue;
734 
735  // Calculate offset in static data block
736  const uint16_t addr = (uintptr_t(&fStaticData[i/4].fDAC[i%4])-uintptr_t(&fStaticData))/2;
737 
738  reinterpret_cast<uint16_t*>(&fBufStaticData)[addr] = th[i];
739 
740  // From CmdSetRegister
741  const array<uint16_t, 2> arr = {{ addr, uint16_t(th[i]) }};
742  PostCmd(arr, FTM::kCmdWrite, FTM::kCmdRegister);
743  PostCmd(FTM::kCmdConfigFTU, (i/40) | (((i/4)%10)<<8));
744  }
745 
746  //CmdGetRegister(addr);
747  CmdReqStatDat();
748 
749  return true;
750  }
751 
752  bool SetAllThresholds(const int32_t *th)
753  {
754  for (int i=0; i<FTM::StaticData::kMaxPatchIdx; i++)
755  if (th[i]<0 || th[i]>FTM::StaticData::kMaxDAC)
756  return false;
757 
758  FTM::StaticData data(fBufStaticData);
759 
760  for (int i=0; i<=FTM::StaticData::kMaxPatchIdx; i++)
761  data[i/4].fDAC[i%4] = th[i];
762 
763  CmdSendStatDat(data);
764 
765  return true;
766  }
767 
768  bool SetNoutof4(int32_t patch, int32_t value)
769  {
771  return false;
772 
773  if (value<0 || value>FTM::StaticData::kMaxDAC)
774  return false;
775 
776  if (patch<0)
777  {
778  FTM::StaticData data(fBufStaticData);
779 
780  bool ident = true;
781  for (int i=0; i<FTM::StaticData::kMaxMultiplicity; i++)
782  if (data[i].fDAC[4] != value)
783  {
784  ident = false;
785  break;
786  }
787 
788  if (ident)
789  return true;
790 
791  for (int i=0; i<=FTM::StaticData::kMaxMultiplicity; i++)
792  data[i].fDAC[4] = value;
793 
794  // Maybe move to a "COMMIT" command?
795  CmdSendStatDat(data);
796 
797  return true;
798  }
799 
800  /*
801  if (data[patch/4].fDAC[patch%4] == value)
802  return true;
803 
804  data[patch/4].fDAC[patch%4] = value;
805 
806  CmdSendStatDat(data);
807  return true;
808  */
809 
810  // Calculate offset in static data block
811  const uint16_t addr = (uintptr_t(&fStaticData[patch].fDAC[4])-uintptr_t(&fStaticData))/2;
812 
813  // From CmdSetRegister
814  const array<uint16_t, 2> data = {{ addr, uint16_t(value) }};
815  PostCmd(data, FTM::kCmdWrite, FTM::kCmdRegister);
816 
817  reinterpret_cast<uint16_t*>(&fBufStaticData)[addr] = value;
818 
819  // Now execute change before the static data is requested back
820  PostCmd(FTM::kCmdConfigFTU, (patch/40) | (((patch/4)%10)<<8));
821 
822  //CmdGetRegister(addr);
823  CmdReqStatDat();
824 
825  return true;
826  }
827 
828  bool SetPrescaling(uint32_t value)
829  {
830  if (value>0xffff)
831  return false;
832 
833  FTM::StaticData data(fBufStaticData);
834 
835  bool ident = true;
836  for (int i=0; i<40; i++)
837  if (data[i].fPrescaling != value)
838  {
839  ident = false;
840  break;
841  }
842 
843  if (ident)
844  return true;
845 
846  data.SetPrescaling(value);
847 
848  // Maybe move to a "COMMIT" command?
849  CmdSendStatDat(data);
850 
851  return true;
852  }
853 
854  bool EnableFTU(int32_t board, bool enable)
855  {
856  if (board>39)
857  return false;
858 
859  FTM::StaticData data(fBufStaticData);
860 
861  if (board<0)
862  {
863  if (enable)
864  data.EnableAllFTU();
865  else
866  data.DisableAllFTU();
867  }
868  else
869  {
870  if (enable)
871  data.EnableFTU(board);
872  else
873  data.DisableFTU(board);
874 
875  }
876 
877  // Maybe move to a "COMMIT" command?
878  CmdSendStatDat(data);
879 
880  return true;
881  }
882 
883  bool ToggleFTU(uint32_t board)
884  {
885  if (board>39)
886  return false;
887 
888  FTM::StaticData data(fBufStaticData);
889 
890  data.ToggleFTU(board);
891 
892  // Maybe move to a "COMMIT" command?
893  CmdSendStatDat(data);
894 
895  return true;
896  }
897 
898  bool SetVal(uint16_t *dest, uint32_t val, uint32_t max)
899  {
900  if (val>max)
901  return false;
902 
903  if (*dest==val)
904  return true;
905 
906  FTM::StaticData data(fBufStaticData);
907 
908  dest = reinterpret_cast<uint16_t*>(&data) + (dest - reinterpret_cast<uint16_t*>(&fStaticData));
909 
910  *dest = val;
911 
912  CmdSendStatDat(data);
913 
914  return true;
915  }
916 
917  bool SetTriggerInterval(uint32_t val)
918  {
919  return SetVal(&fStaticData.fTriggerInterval, val,
921  }
922 
923  bool SetTriggerDelay(uint32_t val)
924  {
925  return SetVal(&fStaticData.fDelayTrigger, val,
927  }
928 
929  bool SetTimeMarkerDelay(uint32_t val)
930  {
931  return SetVal(&fStaticData.fDelayTimeMarker, val,
933  }
934 
935  bool SetDeadTime(uint32_t val)
936  {
937  return SetVal(&fStaticData.fDeadTime, val,
939  }
940 
942  {
943  //if (fStaticData.IsEnabled(type)==enable)
944  // return;
945 
946  FTM::StaticData data(fBufStaticData);
947  data.Enable(type, enable);
948  CmdSendStatDat(data);
949  }
950 
951  bool SetTriggerSeq(const uint16_t d[3])
952  {
956  return false;
957 
958  FTM::StaticData data(fBufStaticData);
959 
960  /*
961  data.Enable(FTM::StaticData::kPedestal, d[0]>0);
962  data.Enable(FTM::StaticData::kLPext, d[1]>0);
963  data.Enable(FTM::StaticData::kLPint, d[2]>0);
964  */
965 
966  data.SetSequence(d[0], d[2], d[1]);
967 
968  //if (fStaticData.fTriggerSeq !=data.fTriggerSequence ||
969  // fStaticData.fGeneralSettings!=data.fGeneralSettings)
970  // CmdSendStatDat(data);
971 
972  CmdSendStatDat(data);
973 
974  return true;
975  }
976 
977  bool SetTriggerMultiplicity(uint16_t n)
978  {
979  if (n==0 || n>FTM::StaticData::kMaxMultiplicity)
980  return false;
981 
982  //if (n==fBufStaticData.fMultiplicityPhysics)
983  // return true;
984 
985  FTM::StaticData data(fBufStaticData);
986 
987  data.fMultiplicityPhysics = n;
988 
989  CmdSendStatDat(data);
990 
991  return true;
992  }
993 
994  bool SetTriggerWindow(uint16_t win)
995  {
997  return false;
998 
999  //if (win==fStaticData.fWindowPhysics)
1000  // return true;
1001 
1002  FTM::StaticData data(fBufStaticData);
1003 
1004  data.fWindowPhysics = win;
1005 
1006  CmdSendStatDat(data);
1007 
1008  return true;
1009  }
1010 
1011  bool SetCalibMultiplicity(uint16_t n)
1012  {
1013  if (n==0 || n>FTM::StaticData::kMaxMultiplicity)
1014  return false;
1015 
1016  //if (n==fStaticData.fMultiplicityCalib)
1017  // return true;
1018 
1019  FTM::StaticData data(fBufStaticData);
1020 
1021  data.fMultiplicityCalib = n;
1022 
1023  CmdSendStatDat(data);
1024 
1025  return true;
1026  }
1027 
1028  bool SetCalibWindow(uint16_t win)
1029  {
1031  return false;
1032 
1033  //if (win==fStaticData.fWindowCalib)
1034  // return true;
1035 
1036  FTM::StaticData data(fBufStaticData);
1037 
1038  data.fWindowCalib = win;
1039 
1040  CmdSendStatDat(data);
1041 
1042  return true;
1043  }
1044 
1045  bool SetClockRegister(const uint64_t reg[])
1046  {
1047  FTM::StaticData data(fBufStaticData);
1048 
1049  for (int i=0; i<8; i++)
1050  if (reg[i]>0xffffffff)
1051  return false;
1052 
1053  data.SetClockRegister(reg);
1054 
1055  CmdSendStatDat(data);
1056 
1057  return true;
1058  }
1059 
1061  {
1063  return false;
1064 
1065  FTM::StaticData data(fBufStaticData);
1066 
1067  if (lp==FTM::StaticData::kLPint)
1068  data.EnableLPint(group, enable);
1069 
1070  if (lp==FTM::StaticData::kLPext)
1071  data.EnableLPext(group, enable);
1072 
1073  CmdSendStatDat(data);
1074 
1075  return true;
1076  }
1077 
1078  bool SetIntensity(FTM::StaticData::GeneralSettings lp, uint16_t intensity)
1079  {
1080  if (intensity>FTM::StaticData::kMaxIntensity)
1081  return false;
1082 
1084  return false;
1085 
1086  FTM::StaticData data(fBufStaticData);
1087 
1088  if (lp==FTM::StaticData::kLPint)
1089  data.fIntensityLPint = intensity;
1090 
1091  if (lp==FTM::StaticData::kLPext)
1092  data.fIntensityLPext = intensity;
1093 
1094  CmdSendStatDat(data);
1095 
1096  return true;
1097  }
1098 
1099  bool EnablePixel(int16_t idx, bool enable)
1100  {
1101  if (idx<-1 || idx>FTM::StaticData::kMaxPixelIdx)
1102  return false;
1103 
1104  if (idx==-1)
1105  {
1106  FTM::StaticData data(fBufStaticData);
1107 
1108  for (int i=0; i<=FTM::StaticData::kMaxPixelIdx; i++)
1109  data.EnablePixel(i, enable);
1110 
1111  CmdSendStatDat(data);
1112 
1113  return true;
1114  }
1115 
1116  /*
1117  data.EnablePixel(idx, enable);
1118  CmdSendStatDat(data);
1119  return true;
1120  */
1121 
1122  FTM::StaticData data(fBufStaticData);
1123 
1124  const uintptr_t base = uintptr_t(&data);
1125  const uint16_t *mem = data.EnablePixel(idx, enable);
1126 
1127  // Calculate offset in static data block
1128  const uint16_t addr = (uintptr_t(mem)-base)/2;
1129 
1130  // From CmdSetRegister
1131  const array<uint16_t, 2> cmd = {{ addr, *mem }};
1132  PostCmd(cmd, FTM::kCmdWrite, FTM::kCmdRegister);
1133 
1134  reinterpret_cast<uint16_t*>(&fBufStaticData)[addr] = *mem;
1135 
1136  // Now execute change before the static data is requested back
1137  PostCmd(FTM::kCmdConfigFTU, (idx/360) | (((idx/36)%10)<<8));
1138 
1139  // Now request the register back to ensure consistency
1140  //CmdGetRegister(addr);
1141  CmdReqStatDat();
1142 
1143  return true;
1144  }
1145 
1146  bool DisableAllPixelsExcept(uint16_t idx)
1147  {
1149  return false;
1150 
1151  FTM::StaticData data(fBufStaticData);
1152 
1153  for (int i=0; i<=FTM::StaticData::kMaxPixelIdx; i++)
1154  data.EnablePixel(i, i==idx);
1155 
1156  CmdSendStatDat(data);
1157 
1158  return true;
1159  }
1160 
1161  bool DisableAllPatchesExcept(int16_t idx)
1162  {
1164  return false;
1165 
1166  FTM::StaticData data(fBufStaticData);
1167 
1168  for (int i=0; i<=FTM::StaticData::kMaxPixelIdx; i++)
1169  data.EnablePixel(i, i/9==idx);
1170 
1171  CmdSendStatDat(data);
1172 
1173  return true;
1174  }
1175 
1176  bool EnablePatch(int16_t idx, bool enable)
1177  {
1179  return false;
1180 
1181  FTM::StaticData data(fBufStaticData);
1182 
1183  for (int i=0; i<=FTM::StaticData::kMaxPixelIdx; i++)
1184  if (i/9==idx)
1185  data.EnablePixel(i, enable);
1186 
1187  CmdSendStatDat(data);
1188 
1189  return true;
1190  }
1191 
1192  bool TogglePixel(uint16_t idx)
1193  {
1195  return false;
1196 
1197  FTM::StaticData data(fBufStaticData);
1198 
1199  data.EnablePixel(idx, !fBufStaticData.Enabled(idx));
1200 
1201  CmdSendStatDat(data);
1202 
1203  return true;
1204  }
1205 
1207  {
1208  if (!IsConnected())
1209  return kDisconnected; // rc=1
1210 
1211  switch (fHeader.fState&FTM::kFtmStates)
1212  {
1213  case FTM::kFtmUndefined: // 0
1214  return fBufStaticData.valid() ? kConnected : kDisconnected; // rc=2
1215 
1216  case FTM::kFtmRunning: // 3
1217  case FTM::kFtmCalib: // 4
1218  return kTriggerOn; // rc=4
1219 
1220  case FTM::kFtmIdle: // 1
1221  case FTM::kFtmConfig: // 2 // rc=7 // rc=3
1222  return fStaticData == fBufStaticData ? kConfigured : kIdle;
1223  }
1224 
1225  throw runtime_error("ConnectionFTM::GetState - Impossible code reached.");
1226  }
1227 
1228  // If fState==2, the clock conditioner will always be reported as unlocked
1229  //bool IsLocked() const { return fHeader.fState&FTM::kFtmLocked; }
1230 
1231  uint32_t GetCounter(FTM::Types type) { return fCounter[type]; }
1232 
1233  const FTM::StaticData &GetStaticData() const { return fStaticData; }
1234 };
1235 
1236 //const uint16_t ConnectionFTM::kMaxAddr = 0xfff;
1237 
1238 // ------------------------------------------------------------------------
1239 
1240 #include "DimDescriptionService.h"
1241 
1243 {
1244 private:
1245 
1253 
1254  uint64_t fTimeStamp;
1255  uint64_t fTimeStampOn;
1257  uint64_t fPrevState;
1258 
1260  {
1262 
1263  const FTM::DimPassport data(fHeader);
1264  fDimPassport.Update(data);
1265  }
1266 
1267  /*
1268  void UpdateHeader()
1269  {
1270  ConnectionFTM::UpdateHeader();
1271 
1272  if (fHeader.fType!=FTM::kDynamicData)
1273  return;
1274 
1275  const FTM::DimTriggerCounter data(fHeader);
1276  fDimTriggerCounter.Update(data);
1277  }*/
1278 
1280  {
1282 
1283  const FTM::DimFtuList data(fHeader, fFtuList);
1284  fDimFtuList.Update(data);
1285  }
1286 
1288  {
1290 
1291  const FTM::DimStaticData data(fHeader, fStaticData);
1292  fDimStaticData.setQuality(fHeader.fState);
1293  fDimStaticData.Update(data);
1294  }
1295 
1297  {
1299 
1300  const FTM::DimDynamicData data(fHeader, fDynamicData, fStaticData);
1301  fDimDynamicData.setQuality(fHeader.fState);
1302  fDimDynamicData.Update(data);
1303 
1304  uint64_t odiff = fDynamicData.fOnTimeCounter;
1305  uint32_t cdiff = fHeader.fTriggerCounter;
1306  uint64_t tdiff = fHeader.fTimeStamp;
1307 
1308  // The easiest way to detect whether the counters have been
1309  // reset or not is to detect a state change, because with
1310  // every state change they are reset. However, there are cases
1311  // when the trigger is switched on already (data run) and
1312  // the trigger is turned off ans switched on again within
1313  // a very short time, that the state of the previous and the
1314  // new report is the same. So in addition we have to check
1315  // for other indications. Any counter decreasing is a hint.
1316  // None of them should ever decrease. So all three are checked.
1317  const uint8_t state = fHeader.fState & FTM::States::kFtmStates;
1318 
1319  const bool first = state!=fPrevState ||
1320  fHeader.fTimeStamp<fTimeStamp ||
1321  fHeader.fTriggerCounter<fTriggerCounter ||
1322  fDynamicData.fOnTimeCounter<fTimeStampOn;
1323 
1324  if (!first)
1325  {
1326  tdiff -= fTimeStamp;
1327  odiff -= fTimeStampOn;
1328  cdiff -= fTriggerCounter;
1329  }
1330 
1331  // The observation time calculated in the first report is most likely
1332  // too large because the previous report is taken as reference,
1333  // but this is the best what could be done.
1334  const float rate = tdiff==0 ? 0 : 1e6*cdiff/tdiff;
1335 
1336  fTimeStamp = fHeader.fTimeStamp;
1337  fTimeStampOn = fDynamicData.fOnTimeCounter;
1338  fTriggerCounter = fHeader.fTriggerCounter;
1339  fPrevState = state;
1340 
1341  const FTM::DimTriggerRates rates(fHeader, fDynamicData, fStaticData,
1342  rate, tdiff*1e-6, odiff*1e-6);
1343 
1344  fDimTriggerRates.setQuality(fHeader.fState);
1345  fDimTriggerRates.Update(rates);
1346  }
1347 
1349  {
1351 
1352  const FTM::DimError data(fHeader, fError);
1353  fDimError.Update(data);
1354  }
1355 
1357  {
1359 
1360  const uint32_t counter[6] =
1361  {
1362  fCounter[FTM::kHeader],
1363  fCounter[FTM::kStaticData],
1364  fCounter[FTM::kDynamicData],
1365  fCounter[FTM::kFtuList],
1366  fCounter[FTM::kErrorList],
1367  fCounter[FTM::kRegister],
1368  };
1369 
1370  fDimCounter.setQuality(fHeader.fState);
1371  fDimCounter.Update(counter);
1372  }
1373 
1374 public:
1375  ConnectionDimFTM(ba::io_service& ioservice, MessageImp &imp) :
1376  ConnectionFTM(ioservice, imp),
1377  fDimPassport ("FTM_CONTROL/PASSPORT", "X:1;S:1",
1378  "Info about the FTM and FPGA version"
1379  "|BoardId[int]:BoardId, hexCode"
1380  "|DNA[int]:DNA of the FTM board"),
1381  fDimTriggerRates ("FTM_CONTROL/TRIGGER_RATES", "X:1;X:1;I:1;F:1;F:40;F:160;F:1;F:1",
1382  "Patch,Board,Camera trigger rates"
1383  "|FTMtimeStamp[us]:Time in microseconds, since trigger enabled or disabled"
1384  "|OnTimeCounter[us]:Effective on-time, ie. FTM triggers (eg. w/o busy)"
1385  "|TriggerCounter[int]:Counter of triggers since enabled or disabled"
1386  "|TriggerRate[Hz]:Trigger rate"
1387  "|BoardRate[Hz]:Trigger rate of individual FTUs"
1388  "|PatchRate[Hz]:Trigger rate of individual patches"
1389  "|ElapsedTime[s]:Time elapsed since previous report"
1390  "|OnTime[s]:OnTime elapsed since previous report"),
1391  fDimError ("FTM_CONTROL/ERROR", "X:1;S:1;S:28", ""),
1392  fDimFtuList ("FTM_CONTROL/FTU_LIST", "X:1;X:1;S:1;C:4;X:40;C:40;C:40",
1393  "Logs the changes of status of the FTUs"
1394  "|FTMtimeStamp[us]:Time in microseconds"
1395  "|ActiveFTU[bitpattern]:Description of enabled FTUs"
1396  "|NumBoards[int]:Total number of enabled FTUs"
1397  "|NumBoardsCrate[int]:Total number of enabled FTUs per crate"
1398  "|DNA[hexCode]:Hex code identifier of FTUs"
1399  "|Addr[bitpattern]:Crate address (hardware) of FTUs"
1400  "|Ping[int]:Number of pings until FTU response"),
1401  fDimStaticData ("FTM_CONTROL/STATIC_DATA", "X:1;S:1;S:1;X:1;S:1;S:3;C:4;S:1;S:1;S:1;S:1;S:1;S:1;I:1;I:8;S:90;S:160;S:40;S:40",
1402  "Configuration of FTM and FTUs"
1403  "|FTMtimeStamp[us]:Time in microseconds, since trigger enabled or disabled"
1404  "|GeneralSettings[bitpattern]:Status of the FTM settings (cf. FTM doc)"
1405  "|LEDStatus[bitpattern]:Not Used"
1406  "|ActiveFTU[bitpattern]:List of enabled FTUs"
1407  "|TriggerInterval[bitpattern]:Period of cal. and ped. events (cf. FTM doc)"
1408  "|TriggerSeq[int]:Sequence of calib. and pedestal events (LPint, LPext, Ped)"
1409  "|LPSettings[bitpattern]:Settings of LP, enabled int, ext, intensity int, ext"
1410  "|PhysTrigMult[int]:N for N out of 40 logic on FTM (Physics)"
1411  "|CalibTrigMult[int]: N for N out of 40 logic on FTM (Calib)"
1412  "|PhysTrigWindow[ns]:Coincidence window for N out of 40 (Physics)"
1413  "|CalibTrigWindow[ns]:Coincidence window for N out of 40 (Calib)"
1414  "|TrigDelay[ns]:Trigger delay applied on FTM"
1415  "|TMDelay[ns]:TM delay applied on FTM"
1416  "|DeadTime[ns]:Dead time applied after each event on the FTM"
1417  "|ClkCond[bitpattern]:Clock conditionner settings on the FTM (DRS sampling freq.)"
1418  "|PixEnabled[bitpattern]:Enabled pixels, pckd in 90 shorts (160*9bits=180bytes)"
1419  "|PatchThresh[DACcounts]:Threshold of the trigger patches"
1420  "|Multiplicity[DACcounts]:N out of 4 logic settings per FTU"
1421  "|Prescaling[500ms]:Update rate of the rate counter"),
1422  fDimDynamicData ("FTM_CONTROL/DYNAMIC_DATA", "X:1;X:1;F:4;I:160;I:40;S:40;S:40;S:40;S:1",
1423  "Regular reports sent by FTM"
1424  "|FTMtimeStamp[us]:Time in microseconds, since trigger enabled or disabled"
1425  "|OnTimeCounter[us]:Ontime, i.e. FTM processes triggers (e.g. No FAD busy)"
1426  "|Temperatures[Nan]:not yet defined nor used (wanna be FTM onboard temps)"
1427  "|TriggerPatchCounter[int]:counting since last update (prescaling)"
1428  "|BoardsCounter[int]:FTU board counting after N out of 4 and since last update"
1429  "|RateOverflow[bitpattern]:bits 0-4=patches overflow, 5=board overflow, 1 per board"
1430  "|Prescaling[500ms]:Update rate of the rate counter"
1431  "|CrcError[int]:Number of checksum error in RS485 communication"
1432  "|State[int]:State value of the FTM firmware (cf. FTM doc)"),
1433  fDimCounter ("FTM_CONTROL/COUNTER", "I:1;I:1;I:1;I:1;I:1;I:1",
1434  "Communication statistics to or from FTM control and FTM"
1435  "|NumHeaders[int]:Num. of headers (any header) received by ftm control"
1436  "|NumStaticData[int]:Num. of static data blocks (ftm and ftu settings)"
1437  "|NumDynamicData[int]:Num. of dynamic data blocks (e.g. rates)"
1438  "|NumFtuList[int]:Num. of FTU list (FTU identifiers, answer from ping)"
1439  "|NumErrors[int]:Num. of error messages"
1440  "|NumRegister[int]:Num. of answers from a single register accesess"),
1441  fTimeStamp(0), fTimeStampOn(0), fTriggerCounter(0), fPrevState(0)
1442  {
1443  }
1444 
1445  // A B [C] [D] E [F] G H [I] J K [L] M N O P Q R [S] T U V W [X] Y Z
1446 };
1447 
1448 // ------------------------------------------------------------------------
1449 
1450 template <class T, class S>
1452 {
1453  int Wrap(function<void()> f)
1454  {
1455  f();
1456  return T::GetCurrentState();
1457  }
1458 
1459  function<int(const EventImp &)> Wrapper(function<void()> func)
1460  {
1461  return bind(&StateMachineFTM::Wrap, this, func);
1462  }
1463 
1464 private:
1465  S fFTM;
1466 
1467  bool CheckEventSize(size_t has, const char *name, size_t size)
1468  {
1469  if (has==size)
1470  return true;
1471 
1472  ostringstream msg;
1473  msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
1474  T::Fatal(msg);
1475  return false;
1476  }
1477 
1478  int SetRegister(const EventImp &evt)
1479  {
1480  if (!CheckEventSize(evt.GetSize(), "SetRegister", 8))
1481  return T::kSM_FatalError;
1482 
1483  const uint32_t *dat = evt.Ptr<uint32_t>();
1484 
1485  if (dat[1]>uint16_t(-1))
1486  {
1487  ostringstream msg;
1488  msg << hex << "Value " << dat[1] << " out of range.";
1489  T::Error(msg);
1490  return T::GetCurrentState();
1491  }
1492 
1493 
1494  if (dat[0]>uint16_t(-1) || !fFTM.CmdSetRegister(dat[0], dat[1]))
1495  {
1496  ostringstream msg;
1497  msg << hex << "Address " << dat[0] << " out of range.";
1498  T::Error(msg);
1499  }
1500 
1501  return T::GetCurrentState();
1502  }
1503 
1504  int GetRegister(const EventImp &evt)
1505  {
1506  if (!CheckEventSize(evt.GetSize(), "GetRegister", 4))
1507  return T::kSM_FatalError;
1508 
1509  const unsigned int addr = evt.GetInt();
1510  if (addr>uint16_t(-1) || !fFTM.CmdGetRegister(addr))
1511  {
1512  ostringstream msg;
1513  msg << hex << "Address " << addr << " out of range.";
1514  T::Error(msg);
1515  }
1516 
1517  return T::GetCurrentState();
1518  }
1519 
1520  int StartRun()
1521  {
1522  // This is a workaround... it seems that the FTM ignored the 'trigger on'
1523  // as long as it is still sending thresholds to the FTUs (and it seems
1524  // that this is the only command/confguration) which gets ignored.
1525  // So if we are configuring, we resent this command until we got a
1526  // reasonable answer (TriggerOn) back from the FTM.
1527  // There is no need to send the command here, because Execute
1528  // will be called immediately after this anyway before any
1529  // answer could be processed. So it would just guarantee that
1530  // the command is sent twice for no reason.
1531 
1532  fFTM.CmdStartRun();
1533 
1534  if (T::GetCurrentState()!=FTM::State::kConfigured1)
1535  return T::GetCurrentState();
1536 
1537  fCounterReg = fFTM.GetCounter(FTM::kRegister);
1538  return FTM::State::kConfigured2;
1539  }
1540 
1541  int TakeNevents(const EventImp &evt)
1542  {
1543  if (!CheckEventSize(evt.GetSize(), "TakeNevents", 4))
1544  return T::kSM_FatalError;
1545 
1546  const unsigned int dat = evt.GetUInt();
1547 
1548  /*
1549  if (dat[1]>uint32_t(-1))
1550  {
1551  ostringstream msg;
1552  msg << hex << "Value " << dat[1] << " out of range.";
1553  T::Error(msg);
1554  return T::GetCurrentState();
1555  }*/
1556 
1557  fFTM.CmdTakeNevents(dat);
1558 
1559  return T::GetCurrentState();
1560  }
1561 
1562  int DisableReports(const EventImp &evt)
1563  {
1564  if (!CheckEventSize(evt.GetSize(), "DisableReports", 1))
1565  return T::kSM_FatalError;
1566 
1567  fFTM.CmdDisableReports(evt.GetBool());
1568 
1569  return T::GetCurrentState();
1570  }
1571 
1572  int SetVerbosity(const EventImp &evt)
1573  {
1574  if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
1575  return T::kSM_FatalError;
1576 
1577  fFTM.SetVerbose(evt.GetBool());
1578 
1579  return T::GetCurrentState();
1580  }
1581 
1582  int SetHexOutput(const EventImp &evt)
1583  {
1584  if (!CheckEventSize(evt.GetSize(), "SetHexOutput", 1))
1585  return T::kSM_FatalError;
1586 
1587  fFTM.SetHexOutput(evt.GetBool());
1588 
1589  return T::GetCurrentState();
1590  }
1591 
1592  int SetDynamicOut(const EventImp &evt)
1593  {
1594  if (!CheckEventSize(evt.GetSize(), "SetDynamicOut", 1))
1595  return T::kSM_FatalError;
1596 
1597  fFTM.SetDynamicOut(evt.GetBool());
1598 
1599  return T::GetCurrentState();
1600  }
1601 
1602  int LoadStaticData(const EventImp &evt)
1603  {
1604  if (fFTM.LoadStaticData(evt.GetString()))
1605  return T::GetCurrentState();
1606 
1607  ostringstream msg;
1608  msg << "Loading static data from file '" << evt.GetString() << "' failed ";
1609 
1610  if (errno)
1611  msg << "(" << strerror(errno) << ")";
1612  else
1613  msg << "(wrong size, expected " << sizeof(FTM::StaticData) << " bytes)";
1614 
1615  T::Warn(msg);
1616 
1617  return T::GetCurrentState();
1618  }
1619 
1620  int SaveStaticData(const EventImp &evt)
1621  {
1622  if (fFTM.SaveStaticData(evt.GetString()))
1623  return T::GetCurrentState();
1624 
1625  ostringstream msg;
1626  msg << "Writing static data to file '" << evt.GetString() << "' failed ";
1627  msg << "(" << strerror(errno) << ")";
1628 
1629  T::Warn(msg);
1630 
1631  return T::GetCurrentState();
1632  }
1633 
1634  int SetThreshold(const EventImp &evt)
1635  {
1636  if (!CheckEventSize(evt.GetSize(), "SetThreshold", 8))
1637  return T::kSM_FatalError;
1638 
1639  const int32_t *data = evt.Ptr<int32_t>();
1640 
1641  if (!fFTM.SetThreshold(data[0], data[1]))
1642  {
1643  ostringstream msg;
1644  msg << "SetThreshold - Maximum allowed patch number 159, valid value range 0-0xffff (got: " << data[0] << " " << data[1] << ")";
1645  T::Warn(msg);
1646  }
1647 
1648  return T::GetCurrentState();
1649  }
1650 
1652  {
1653  if (!CheckEventSize(evt.GetSize(), "SetSelectedThresholds", 160*4))
1654  return T::kSM_FatalError;
1655 
1656  const int32_t *data = evt.Ptr<int32_t>();
1657  if (!fFTM.SetSelectedThresholds(data))
1658  {
1659  ostringstream msg;
1660  msg << "SetSelectedThresholds - Value out of range, maximum 0xffff.";
1661  T::Warn(msg);
1662  }
1663 
1664  return T::GetCurrentState();
1665  }
1666 
1667  int SetAllThresholds(const EventImp &evt)
1668  {
1669  if (!CheckEventSize(evt.GetSize(), "SetAllThresholds", 160*4))
1670  return T::kSM_FatalError;
1671 
1672  const int32_t *data = evt.Ptr<int32_t>();
1673  if (!fFTM.SetAllThresholds(data))
1674  {
1675  ostringstream msg;
1676  msg << "SetAllThresholds - Value out of range [0; 0xffff]";
1677  T::Warn(msg);
1678  }
1679 
1680  return T::GetCurrentState();
1681  }
1682 
1683  int SetNoutof4(const EventImp &evt)
1684  {
1685  if (!CheckEventSize(evt.GetSize(), "SetNoutof4", 8))
1686  return T::kSM_FatalError;
1687 
1688  const int32_t *data = evt.Ptr<int32_t>();
1689 
1690  if (!fFTM.SetNoutof4(data[0], data[1]))
1691  T::Warn("SetNoutof4 - Maximum allowed board number 39, valid value range 0-0xffff");
1692 
1693  return T::GetCurrentState();
1694  }
1695 
1696  int EnableFTU(const EventImp &evt)
1697  {
1698  if (!CheckEventSize(evt.GetSize(), "EnableFTU", 5))
1699  return T::kSM_FatalError;
1700 
1701  const int32_t &board = evt.Get<int32_t>();
1702  const int8_t &enable = evt.Get<int8_t>(4);
1703 
1704  if (!fFTM.EnableFTU(board, enable))
1705  T::Warn("EnableFTU - Board number must be <40.");
1706 
1707  return T::GetCurrentState();
1708  }
1709 
1710  int ToggleFTU(const EventImp &evt)
1711  {
1712  if (!CheckEventSize(evt.GetSize(), "ToggleFTU", 4))
1713  return T::kSM_FatalError;
1714 
1715  if (!fFTM.ToggleFTU(evt.GetInt()))
1716  T::Warn("ToggleFTU - Allowed range of boards 0-39.");
1717 
1718  return T::GetCurrentState();
1719  }
1720 
1722  {
1723  if (!CheckEventSize(evt.GetSize(), "SetTriggerInterval", 4))
1724  return T::kSM_FatalError;
1725 
1726  if (!fFTM.SetTriggerInterval(evt.GetInt()))
1727  T::Warn("SetTriggerInterval - Value out of range.");
1728 
1729  return T::GetCurrentState();
1730  }
1731 
1732  int SetTriggerDelay(const EventImp &evt)
1733  {
1734  if (!CheckEventSize(evt.GetSize(), "SetTriggerDelay", 4))
1735  return T::kSM_FatalError;
1736 
1737  if (!fFTM.SetTriggerDelay(evt.GetInt()))
1738  T::Warn("SetTriggerDealy - Value out of range.");
1739 
1740  return T::GetCurrentState();
1741  }
1742 
1744  {
1745  if (!CheckEventSize(evt.GetSize(), "SetTimeMarkerDelay", 4))
1746  return T::kSM_FatalError;
1747 
1748  if (!fFTM.SetTimeMarkerDelay(evt.GetInt()))
1749  T::Warn("SetTimeMarkerDelay - Value out of range.");
1750 
1751  return T::GetCurrentState();
1752  }
1753 
1754  int SetPrescaling(const EventImp &evt)
1755  {
1756  if (!CheckEventSize(evt.GetSize(), "SetPrescaling", 4))
1757  return T::kSM_FatalError;
1758 
1759  if (!fFTM.SetPrescaling(evt.GetInt()-1))
1760  T::Warn("SetPrescaling - Value out of range.");
1761 
1762  return T::GetCurrentState();
1763  }
1764 
1765  int SetTriggerSeq(const EventImp &evt)
1766  {
1767  if (!CheckEventSize(evt.GetSize(), "SetTriggerSeq", 6))
1768  return T::kSM_FatalError;
1769 
1770  const uint16_t *data = evt.Ptr<uint16_t>();
1771 
1772  if (!fFTM.SetTriggerSeq(data))
1773  T::Warn("SetTriggerSeq - Value out of range.");
1774 
1775  return T::GetCurrentState();
1776  }
1777 
1778  int SetDeadTime(const EventImp &evt)
1779  {
1780  if (!CheckEventSize(evt.GetSize(), "SetDeadTime", 4))
1781  return T::kSM_FatalError;
1782 
1783  if (!fFTM.SetDeadTime(evt.GetInt()))
1784  T::Warn("SetDeadTime - Value out of range.");
1785 
1786  return T::GetCurrentState();
1787  }
1788 
1790  {
1791  if (!CheckEventSize(evt.GetSize(), "SetTriggerMultiplicity", 2))
1792  return T::kSM_FatalError;
1793 
1794  if (!fFTM.SetTriggerMultiplicity(evt.GetUShort()))
1795  T::Warn("SetTriggerMultiplicity - Value out of range.");
1796 
1797  return T::GetCurrentState();
1798  }
1799 
1801  {
1802  if (!CheckEventSize(evt.GetSize(), "SetCalibMultiplicity", 2))
1803  return T::kSM_FatalError;
1804 
1805  if (!fFTM.SetCalibMultiplicity(evt.GetUShort()))
1806  T::Warn("SetCalibMultiplicity - Value out of range.");
1807 
1808  return T::GetCurrentState();
1809  }
1810 
1811  int SetTriggerWindow(const EventImp &evt)
1812  {
1813  if (!CheckEventSize(evt.GetSize(), "SetTriggerWindow", 2))
1814  return T::kSM_FatalError;
1815 
1816  if (!fFTM.SetTriggerWindow(evt.GetUShort()))
1817  T::Warn("SetTriggerWindow - Value out of range.");
1818 
1819  return T::GetCurrentState();
1820  }
1821 
1822  int SetCalibWindow(const EventImp &evt)
1823  {
1824  if (!CheckEventSize(evt.GetSize(), "SetCalibWindow", 2))
1825  return T::kSM_FatalError;
1826 
1827  if (!fFTM.SetCalibWindow(evt.GetUShort()))
1828  T::Warn("SetCalibWindow - Value out of range.");
1829 
1830  return T::GetCurrentState();
1831  }
1832 
1833  int SetClockRegister(const EventImp &evt)
1834  {
1835  if (!CheckEventSize(evt.GetSize(), "SetClockRegister", 8*8))
1836  return T::kSM_FatalError;
1837 
1838  const uint64_t *reg = evt.Ptr<uint64_t>();
1839 
1840  if (!fFTM.SetClockRegister(reg))
1841  T::Warn("SetClockRegister - Value out of range.");
1842 
1843  return T::GetCurrentState();
1844  }
1845 
1846  int SetClockFrequency(const EventImp &evt)
1847  {
1848  if (!CheckEventSize(evt.GetSize(), "SetClockFrequency", 2))
1849  return T::kSM_FatalError;
1850 
1851  const map<uint16_t,array<uint64_t, 8>>::const_iterator it =
1852  fClockCondSetup.find(evt.GetUShort());
1853 
1854  if (it==fClockCondSetup.end())
1855  {
1856  T::Warn("SetClockFrequency - Frequency not supported.");
1857  return T::GetCurrentState();
1858  }
1859 
1860  if (!fFTM.SetClockRegister(it->second.data()))
1861  T::Warn("SetClockFrequency - Register values out of range.");
1862 
1863  return T::GetCurrentState();
1864  }
1865 
1867  {
1868  if (!CheckEventSize(evt.GetSize(), "EnableLP", 1))
1869  return T::kSM_FatalError;
1870 
1871  if (!fFTM.EnableLP(lp, group, evt.GetBool()))
1872  T::Warn("EnableLP - Invalid light pulser id.");
1873 
1874  return T::GetCurrentState();
1875  }
1876 
1878  {
1879  if (!CheckEventSize(evt.GetSize(), "SetIntensity", 2))
1880  return T::kSM_FatalError;
1881 
1882  if (!fFTM.SetIntensity(lp, evt.GetShort()))
1883  T::Warn("SetIntensity - Value out of range.");
1884 
1885  return T::GetCurrentState();
1886  }
1887 
1889  {
1890  if (!CheckEventSize(evt.GetSize(), "Enable", 1))
1891  return T::kSM_FatalError;
1892 
1893  fFTM.Enable(type, evt.GetBool());
1894 
1895  return T::GetCurrentState();
1896  }
1897 
1898  int EnablePixel(const EventImp &evt, bool b)
1899  {
1900  if (!CheckEventSize(evt.GetSize(), "EnablePixel", 2))
1901  return T::kSM_FatalError;
1902 
1903  if (!fFTM.EnablePixel(evt.GetUShort(), b))
1904  T::Warn("EnablePixel - Value out of range.");
1905 
1906  return T::GetCurrentState();
1907  }
1908 
1910  {
1911  if (!CheckEventSize(evt.GetSize(), "DisableAllPixelsExcept", 2))
1912  return T::kSM_FatalError;
1913 
1914  if (!fFTM.DisableAllPixelsExcept(evt.GetUShort()))
1915  T::Warn("DisableAllPixelsExcept - Value out of range.");
1916 
1917  return T::GetCurrentState();
1918  }
1919 
1921  {
1922  if (!CheckEventSize(evt.GetSize(), "DisableAllPatchesExcept", 2))
1923  return T::kSM_FatalError;
1924 
1925  if (!fFTM.DisableAllPatchesExcept(evt.GetUShort()))
1926  T::Warn("DisableAllPatchesExcept - Value out of range.");
1927 
1928  return T::GetCurrentState();
1929  }
1930 
1931  int EnablePatch(const EventImp &evt, bool enable)
1932  {
1933  if (!CheckEventSize(evt.GetSize(), "EnablePatch", 2))
1934  return T::kSM_FatalError;
1935 
1936  if (!fFTM.EnablePatch(evt.GetUShort(), enable))
1937  T::Warn("EnablePatch - Value out of range.");
1938 
1939  return T::GetCurrentState();
1940  }
1941 
1942  int TogglePixel(const EventImp &evt)
1943  {
1944  if (!CheckEventSize(evt.GetSize(), "TogglePixel", 2))
1945  return T::kSM_FatalError;
1946 
1947  if (!fFTM.TogglePixel(evt.GetUShort()))
1948  T::Warn("TogglePixel - Value out of range.");
1949 
1950  return T::GetCurrentState();
1951  }
1952 
1953  int ResetCrate(const EventImp &evt)
1954  {
1955  if (!CheckEventSize(evt.GetSize(), "ResetCrate", 2))
1956  return T::kSM_FatalError;
1957 
1958  fFTM.CmdResetCrate(evt.GetUShort());
1959 
1960  return T::GetCurrentState();
1961  }
1962 
1964  {
1965  // Close all connections
1966  fFTM.PostClose(false);
1967 
1968  /*
1969  // Now wait until all connection have been closed and
1970  // all pending handlers have been processed
1971  poll();
1972  */
1973 
1974  return T::GetCurrentState();
1975  }
1976 
1977  int Reconnect(const EventImp &evt)
1978  {
1979  // Close all connections to supress the warning in SetEndpoint
1980  fFTM.PostClose(false);
1981 
1982  // Now wait until all connection have been closed and
1983  // all pending handlers have been processed
1984  ba::io_service::poll();
1985 
1986  if (evt.GetBool())
1987  fFTM.SetEndpoint(evt.GetString());
1988 
1989  // Now we can reopen the connection
1990  fFTM.PostClose(true);
1991 
1992  return T::GetCurrentState();
1993  }
1994 
1995  /*
1996  int Transition(const Event &evt)
1997  {
1998  switch (evt.GetTargetState())
1999  {
2000  case kDisconnected:
2001  case kConnected:
2002  }
2003 
2004  return T::kSM_FatalError;
2005  }*/
2006 
2007  uint32_t fCounterReg;
2008  uint32_t fCounterStat;
2009 
2010  typedef map<string, FTM::StaticData> Configs;
2011  Configs fConfigs;
2012  Configs::const_iterator fTargetConfig;
2013 
2014  int ConfigureFTM(const EventImp &evt)
2015  {
2016  const string name = evt.GetText();
2017 
2018  fTargetConfig = fConfigs.find(name);
2019  if (fTargetConfig==fConfigs.end())
2020  {
2021  T::Error("ConfigureFTM - Run-type '"+name+"' not found.");
2022  return T::GetCurrentState();
2023  }
2024 
2025  T::Message("Starting configuration for '"+name+"' ["+to_string(fFTM.IsTxQueueEmpty())+"]");
2026 
2027  fCounterReg = fFTM.GetCounter(FTM::kRegister);
2028  fFTM.CmdStopRun();
2029 
2031  }
2032 
2034  {
2035  return fFTM.GetState();
2036  }
2037 
2038  int Execute()
2039  {
2040  // If FTM is neither in data taking nor idle,
2041  // leave configuration state
2042  switch (fFTM.GetState())
2043  {
2046  default:
2047  break;
2048  }
2049 
2050  // FIXME: Add timeouts and go to error state
2051  // so that a configuration error can be handled
2052  switch (T::GetCurrentState())
2053  {
2055  // If FTM has received an anwer to the stop_run command
2056  // the counter for the registers has been increased
2057  if (fFTM.GetCounter(FTM::kRegister)<=fCounterReg)
2059 
2060  // If now the state is not idle as expected this means we had
2061  // an error (maybe old events waiting in the queue)
2062  if (fFTM.GetState()!=ConnectionFTM::kIdle &&
2063  fFTM.GetState()!=ConnectionFTM::kConfigured)
2065 
2066  fCounterStat = fFTM.GetCounter(FTM::kStaticData);
2067 
2068  fFTM.CmdSendStatDat(fTargetConfig->second);
2069 
2070  T::Message("Trigger successfully disabled... sending new configuration.");
2071 
2072  // Next state is: wait for the answer to our configuration
2074 
2077  // If FTM has received an anwer to the CmdSendStatDat
2078  // the counter for static data has been increased
2079  if (fFTM.GetCounter(FTM::kStaticData)<=fCounterStat)
2080  break;
2081 
2082  // If now the configuration is not what we expected
2083  // we had an error (maybe old events waiting in the queue?)
2084  if (fFTM.GetState()!=ConnectionFTM::kConfigured)
2086 
2087  // Check configuration again when a new static data block
2088  // will be received
2089  fCounterStat = fFTM.GetCounter(FTM::kStaticData);
2090 
2091  // This is also displayed when the ratecontrol sends its configuration...
2092  if (T::GetCurrentState()==FTM::State::kConfiguring2)
2093  T::Message("Sending new configuration was successfull.");
2094  else
2095  T::Message("Configuration successfully updated.");
2096 
2097  // Next state is: wait for the answer to our configuration
2098  return FTM::State::kConfigured1;
2099 
2100  // This state is set by StartRun [START_TRIGGER]
2102  // No answer to the CmdStartRun received yet... go on waiting
2103  if (fFTM.GetCounter(FTM::kRegister)<=fCounterReg)
2104  return FTM::State::kConfigured2;
2105 
2106  // Answer received and trigger enable acknowledged
2107  if (fFTM.GetState()==ConnectionFTM::kTriggerOn)
2108  return FTM::State::kTriggerOn;
2109 
2110  // If the trigger is not enabled, but the configuration
2111  // has changed go to error state (should never happen)
2112  if (fFTM.GetState()!=ConnectionFTM::kConfigured)
2114 
2115  // Send a new command... the previous one might have gone
2116  // ignored by the ftm because it was just after a
2117  // threshold setting during the configured state
2118  fFTM.CmdStartRun(false);
2119 
2120  // Set counter to wait for answer.
2121  fCounterReg = fFTM.GetCounter(FTM::kRegister);
2122 
2123  // Go on waiting for a proper acknowledge of the trigger enable
2124  return FTM::State::kConfigured2;
2125 
2128  //case FTM::State::kConfigError3:
2129  break;
2130 
2131  default:
2132  switch (fFTM.GetState())
2133  {
2137  default:
2138  throw runtime_error("StateMachineFTM - Execute() - Inavlid state.");
2139  }
2140  }
2141 
2142  return T::GetCurrentState();
2143  }
2144 
2145 public:
2146  StateMachineFTM(ostream &out=cout) :
2147  StateMachineAsio<T>(out, "FTM_CONTROL"), fFTM(*this, *this)
2148  {
2149  // State names
2150  T::AddStateName(FTM::State::kDisconnected, "Disconnected",
2151  "FTM board not connected via ethernet.");
2152 
2153  T::AddStateName(FTM::State::kConnected, "Connected",
2154  "Ethernet connection to FTM established (no state received yet).");
2155 
2156  T::AddStateName(FTM::State::kIdle, "Idle",
2157  "Ethernet connection to FTM established, FTM in idle state.");
2158 
2159  T::AddStateName(FTM::State::kValid, "Valid",
2160  "FTM in idle state and the last sent and received static data block are bitwise identical.");
2161 
2162  T::AddStateName(FTM::State::kConfiguring1, "Configuring1",
2163  "Command to disable run sent... waiting for response.");
2164  T::AddStateName(FTM::State::kConfiguring2, "Configuring2",
2165  "New configuration sent... waiting for response.");
2166  T::AddStateName(FTM::State::kConfigured1, "Configured1",
2167  "Received answer identical with target configuration.");
2168  T::AddStateName(FTM::State::kConfigured2, "Configured2",
2169  "Waiting for acknowledge of trigger enable.");
2170 
2171  T::AddStateName(FTM::State::kTriggerOn, "TriggerOn",
2172  "Ethernet connection to FTM established, FTM trigger output to FADs enabled.");
2173 
2174  T::AddStateName(FTM::State::kConfigError1, "ErrorInConfig1", "Unexpected state received from FTM");
2175  T::AddStateName(FTM::State::kConfigError2, "ErrorInConfig2", "Unexpected state received from FTM");
2176  //T::AddStateName(FTM::State::kConfigError3, "ClockCondError", "Clock conditioner not locked");
2177 
2178  // FTM Commands
2179  T::AddEvent("TOGGLE_LED", FTM::State::kIdle, FTM::State::kValid)
2180  (Wrapper(bind(&ConnectionFTM::CmdToggleLed, &fFTM)))
2181  ("toggle led");
2182 
2183  T::AddEvent("PING", FTM::State::kIdle, FTM::State::kValid)
2184  (Wrapper(bind(&ConnectionFTM::CmdPing, &fFTM)))
2185  ("send ping");
2186 
2187  T::AddEvent("REQUEST_DYNAMIC_DATA", FTM::State::kIdle, FTM::State::kValid)
2188  (Wrapper(bind(&ConnectionFTM::CmdReqDynDat, &fFTM)))
2189  ("request transmission of dynamic data block");
2190 
2191  T::AddEvent("REQUEST_STATIC_DATA", FTM::State::kIdle, FTM::State::kValid)
2192  (Wrapper(bind(&ConnectionFTM::CmdReqStatDat, &fFTM)))
2193  ("request transmission of static data from FTM to memory");
2194 
2195  T::AddEvent("GET_REGISTER", "I", FTM::State::kIdle, FTM::State::kValid)
2196  (bind(&StateMachineFTM::GetRegister, this, placeholders::_1))
2197  ("read register from address addr"
2198  "|addr[short]:Address of register");
2199 
2200  T::AddEvent("SET_REGISTER", "I:2", FTM::State::kIdle, FTM::State::kValid)
2201  (bind(&StateMachineFTM::SetRegister, this, placeholders::_1))
2202  ("set register to value"
2203  "|addr[short]:Address of register"
2204  "|val[short]:Value to be set");
2205 
2207  (bind(&StateMachineFTM::StartRun, this))
2208  ("start a run (start distributing triggers)");
2209 
2210  T::AddEvent("STOP_TRIGGER", FTM::State::kTriggerOn)
2211  (Wrapper(bind(&ConnectionFTM::CmdStopRun, &fFTM)))
2212  ("stop a run (stop distributing triggers)");
2213 
2214  T::AddEvent("TAKE_N_EVENTS", "I", FTM::State::kIdle, FTM::State::kValid)
2215  (bind(&StateMachineFTM::TakeNevents, this, placeholders::_1))
2216  ("take n events (distribute n triggers)|number[int]:Number of events to be taken");
2217 
2218  T::AddEvent("DISABLE_REPORTS", "B", FTM::State::kIdle, FTM::State::kValid)
2219  (bind(&StateMachineFTM::DisableReports, this, placeholders::_1))
2220  ("disable sending rate reports"
2221  "|status[bool]:disable or enable that the FTM sends rate reports (yes/no)");
2222 
2224  (bind(&StateMachineFTM::SetThreshold, this, placeholders::_1))
2225  ("Set the comparator threshold"
2226  "|Patch[idx]:Index of the patch (0-159), -1 for all"
2227  "|Threshold[counts]:Threshold to be set in binary counts");
2228 
2229  T::AddEvent("SET_SELECTED_THRESHOLDS", "I:160", FTM::State::kTriggerOn)
2230  (bind(&StateMachineFTM::SetSelectedThresholds, this, placeholders::_1))
2231  ("Set the comparator thresholds. Only thresholds which are different and >=0 are sent."
2232  "|Thresholds[counts]:Threshold to be set in binary counts");
2233 
2234  T::AddEvent("SET_ALL_THRESHOLDS", "I:160", FTM::State::kIdle, FTM::State::kValid, FTM::State::kConfigured1)
2235  (bind(&StateMachineFTM::SetAllThresholds, this, placeholders::_1))
2236  ("Set the comparator thresholds"
2237  "|Thresholds[counts]:Threshold to be set in binary counts");
2238 
2239  T::AddEvent("SET_N_OUT_OF_4", "I:2", FTM::State::kIdle, FTM::State::kValid, FTM::State::kTriggerOn)
2240  (bind(&StateMachineFTM::SetNoutof4, this, placeholders::_1))
2241  ("Set the comparator threshold"
2242  "|Board[idx]:Index of the board (0-39), -1 for all"
2243  "|Threshold[counts]:Threshold to be set in binary counts");
2244 
2245  T::AddEvent("SET_PRESCALING", "I:1", FTM::State::kIdle, FTM::State::kValid)
2246  (bind(&StateMachineFTM::SetPrescaling, this, placeholders::_1))
2247  ("Sets the FTU readout time intervals"
2248  "|time[0.5s]:The interval is given in units of 0.5s, i.e. 1 means 0.5s, 2 means 1s, ...");
2249 
2250  T::AddEvent("ENABLE_FTU", "I:1;B:1", FTM::State::kIdle, FTM::State::kValid)
2251  (bind(&StateMachineFTM::EnableFTU, this, placeholders::_1))
2252  ("Enable or disable FTU"
2253  "|Board[idx]:Index of the board (0-39), -1 for all"
2254  "|Enable[bool]:Whether FTU should be enabled or disabled (yes/no)");
2255 
2256  T::AddEvent("DISABLE_PIXEL", "S:1", FTM::State::kIdle, FTM::State::kValid, FTM::State::kTriggerOn)
2257  (bind(&StateMachineFTM::EnablePixel, this, placeholders::_1, false))
2258  ("(-1 or all)");
2259 
2260  T::AddEvent("ENABLE_PIXEL", "S:1", FTM::State::kIdle, FTM::State::kValid, FTM::State::kTriggerOn)
2261  (bind(&StateMachineFTM::EnablePixel, this, placeholders::_1, true))
2262  ("(-1 or all)");
2263 
2264  T::AddEvent("DISABLE_ALL_PIXELS_EXCEPT", "S:1", FTM::State::kIdle, FTM::State::kValid)
2265  (bind(&StateMachineFTM::DisableAllPixelsExcept, this, placeholders::_1))
2266  ("");
2267 
2268  T::AddEvent("DISABLE_ALL_PATCHES_EXCEPT", "S:1", FTM::State::kIdle, FTM::State::kValid)
2269  (bind(&StateMachineFTM::DisableAllPatchesExcept, this, placeholders::_1))
2270  ("");
2271 
2272  T::AddEvent("ENABLE_PATCH", "S:1", FTM::State::kIdle, FTM::State::kValid)
2273  (bind(&StateMachineFTM::EnablePatch, this, placeholders::_1, true))
2274  ("");
2275 
2276  T::AddEvent("DISABLE_PATCH", "S:1", FTM::State::kIdle, FTM::State::kValid)
2277  (bind(&StateMachineFTM::EnablePatch, this, placeholders::_1, false))
2278  ("");
2279 
2280  T::AddEvent("TOGGLE_PIXEL", "S:1", FTM::State::kIdle, FTM::State::kValid)
2281  (bind(&StateMachineFTM::TogglePixel, this, placeholders::_1))
2282  ("");
2283 
2284  T::AddEvent("TOGGLE_FTU", "I:1", FTM::State::kIdle, FTM::State::kValid)
2285  (bind(&StateMachineFTM::ToggleFTU, this, placeholders::_1))
2286  ("Toggle status of FTU (this is mainly meant to be used in the GUI)"
2287  "|Board[idx]:Index of the board (0-39)");
2288 
2289  T::AddEvent("SET_TRIGGER_INTERVAL", "I:1", FTM::State::kIdle, FTM::State::kValid)
2290  (bind(&StateMachineFTM::SetTriggerInterval, this, placeholders::_1))
2291  ("Sets the trigger interval which is the distance between two consecutive artificial triggers."
2292  "|interval[ms]:The applied trigger interval in millisecond (min 1ms / 10bit)");
2293 
2294  T::AddEvent("SET_TRIGGER_DELAY", "I:1", FTM::State::kIdle, FTM::State::kValid)
2295  (bind(&StateMachineFTM::SetTriggerDelay, this, placeholders::_1))
2296  (""
2297  "|delay[int]:The applied trigger delay is: delay*4ns+8ns");
2298 
2299  T::AddEvent("SET_TIME_MARKER_DELAY", "I:1", FTM::State::kIdle, FTM::State::kValid)
2300  (bind(&StateMachineFTM::SetTimeMarkerDelay, this, placeholders::_1))
2301  (""
2302  "|delay[int]:The applied time marker delay is: delay*4ns+8ns");
2303 
2304  T::AddEvent("SET_DEAD_TIME", "I:1", FTM::State::kIdle, FTM::State::kValid)
2305  (bind(&StateMachineFTM::SetDeadTime, this, placeholders::_1))
2306  (""
2307  "|dead_time[int]:The applied dead time is: dead_time*4ns+8ns");
2308 
2309  T::AddEvent("ENABLE_TRIGGER", "B:1", FTM::State::kIdle, FTM::State::kValid)
2310  (bind(&StateMachineFTM::Enable, this, placeholders::_1, FTM::StaticData::kTrigger))
2311  ("Switch on the physics trigger"
2312  "|Enable[bool]:Enable physics trigger (yes/no)");
2313 
2314  // FIXME: Switch on/off depending on sequence
2315  T::AddEvent("ENABLE_EXT1", "B:1", FTM::State::kIdle, FTM::State::kValid)
2316  (bind(&StateMachineFTM::Enable, this, placeholders::_1, FTM::StaticData::kExt1))
2317  ("Switch on the triggers through the first external line"
2318  "|Enable[bool]:Enable ext1 trigger (yes/no)");
2319 
2320  // FIXME: Switch on/off depending on sequence
2321  T::AddEvent("ENABLE_EXT2", "B:1", FTM::State::kIdle, FTM::State::kValid)
2322  (bind(&StateMachineFTM::Enable, this, placeholders::_1, FTM::StaticData::kExt2))
2323  ("Switch on the triggers through the second external line"
2324  "|Enable[bool]:Enable ext2 trigger (yes/no)");
2325 
2326  T::AddEvent("ENABLE_VETO", "B:1", FTM::State::kIdle, FTM::State::kValid)
2327  (bind(&StateMachineFTM::Enable, this, placeholders::_1, FTM::StaticData::kVeto))
2328  ("Enable veto line"
2329  "|Enable[bool]:Enable veto (yes/no)");
2330 
2331  T::AddEvent("ENABLE_CLOCK_CONDITIONER", "B:1", FTM::State::kIdle, FTM::State::kValid)
2332  (bind(&StateMachineFTM::Enable, this, placeholders::_1, FTM::StaticData::kClockConditioner))
2333  ("Enable clock conidtioner output in favor of time marker output"
2334  "|Enable[bool]:Enable clock conditioner (yes/no)");
2335 
2336  T::AddEvent("ENABLE_GROUP1_LPINT", "B:1", FTM::State::kIdle, FTM::State::kValid)
2338  ("");
2339  T::AddEvent("ENABLE_GROUP1_LPEXT", "B:1", FTM::State::kIdle, FTM::State::kValid)
2341  ("");
2342  T::AddEvent("ENABLE_GROUP2_LPINT", "B:1", FTM::State::kIdle, FTM::State::kValid)
2344  ("");
2345  T::AddEvent("ENABLE_GROUP2_LPEXT", "B:1", FTM::State::kIdle, FTM::State::kValid)
2347  ("");
2348  T::AddEvent("SET_INTENSITY_LPINT", "S:1", FTM::State::kIdle, FTM::State::kValid)
2349  (bind(&StateMachineFTM::SetIntensity, this, placeholders::_1, FTM::StaticData::kLPint))
2350  ("");
2351  T::AddEvent("SET_INTENSITY_LPEXT", "S:1", FTM::State::kIdle, FTM::State::kValid)
2352  (bind(&StateMachineFTM::SetIntensity, this, placeholders::_1, FTM::StaticData::kLPext))
2353  ("");
2354 
2355 
2356  T::AddEvent("SET_TRIGGER_SEQUENCE", "S:3", FTM::State::kIdle, FTM::State::kValid)
2357  (bind(&StateMachineFTM::SetTriggerSeq, this, placeholders::_1))
2358  ("Setup the sequence of artificial triggers produced by the FTM"
2359  "|Ped[short]:number of pedestal triggers in a row"
2360  "|LPext[short]:number of triggers of the external light pulser"
2361  "|LPint[short]:number of triggers of the internal light pulser");
2362 
2363  T::AddEvent("SET_TRIGGER_MULTIPLICITY", "S:1", FTM::State::kIdle, FTM::State::kValid)
2364  (bind(&StateMachineFTM::SetTriggerMultiplicity, this, placeholders::_1))
2365  ("Setup the Multiplicity condition for physcis triggers"
2366  "|N[int]:Number of requirered coincident triggers from sum-patches (1-40)");
2367 
2368  T::AddEvent("SET_TRIGGER_WINDOW", "S:1", FTM::State::kIdle, FTM::State::kValid)
2369  (bind(&StateMachineFTM::SetTriggerWindow, this, placeholders::_1))
2370  ("");
2371 
2372  T::AddEvent("SET_CALIBRATION_MULTIPLICITY", "S:1", FTM::State::kIdle, FTM::State::kValid)
2373  (bind(&StateMachineFTM::SetCalibMultiplicity, this, placeholders::_1))
2374  ("Setup the Multiplicity condition for artificial (calibration) triggers"
2375  "|N[int]:Number of requirered coincident triggers from sum-patches (1-40)");
2376 
2377  T::AddEvent("SET_CALIBRATION_WINDOW", "S:1", FTM::State::kIdle, FTM::State::kValid)
2378  (bind(&StateMachineFTM::SetCalibWindow, this, placeholders::_1))
2379  ("");
2380 
2381  T::AddEvent("SET_CLOCK_FREQUENCY", "S:1", FTM::State::kIdle, FTM::State::kValid)
2382  (bind(&StateMachineFTM::SetClockFrequency, this, placeholders::_1))
2383  ("");
2384 
2385  T::AddEvent("SET_CLOCK_REGISTER", "X:8", FTM::State::kIdle, FTM::State::kValid)
2386  (bind(&StateMachineFTM::SetClockRegister, this, placeholders::_1))
2387  ("");
2388 
2389  // A new configure will first stop the FTM this means
2390  // we can allow it in idle _and_ taking data
2392  (bind(&StateMachineFTM::ConfigureFTM, this, placeholders::_1))
2393  ("");
2394 
2396  (bind(&StateMachineFTM::ResetConfig, this))
2397  ("Reset states during a configuration or in case of configuration error");
2398 
2399 
2400 
2401  T::AddEvent("RESET_CRATE", "S:1", FTM::State::kIdle, FTM::State::kValid)
2402  (bind(&StateMachineFTM::ResetCrate, this, placeholders::_1))
2403  ("Reset one of the crates 0-3"
2404  "|crate[short]:Crate number to be reseted (0-3)");
2405 
2406  T::AddEvent("RESET_CAMERA", FTM::State::kIdle, FTM::State::kValid)
2407  (Wrapper(bind(&ConnectionFTM::CmdResetCamera, &fFTM)))
2408  ("Reset all crates. The commands are sent in the order 0,1,2,3");
2409 
2410 
2411  // Load/save static data block
2412  T::AddEvent("SAVE", "C", FTM::State::kIdle, FTM::State::kValid)
2413  (bind(&StateMachineFTM::SaveStaticData, this, placeholders::_1))
2414  ("Saves the static data (FTM configuration) from memory to a file"
2415  "|filename[string]:Filename (can include a path), .bin is automatically added");
2416 
2417  T::AddEvent("LOAD", "C", FTM::State::kIdle, FTM::State::kValid)
2418  (bind(&StateMachineFTM::LoadStaticData, this, placeholders::_1))
2419  ("Loads the static data (FTM configuration) from a file into memory and sends it to the FTM"
2420  "|filename[string]:Filename (can include a path), .bin is automatically added");
2421 
2422 
2423 
2424  // Verbosity commands
2425  T::AddEvent("SET_VERBOSE", "B")
2426  (bind(&StateMachineFTM::SetVerbosity, this, placeholders::_1))
2427  ("set verbosity state"
2428  "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
2429 
2430  T::AddEvent("SET_HEX_OUTPUT", "B")
2431  (bind(&StateMachineFTM::SetHexOutput, this, placeholders::_1))
2432  ("enable or disable hex output for received data"
2433  "|hexout[bool]:disable or enable hex output for received data (yes/no)");
2434 
2435  T::AddEvent("SET_DYNAMIC_OUTPUT", "B")
2436  (bind(&StateMachineFTM::SetDynamicOut, this, placeholders::_1))
2437  ("enable or disable output for received dynamic data (data is still broadcasted via Dim)"
2438  "|dynout[bool]:disable or enable output for dynamic data (yes/no)");
2439 
2440 
2441  // Conenction commands
2442  T::AddEvent("DISCONNECT", FTM::State::kConnected, FTM::State::kIdle, FTM::State::kValid)
2443  (bind(&StateMachineFTM::Disconnect, this))
2444  ("disconnect from ethernet");
2445 
2447  (bind(&StateMachineFTM::Reconnect, this, placeholders::_1))
2448  ("(Re)connect ethernet connection to FTM, a new address can be given"
2449  "|[host][string]:new ethernet address in the form <host:port>");
2450 
2451  fFTM.StartConnect();
2452  }
2453 
2454  void SetEndpoint(const string &url)
2455  {
2456  fFTM.SetEndpoint(url);
2457  }
2458 
2459  map<uint16_t, array<uint64_t, 8>> fClockCondSetup;
2460 
2461  template<class V>
2462  bool CheckConfigVal(Configuration &conf, V max, const string &name, const string &sub)
2463  {
2464  if (!conf.HasDef(name, sub))
2465  {
2466  T::Error("Neither "+name+"default nor "+name+sub+" found.");
2467  return false;
2468  }
2469 
2470  const V val = conf.GetDef<V>(name, sub);
2471 
2472  if (val<=max)
2473  return true;
2474 
2475  ostringstream str;
2476  str << name << sub << "=" << val << " exceeds allowed maximum of " << max << "!";
2477  T::Error(str);
2478 
2479  return false;
2480  }
2481 
2483  {
2484  // ---------- General setup ----------
2485  fFTM.SetVerbose(!conf.Get<bool>("quiet"));
2486  fFTM.SetHexOutput(conf.Get<bool>("hex-out"));
2487  fFTM.SetDynamicOut(conf.Get<bool>("dynamic-out"));
2488 
2489  // ---------- Setup clock conditioner frequencies ----------
2490  const vector<uint16_t> freq = conf.Vec<uint16_t>("clock-conditioner.frequency");
2491  if (freq.empty())
2492  T::Warn("No frequencies for the clock-conditioner defined.");
2493  else
2494  T::Message("Defining clock conditioner frequencies");
2495  for (vector<uint16_t>::const_iterator it=freq.begin();
2496  it!=freq.end(); it++)
2497  {
2498  if (fClockCondSetup.count(*it)>0)
2499  {
2500  T::Error("clock-conditioner frequency defined twice.");
2501  return 1;
2502  }
2503 
2504  if (!conf.HasDef("clock-conditioner.R0.", *it) ||
2505  !conf.HasDef("clock-conditioner.R1.", *it) ||
2506  !conf.HasDef("clock-conditioner.R8.", *it) ||
2507  !conf.HasDef("clock-conditioner.R9.", *it) ||
2508  !conf.HasDef("clock-conditioner.R11.", *it) ||
2509  !conf.HasDef("clock-conditioner.R13.", *it) ||
2510  !conf.HasDef("clock-conditioner.R14.", *it) ||
2511  !conf.HasDef("clock-conditioner.R15.", *it))
2512  {
2513  T::Error("clock-conditioner values incomplete.");
2514  return 1;
2515  }
2516 
2517  array<uint64_t, 8> &arr = fClockCondSetup[*it];
2518 
2519  arr[0] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R0.", *it);
2520  arr[1] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R1.", *it);
2521  arr[2] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R8.", *it);
2522  arr[3] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R9.", *it);
2523  arr[4] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R11.", *it);
2524  arr[5] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R13.", *it);
2525  arr[6] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R14.", *it);
2526  arr[7] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R15.", *it);
2527 
2528  ostringstream out;
2529  out << " -> " << setw(4) << *it << "MHz:" << hex << setfill('0');
2530  for (int i=0; i<8; i++)
2531  out << " " << setw(8) << arr[i];
2532  T::Message(out.str());
2533  }
2534 
2535  // ---------- Setup run types ---------
2536  const vector<string> types = conf.Vec<string>("run-type");
2537  if (types.empty())
2538  T::Warn("No run-types defined.");
2539  else
2540  T::Message("Defining run-types");
2541  for (vector<string>::const_iterator it=types.begin();
2542  it!=types.end(); it++)
2543  {
2544  T::Message(" -> "+ *it);
2545 
2546  if (fConfigs.count(*it)>0)
2547  {
2548  T::Error("Run-type "+*it+" defined twice.");
2549  return 2;
2550  }
2551 
2552  if (!conf.HasDef("sampling-frequency.", *it))
2553  {
2554  T::Error("Neither sampling-frequency."+*it+" nor sampling-frequency.default found.");
2555  return 2;
2556  }
2557 
2558  const uint16_t frq = conf.GetDef<uint16_t>("sampling-frequency.", *it);
2559 
2561  data.SetClockRegister(fClockCondSetup[frq].data());
2562 
2563  // Trigger sequence ped:lp1:lp2
2564  // (data. is used here as an abbreviation for FTM::StaticData::
2565  if (!CheckConfigVal<bool> (conf, true, "trigger.enable-trigger.", *it) ||
2566  !CheckConfigVal<bool> (conf, true, "trigger.enable-external-1.", *it) ||
2567  !CheckConfigVal<bool> (conf, true, "trigger.enable-external-2.", *it) ||
2568  !CheckConfigVal<bool> (conf, true, "trigger.enable-veto.", *it) ||
2569  !CheckConfigVal<bool> (conf, true, "trigger.enable-clock-conditioner.", *it) ||
2570  !CheckConfigVal<bool> (conf, true, "light-pulser.external.enable-group1.", *it) ||
2571  !CheckConfigVal<bool> (conf, true, "light-pulser.external.enable-group2.", *it) ||
2572  !CheckConfigVal<bool> (conf, true, "light-pulser.internal.enable-group1.", *it) ||
2573  !CheckConfigVal<bool> (conf, true, "light-pulser.internal.enable-group2.", *it) ||
2574  !CheckConfigVal<uint16_t>(conf, data.kMaxSequence, "trigger.sequence.pedestal.", *it) ||
2575  !CheckConfigVal<uint16_t>(conf, data.kMaxSequence, "trigger.sequence.lp-ext.", *it) ||
2576  !CheckConfigVal<uint16_t>(conf, data.kMaxSequence, "trigger.sequence.lp-int.", *it) ||
2577  !CheckConfigVal<uint16_t>(conf, data.kMaxTriggerInterval, "trigger.sequence.interval.", *it) ||
2578  !CheckConfigVal<uint16_t>(conf, data.kMaxMultiplicity, "trigger.multiplicity-physics.", *it) ||
2579  !CheckConfigVal<uint16_t>(conf, data.kMaxMultiplicity, "trigger.multiplicity-calib.", *it) ||
2580  !CheckConfigVal<uint16_t>(conf, data.kMaxWindow, "trigger.coincidence-window-physics.", *it) ||
2581  !CheckConfigVal<uint16_t>(conf, data.kMaxWindow, "trigger.coincidence-window-calib.", *it) ||
2582  !CheckConfigVal<uint16_t>(conf, data.kMaxDeadTime, "trigger.dead-time.", *it) ||
2583  !CheckConfigVal<uint16_t>(conf, data.kMaxDelayTrigger, "trigger.delay.", *it) ||
2584  !CheckConfigVal<uint16_t>(conf, data.kMaxDelayTimeMarker, "trigger.time-marker-delay.", *it) ||
2585  !CheckConfigVal<uint16_t>(conf, 0xffff, "ftu-report-interval.", *it) ||
2586  !CheckConfigVal<uint16_t>(conf, data.kMaxIntensity, "light-pulser.external.intensity.", *it) ||
2587  !CheckConfigVal<uint16_t>(conf, data.kMaxIntensity, "light-pulser.internal.intensity.", *it) ||
2588  !CheckConfigVal<uint16_t>(conf, data.kMaxDAC, "trigger.threshold.patch.", *it) ||
2589  !CheckConfigVal<uint16_t>(conf, data.kMaxDAC, "trigger.threshold.logic.", *it) ||
2590  0)
2591  return 2;
2592 
2593  data.Enable(data.kTrigger, conf.GetDef<bool>("trigger.enable-trigger.", *it));
2594  data.Enable(data.kExt1, conf.GetDef<bool>("trigger.enable-external-1.", *it));
2595  data.Enable(data.kExt2, conf.GetDef<bool>("trigger.enable-external-2.", *it));
2596  data.Enable(data.kVeto, conf.GetDef<bool>("trigger.enable-veto.", *it));
2597  data.Enable(data.kClockConditioner, conf.GetDef<bool>("trigger.enable-clock-conditioner.", *it));
2598 
2599  data.EnableLPint(data.kGroup1, conf.GetDef<bool>("light-pulser.internal.enable-group1.", *it));
2600  data.EnableLPint(data.kGroup2, conf.GetDef<bool>("light-pulser.internal.enable-group2.", *it));
2601  data.EnableLPext(data.kGroup1, conf.GetDef<bool>("light-pulser.external.enable-group1.", *it));
2602  data.EnableLPext(data.kGroup2, conf.GetDef<bool>("light-pulser.external.enable-group2.", *it));
2603 
2604  // [ms] Interval between two artificial triggers (no matter which type) minimum 1ms, 10 bit
2605  data.fIntensityLPint = conf.GetDef<uint16_t>("light-pulser.internal.intensity.", *it);
2606  data.fIntensityLPext = conf.GetDef<uint16_t>("light-pulser.external.intensity.", *it);
2607  data.fTriggerInterval = conf.GetDef<uint16_t>("trigger.sequence.interval.", *it);
2608  data.fMultiplicityPhysics = conf.GetDef<uint16_t>("trigger.multiplicity-physics.", *it);
2609  data.fMultiplicityCalib = conf.GetDef<uint16_t>("trigger.multiplicity-calib.", *it);
2610  data.fWindowPhysics = conf.GetDef<uint16_t>("trigger.coincidence-window-physics.", *it);
2611  data.fWindowCalib = conf.GetDef<uint16_t>("trigger.coincidence-window-calib.", *it);
2612  data.fDelayTrigger = conf.GetDef<uint16_t>("trigger.delay.", *it);
2613  data.fDelayTimeMarker = conf.GetDef<uint16_t>("trigger.time-marker-delay.", *it);
2614  data.fDeadTime = conf.GetDef<uint16_t>("trigger.dead-time.", *it);
2615 
2616  data.SetPrescaling(conf.GetDef<uint16_t>("ftu-report-interval.", *it));
2617 
2618  const uint16_t seqped = conf.GetDef<uint16_t>("trigger.sequence.pedestal.", *it);
2619  const uint16_t seqint = conf.GetDef<uint16_t>("trigger.sequence.lp-int.", *it);
2620  const uint16_t seqext = conf.GetDef<uint16_t>("trigger.sequence.lp-ext.", *it);
2621 
2622  data.SetSequence(seqped, seqint, seqext);
2623 
2624  data.EnableAllFTU();
2625  data.EnableAllPixel();
2626 
2627  const vector<uint16_t> pat1 = conf.Vec<uint16_t>("trigger.disable-patch.default");
2628  const vector<uint16_t> pat2 = conf.Vec<uint16_t>("trigger.disable-patch."+*it);
2629 
2630  const vector<uint16_t> pix1 = conf.Vec<uint16_t>("trigger.disable-pixel.default");
2631  const vector<uint16_t> pix2 = conf.Vec<uint16_t>("trigger.disable-pixel."+*it);
2632 
2633  const vector<uint16_t> ftu1 = conf.Vec<uint16_t>("disable-ftu.default");
2634  const vector<uint16_t> ftu2 = conf.Vec<uint16_t>("disable-ftu."+*it);
2635 
2636  vector<uint16_t> ftu, pat, pix;
2637  ftu.insert(ftu.end(), ftu1.begin(), ftu1.end());
2638  ftu.insert(ftu.end(), ftu2.begin(), ftu2.end());
2639  pat.insert(pat.end(), pat1.begin(), pat1.end());
2640  pat.insert(pat.end(), pat2.begin(), pat2.end());
2641  pix.insert(pix.end(), pix1.begin(), pix1.end());
2642  pix.insert(pix.end(), pix2.begin(), pix2.end());
2643 
2644  for (vector<uint16_t>::const_iterator ip=ftu.begin(); ip!=ftu.end(); ip++)
2645  {
2647  {
2648  ostringstream str;
2649  str << "disable-ftu.*=" << *ip << " exceeds allowed maximum of " << FTM::StaticData::kMaxPatchIdx << "!";
2650  T::Error(str);
2651  return 2;
2652  }
2653  data.DisableFTU(*ip);
2654  }
2655  for (vector<uint16_t>::const_iterator ip=pat.begin(); ip!=pat.end(); ip++)
2656  {
2658  {
2659  ostringstream str;
2660  str << "trigger.disable-patch.*=" << *ip << " exceeds allowed maximum of " << FTM::StaticData::kMaxPatchIdx << "!";
2661  T::Error(str);
2662  return 2;
2663  }
2664  data.EnablePatch(*ip, false);
2665  }
2666  for (vector<uint16_t>::const_iterator ip=pix.begin(); ip!=pix.end(); ip++)
2667  {
2669  {
2670  ostringstream str;
2671  str << "trigger.disable-pixel.*=" << *ip << " exceeds allowed maximum of " << FTM::StaticData::kMaxPixelIdx << "!";
2672  T::Error(str);
2673  return 2;
2674  }
2675  data.EnablePixel(*ip, false);
2676  }
2677 
2678  const uint16_t th0 = conf.GetDef<uint16_t>("trigger.threshold.patch.", *it);
2679  const uint16_t th1 = conf.GetDef<uint16_t>("trigger.threshold.logic.", *it);
2680 
2681  for (int i=0; i<40; i++)
2682  {
2683  data[i].fDAC[0] = th0;
2684  data[i].fDAC[1] = th0;
2685  data[i].fDAC[2] = th0;
2686  data[i].fDAC[3] = th0;
2687  data[i].fDAC[4] = th1;
2688  }
2689 
2690  fConfigs[*it] = data;
2691 
2692  // trigger.threshold.dac-0:
2693 
2694  /*
2695  threshold-A data[n].fDAC[0] = val
2696  threshold-B data[n].fDAC[1] = val
2697  threshold-C data[n].fDAC[2] = val
2698  threshold-D data[n].fDAC[3] = val
2699  threshold-H data[n].fDAC[4] = val
2700  */
2701 
2702  // kMaxDAC = 0xfff,
2703  }
2704 
2705  // FIXME: Add a check about unsused configurations
2706 
2707  // ---------- FOR TESTING PURPOSE ---------
2708 
2709  // fFTM.SetDefaultSetup(conf.Get<string>("default-setup"));
2710  fConfigs["test"] = FTM::StaticData();
2711 
2712  // ---------- Setup connection endpoint ---------
2713  SetEndpoint(conf.Get<string>("addr"));
2714 
2715  return -1;
2716  }
2717 };
2718 
2719 // ------------------------------------------------------------------------
2720 
2721 #include "Main.h"
2722 
2723 template<class T, class S, class R>
2725 {
2726  return Main::execute<T, StateMachineFTM<S, R>>(conf);
2727 }
2728 
2730 {
2731  po::options_description control("Control options");
2732  control.add_options()
2733  ("no-dim", po_bool(), "Disable dim services")
2734  ("addr,a", var<string>("localhost:5000"), "Network address of FTM")
2735  ("quiet,q", po_bool(true), "Disable printing contents of all received messages (except dynamic data) in clear text.")
2736  ("hex-out", po_bool(), "Enable printing contents of all printed messages also as hex data.")
2737  ("dynamic-out", po_bool(), "Enable printing received dynamic data.")
2738 // ("default-setup", var<string>(), "Binary file with static data loaded whenever a connection to the FTM was established.")
2739  ;
2740 
2741  po::options_description freq("Sampling frequency setup");
2742  freq.add_options()
2743  ("clock-conditioner.frequency", vars<uint16_t>(), "Frequencies for which to setup the clock-conditioner (replace the * in the following options by this definition)")
2744  ("clock-conditioner.R0.*", var<Hex<uint32_t>>(), "Clock-conditioner R0")
2745  ("clock-conditioner.R1.*", var<Hex<uint32_t>>(), "Clock-conditioner R1")
2746  ("clock-conditioner.R8.*", var<Hex<uint32_t>>(), "Clock-conditioner R8")
2747  ("clock-conditioner.R9.*", var<Hex<uint32_t>>(), "Clock-conditioner R9")
2748  ("clock-conditioner.R11.*", var<Hex<uint32_t>>(), "Clock-conditioner R11")
2749  ("clock-conditioner.R13.*", var<Hex<uint32_t>>(), "Clock-conditioner R13")
2750  ("clock-conditioner.R14.*", var<Hex<uint32_t>>(), "Clock-conditioner R14")
2751  ("clock-conditioner.R15.*", var<Hex<uint32_t>>(), "Clock-conditioner R15");
2752 
2753  po::options_description runtype("Run type configuration");
2754  runtype.add_options()
2755  ("run-type", vars<string>(), "Name of run-types (replace the * in the following configuration by the case-sensitive names defined here)")
2756  ("sampling-frequency.*", var<uint16_t>(), "Sampling frequency as defined in the clock-conditioner.frequency")
2757  ("trigger.enable-trigger.*", var<bool>(), "Enable trigger output of physics trigger")
2758  ("trigger.enable-external-1.*", var<bool>(), "Enable external trigger line 1")
2759  ("trigger.enable-external-2.*", var<bool>(), "Enable external trigger line 2")
2760  ("trigger.enable-veto.*", var<bool>(), "Enable veto line")
2761  ("trigger.enable-clock-conditioner.*", var<bool>(), "")
2762  ("trigger.sequence.interval.*", var<uint16_t>(), "Interval between two artifical triggers in units of ms")
2763  ("trigger.sequence.pedestal.*", var<uint16_t>(), "Number of pedestal events in the sequence of artificial triggers")
2764  ("trigger.sequence.lp-int.*", var<uint16_t>(), "Number of LPint events in the sequence of artificial triggers")
2765  ("trigger.sequence.lp-ext.*", var<uint16_t>(), "Number of LPext events in the sequence of artificial triggers")
2766  ("trigger.multiplicity-physics.*", var<uint16_t>(), "Multiplicity for physics events (n out of 40)")
2767  ("trigger.multiplicity-calib.*", var<uint16_t>(), "Multiplicity for LPext events (n out of 40)")
2768  ("trigger.coincidence-window-physics.*", var<uint16_t>(), "Coincidence window for physics triggers in units of n*4ns+8ns")
2769  ("trigger.coincidence-window-calib.*", var<uint16_t>(), "Coincidence window for LPext triggers in units of n*4ns+8ns")
2770  ("trigger.dead-time.*", var<uint16_t>(), "Dead time after trigger in units of n*4ns+8ns")
2771  ("trigger.delay.*", var<uint16_t>(), "Delay of the trigger send to the FAD boards after a trigger in units of n*4ns+8ns")
2772  ("trigger.time-marker-delay.*", var<uint16_t>(), "Delay of the time-marker after a trigger in units of n*4ns+8ns")
2773  ("trigger.disable-pixel.*", vars<uint16_t>(), "")
2774  ("trigger.disable-patch.*", vars<uint16_t>(), "")
2775  ("trigger.threshold.patch.*", var<uint16_t>(), "")
2776  ("trigger.threshold.logic.*", var<uint16_t>(), "")
2777  ("ftu-report-interval.*", var<uint16_t>(), "")
2778  ("disable-ftu.*", vars<uint16_t>(), "")
2779  ("light-pulser.external.enable-group1.*", var<bool>(), "Enable LED group 1 of external light pulser")
2780  ("light-pulser.external.enable-group2.*", var<bool>(), "Enable LED group 2 of external light pulser")
2781  ("light-pulser.internal.enable-group1.*", var<bool>(), "Enable LED group 1 of internal light pulser")
2782  ("light-pulser.internal.enable-group2.*", var<bool>(), "Enable LED group 2 of internal light pulser")
2783  ("light-pulser.external.intensity.*", var<uint16_t>(), "Intensity of external light pulser")
2784  ("light-pulser.internal.intensity.*", var<uint16_t>(), "Intensity of internal light pulser")
2785  ;
2786 
2787  conf.AddOptions(control);
2788  conf.AddOptions(freq);
2789  conf.AddOptions(runtype);
2790 }
2791 
2792 /*
2793  Extract usage clause(s) [if any] for SYNOPSIS.
2794  Translators: "Usage" and "or" here are patterns (regular expressions) which
2795  are used to match the usage synopsis in program output. An example from cp
2796  (GNU coreutils) which contains both strings:
2797  Usage: cp [OPTION]... [-T] SOURCE DEST
2798  or: cp [OPTION]... SOURCE... DIRECTORY
2799  or: cp [OPTION]... -t DIRECTORY SOURCE...
2800  */
2802 {
2803  cout <<
2804  "The ftmctrl controls the FTM (FACT Trigger Master) board.\n"
2805  "\n"
2806  "The default is that the program is started without user intercation. "
2807  "All actions are supposed to arrive as DimCommands. Using the -c "
2808  "option, a local shell can be initialized. With h or help a short "
2809  "help message about the usuage can be brought to the screen.\n"
2810  "\n"
2811  "Usage: ftmctrl [-c type] [OPTIONS]\n"
2812  " or: ftmctrl [OPTIONS]\n";
2813  cout << endl;
2814 }
2815 
2817 {
2818  Main::PrintHelp<StateMachineFTM<StateMachine, ConnectionFTM>>();
2819 
2820  /* Additional help text which is printed after the configuration
2821  options goes here */
2822 
2823  /*
2824  cout << "bla bla bla" << endl << endl;
2825  cout << endl;
2826  cout << "Environment:" << endl;
2827  cout << "environment" << endl;
2828  cout << endl;
2829  cout << "Examples:" << endl;
2830  cout << "test exam" << endl;
2831  cout << endl;
2832  cout << "Files:" << endl;
2833  cout << "files" << endl;
2834  cout << endl;
2835  */
2836 }
2837 
2838 int main(int argc, const char* argv[])
2839 {
2840  Configuration conf(argv[0]);
2841  conf.SetPrintUsage(PrintUsage);
2843  SetupConfiguration(conf);
2844 
2845  if (!conf.DoParse(argc, argv, PrintHelp))
2846  return 127;
2847 
2848  //try
2849  {
2850  // No console access at all
2851  if (!conf.Has("console"))
2852  {
2853  if (conf.Get<bool>("no-dim"))
2854  return RunShell<LocalStream, StateMachine, ConnectionFTM>(conf);
2855  else
2856  return RunShell<LocalStream, StateMachineDim, ConnectionDimFTM>(conf);
2857  }
2858  // Cosole access w/ and w/o Dim
2859  if (conf.Get<bool>("no-dim"))
2860  {
2861  if (conf.Get<int>("console")==0)
2862  return RunShell<LocalShell, StateMachine, ConnectionFTM>(conf);
2863  else
2864  return RunShell<LocalConsole, StateMachine, ConnectionFTM>(conf);
2865  }
2866  else
2867  {
2868  if (conf.Get<int>("console")==0)
2869  return RunShell<LocalShell, StateMachineDim, ConnectionDimFTM>(conf);
2870  else
2871  return RunShell<LocalConsole, StateMachineDim, ConnectionDimFTM>(conf);
2872  }
2873  }
2874  /*catch (std::exception& e)
2875  {
2876  cerr << "Exception: " << e.what() << endl;
2877  return -1;
2878  }*/
2879 
2880  return 0;
2881 }
DimDescribedService fDimPassport
Definition: ftmctrl.cc:1246
bool fIsVerbose
Definition: ftmctrl.cc:44
int SetClockRegister(const EventImp &evt)
Definition: ftmctrl.cc:1833
uint8_t GetSequencePed() const
Definition: HeadersFTM.h:349
bool CmdDisableReports(bool b)
Definition: ftmctrl.cc:598
uint64_t fTimeStampOn
Definition: ftmctrl.cc:1255
bool ToggleFTU(uint32_t board)
Definition: ftmctrl.cc:883
Enable the trigger output.
Definition: HeadersFTM.h:60
int LoadStaticData(const EventImp &evt)
Definition: ftmctrl.cc:1602
Request data.
Definition: HeadersFTM.h:58
vector< uint16_t > fBuffer
Definition: ftmctrl.cc:40
Reboot (no power cycle) all FTUs and FADs of one crate.
Definition: HeadersFTM.h:63
int DisableAllPatchesExcept(const EventImp &evt)
Definition: ftmctrl.cc:1920
int SetHexOutput(const EventImp &evt)
Definition: ftmctrl.cc:1582
void SetHexOutput(bool b)
Definition: ftmctrl.cc:610
bool CmdResetCamera()
Definition: ftmctrl.cc:586
bool SetTriggerDelay(uint32_t val)
Definition: ftmctrl.cc:923
int ResetConfig()
Definition: ftmctrl.cc:2033
int SetIntensity(const EventImp &evt, FTM::StaticData::GeneralSettings lp)
Definition: ftmctrl.cc:1877
FTM::DynamicData fDynamicData
Definition: ftmctrl.cc:54
uint16_t * EnablePixel(int idx, bool enable)
Definition: HeadersFTM.h:308
int DisableReports(const EventImp &evt)
Definition: ftmctrl.cc:1562
function< int(const EventImp &)> Wrapper(function< void()> func)
Definition: ftmctrl.cc:1459
int SetNoutof4(const EventImp &evt)
Definition: ftmctrl.cc:1683
FTM::Error fError
Definition: ftmctrl.cc:55
bool fIsDynamicOut
Definition: ftmctrl.cc:45
uint16_t fWindowCalib
(4ns * x + 8ns) At least N (multiplicity) rising edges (trigger signal) within this window ...
Definition: HeadersFTM.h:233
int SetVerbosity(const EventImp &evt)
Definition: ftmctrl.cc:1572
std::vector< uint16_t > HtoN() const
Definition: HeadersFTM.h:249
A general base-class describing events issues in a state machine.
Definition: EventImp.h:11
const char * GetText() const
Definition: EventImp.h:88
bool CheckEventSize(size_t has, const char *name, size_t size)
Definition: ftmctrl.cc:1467
uint8_t GetSequenceLPint() const
Definition: HeadersFTM.h:350
uint16_t fTriggerInterval
only 8 bit used
Definition: HeadersFTM.h:219
int SetClockFrequency(const EventImp &evt)
Definition: ftmctrl.cc:1846
int EnableFTU(const EventImp &evt)
Definition: ftmctrl.cc:1696
int SetDynamicOut(const EventImp &evt)
Definition: ftmctrl.cc:1592
External trigger signal 2.
Definition: HeadersFTM.h:205
bool SetAllThresholds(const int32_t *th)
Definition: ftmctrl.cc:752
void UpdateCounter()
Definition: ftmctrl.cc:1356
bool SetTriggerInterval(uint32_t val)
Definition: ftmctrl.cc:917
int GetRegister(const EventImp &evt)
Definition: ftmctrl.cc:1504
map< string, FTM::StaticData > Configs
Definition: ftmctrl.cc:2010
Dynamic data (rates)
Definition: HeadersFTM.h:90
int SetDeadTime(const EventImp &evt)
Definition: ftmctrl.cc:1778
void SetupConfiguration(Configuration &conf)
Definition: Main.h:25
void UpdateDynamicData()
Definition: ftmctrl.cc:1296
int EnableLP(const EventImp &evt, FTM::StaticData::GeneralSettings lp, FTM::StaticData::LightPulserEnable group)
Definition: ftmctrl.cc:1866
void PostCmd(vector< uint16_t > dat, uint16_t u1=0, uint16_t u2=0, uint16_t u3=0, uint16_t u4=0)
Definition: ftmctrl.cc:450
bool SetTimeMarkerDelay(uint32_t val)
Definition: ftmctrl.cc:929
int i
Definition: db_dim_client.c:21
void setQuality(int quality)
Definition: discpp.cxx:1256
DimDescribedService fDimTriggerRates
Definition: ftmctrl.cc:1247
The base implementation of a distributed messaging system.
Definition: MessageImp.h:10
uint16_t fMultiplicityPhysics
Definition: HeadersFTM.h:226
...until kCmdStopRun
Definition: HeadersFTM.h:74
char str[80]
Definition: test_client.c:7
void SetPrintUsage(const std::function< void(void)> &func)
T Get(const std::string &var)
FTM::StaticData fBufStaticData
Definition: ftmctrl.cc:57
Set color Red.
Definition: WindowLog.h:17
uint16_t fActiveFTU[4]
Definition: HeadersFTM.h:238
DimDescribedService fDimDynamicData
Definition: ftmctrl.cc:1251
int SetSelectedThresholds(const EventImp &evt)
Definition: ftmctrl.cc:1651
Error fError
Definition: HeadersFTM.h:187
void CmdTakeNevents(uint32_t n)
Definition: ftmctrl.cc:538
uint16_t fPrescaling
0-3 (A-D) Threshold of patches, 4 (H) Threshold for N out of 4 (12 bit each)
Definition: HeadersFTM.h:188
Header()
Definition: HeadersFTM.h:195
...fixed number of events
Definition: HeadersFTM.h:75
void EnableLPint(LightPulserEnable group, bool enable)
Definition: HeadersFTM.h:280
void CmdReqStatDat()
Definition: ftmctrl.cc:505
STL namespace.
ConnectionFTM(ba::io_service &ioservice, MessageImp &imp)
Definition: ftmctrl.cc:484
uint32_t fTriggerCounter
Definition: HeadersFAD.h:177
void SetEndpoint(const string &url)
Definition: ftmctrl.cc:2454
Types
Types sent in the header of the following data.
Definition: HeadersFTM.h:86
bool TogglePixel(uint16_t idx)
Definition: ftmctrl.cc:1192
bool fIsHexOutput
Definition: ftmctrl.cc:46
bool SetSelectedThresholds(const int32_t *th)
Definition: ftmctrl.cc:722
bool SetIntensity(FTM::StaticData::GeneralSettings lp, uint16_t intensity)
Definition: ftmctrl.cc:1078
Select clock conditioner frequency (1) / time marker (0) as output.
Definition: HeadersFTM.h:208
int Disconnect()
Definition: ftmctrl.cc:1963
int SetTriggerSeq(const EventImp &evt)
Definition: ftmctrl.cc:1765
Static (configuration) data.
Definition: HeadersFTM.h:89
std::vector< T > Vec(const std::string &var)
uint16_t fDeadTime
(4ns * x + 8ns) FTM internal programmable delay between trigger descision and time marker output ...
Definition: HeadersFTM.h:230
void UpdateError()
Definition: ftmctrl.cc:1348
int32_t GetInt() const
Definition: EventImp.h:93
std::string GetString() const
Definition: EventImp.cc:194
int EnablePatch(const EventImp &evt, bool enable)
Definition: ftmctrl.cc:1931
int64_t first
Size of this column in the tile.
Definition: zofits.h:26
void PostCmd(uint16_t u1=0, uint16_t u2=0, uint16_t u3=0, uint16_t u4=0)
Definition: ftmctrl.cc:475
Configs::const_iterator fTargetConfig
Definition: ftmctrl.cc:2012
void PostCmd(array< uint16_t, N > dat, uint16_t u1=0, uint16_t u2=0, uint16_t u3=0, uint16_t u4=0)
Definition: ftmctrl.cc:425
FTM and FTUs are being reconfigured.
Definition: HeadersFTM.h:22
int SetCalibWindow(const EventImp &evt)
Definition: ftmctrl.cc:1822
void DisableAllFTU()
Definition: HeadersFTM.h:278
void UpdateStaticData()
Definition: ftmctrl.cc:1287
bool SetNoutof4(int32_t patch, int32_t value)
Definition: ftmctrl.cc:768
bool SetCalibMultiplicity(uint16_t n)
Definition: ftmctrl.cc:1011
bool CmdResetCrate(uint16_t addr)
Definition: ftmctrl.cc:575
bool CheckConsistency(FTM::StaticData &data)
Definition: ftmctrl.cc:144
int SaveStaticData(const EventImp &evt)
Definition: ftmctrl.cc:1620
uint16_t fDataSize
Size in words to be received after the header (incl end delim.)
Definition: HeadersFTM.h:108
bool DisableAllPatchesExcept(int16_t idx)
Definition: ftmctrl.cc:1161
void PrintHelp()
Definition: ftmctrl.cc:2816
Specifies that dynamic data is read/written.
Definition: HeadersFTM.h:70
int SetCalibMultiplicity(const EventImp &evt)
Definition: ftmctrl.cc:1800
void SetSequence(uint8_t ped, uint8_t lpint, uint8_t lpext)
Definition: HeadersFTM.h:353
void SetupConfiguration(Configuration &conf)
Definition: ftmctrl.cc:2729
virtual void UpdateFirstHeader()
Definition: ftmctrl.cc:59
int SetTriggerInterval(const EventImp &evt)
Definition: ftmctrl.cc:1721
Specifies that a register is read/written.
Definition: HeadersFTM.h:71
StateMachineFTM(ostream &out=cout)
Definition: ftmctrl.cc:2146
uint16_t fState
State of the FTM central state machine.
Definition: HeadersFTM.h:109
uint16_t GetUShort() const
Definition: EventImp.h:92
virtual void UpdateCounter()
Definition: ftmctrl.cc:127
void DisableFTU(int i)
Definition: HeadersFTM.h:275
int Enable(const EventImp &evt, FTM::StaticData::GeneralSettings type)
Definition: ftmctrl.cc:1888
void SetPrescaling(uint16_t val)
Definition: HeadersFTM.h:368
Configs fConfigs
Definition: ftmctrl.cc:2011
int SetRegister(const EventImp &evt)
Definition: ftmctrl.cc:1478
Specifies that static (configuration) data is read/written.
Definition: HeadersFTM.h:69
void CmdReqDynDat()
Definition: ftmctrl.cc:500
virtual void UpdateFtuList()
Definition: ftmctrl.cc:83
bool SetPrescaling(uint32_t value)
Definition: ftmctrl.cc:828
Minimum required trigger multiplicity.
Definition: HeadersFTM.h:183
FTM::StaticData fStaticData
Definition: ftmctrl.cc:53
uint16_t fType
Type of the data to be received after the header.
Definition: HeadersFTM.h:107
External trigger signal 1.
Definition: HeadersFTM.h:206
bool Has(const std::string &var)
T GetDef(const std::string &var, const S &val)
int Reconnect(const EventImp &evt)
Definition: ftmctrl.cc:1977
bool SaveStaticData(string name) const
Definition: ftmctrl.cc:653
int DisableAllPixelsExcept(const EventImp &evt)
Definition: ftmctrl.cc:1909
bool EnableLP(FTM::StaticData::GeneralSettings lp, FTM::StaticData::LightPulserEnable group, bool enable)
Definition: ftmctrl.cc:1060
uint8_t fIntensityLPint
Enable for LED group 1/2 (LightPulserEnable)
Definition: HeadersFTM.h:223
void ConnectionEstablished()
Definition: ftmctrl.cc:369
uint8_t GetSequenceLPext() const
Definition: HeadersFTM.h:351
void CmdStartRun(bool log=true)
Definition: ftmctrl.cc:521
void EnableLPext(LightPulserEnable group, bool enable)
Definition: HeadersFTM.h:288
void AddOptions(const po::options_description &opt, bool visible=true)
Definition: Configuration.h:92
bool CmdGetRegister(uint16_t addr)
Definition: ftmctrl.cc:564
int type
int SetTimeMarkerDelay(const EventImp &evt)
Definition: ftmctrl.cc:1743
const FTM::StaticData & GetStaticData() const
Definition: ftmctrl.cc:1233
int SetTriggerMultiplicity(const EventImp &evt)
Definition: ftmctrl.cc:1789
First user defined mode (to be used in derived classes&#39; enums)
uint64_t fPrevState
Definition: ftmctrl.cc:1257
bool EnablePixel(int16_t idx, bool enable)
Definition: ftmctrl.cc:1099
bool SetTriggerWindow(uint16_t win)
Definition: ftmctrl.cc:994
void HandleReceivedData(const bs::error_code &err, size_t bytes_received, int)
Definition: ftmctrl.cc:189
uint32_t fTimeStamp
Definition: HeadersFAD.h:189
bool Enabled(uint16_t idx) const
Definition: HeadersFTM.h:340
void EnableFTU(int i)
Definition: HeadersFTM.h:274
void CmdToggleLed()
Definition: ftmctrl.cc:490
DimDescribedService fDimError
Definition: ftmctrl.cc:1248
int SetPrescaling(const EventImp &evt)
Definition: ftmctrl.cc:1754
uint32_t fCounterReg
Definition: ftmctrl.cc:2007
Disable the trigger output.
Definition: HeadersFTM.h:61
bool DisableAllPixelsExcept(uint16_t idx)
Definition: ftmctrl.cc:1146
DimDescribedService fDimCounter
Definition: ftmctrl.cc:1252
Enable trigger decision after light pulse (CalibrationTrigger, LP1)
Definition: HeadersFTM.h:204
int SetAllThresholds(const EventImp &evt)
Definition: ftmctrl.cc:1667
int Wrap(function< void()> f)
Definition: ftmctrl.cc:1453
Commandline parsing, resource file parsing and database access.
Definition: Configuration.h:9
Disable transmission of rate-reports (dynamic data)
Definition: HeadersFTM.h:64
Enable artificial trigger after light pulse (LP2)
Definition: HeadersFTM.h:203
int buffer[BUFFSIZE]
Definition: db_dim_client.c:14
States GetState() const
Definition: ftmctrl.cc:1206
virtual void UpdateError()
Definition: ftmctrl.cc:116
int TogglePixel(const EventImp &evt)
Definition: ftmctrl.cc:1942
Pedestal trigger (artifical)
Definition: HeadersFTM.h:202
bool LoadStaticData(string name)
Definition: ftmctrl.cc:626
map< uint16_t, uint32_t > fCounter
Definition: ftmctrl.cc:49
Local extension to identify a header in fCounter.
Definition: HeadersFTM.h:88
int EvalOptions(Configuration &conf)
Definition: ftmctrl.cc:2482
int size
Definition: db_dim_server.c:17
uint32_t GetUInt() const
Definition: EventImp.h:94
FTU list (answer of ping)
Definition: HeadersFTM.h:91
float data[4 *1440]
bool SetTriggerSeq(const uint16_t d[3])
Definition: ftmctrl.cc:951
Send data.
Definition: HeadersFTM.h:59
void HandleReadTimeout(const bs::error_code &error)
Definition: ftmctrl.cc:389
Start delimiter send before each header.
Definition: HeadersFTM.h:100
bool fHasHeader
Definition: ftmctrl.cc:42
void Enable(FTM::StaticData::GeneralSettings type, bool enable)
Definition: ftmctrl.cc:941
void ToggleFTU(int i)
Definition: HeadersFTM.h:296
bool valid() const
Definition: HeadersFTM.h:266
void Enable(GeneralSettings type, bool enable)
Definition: HeadersFTM.h:298
uint32_t GetCounter(FTM::Types type)
Definition: ftmctrl.cc:1231
uint32_t fTriggerCounter
Definition: ftmctrl.cc:1256
int counter
Definition: db_dim_client.c:19
uint16_t fWindowPhysics
R0, R1, R8, R9, R11, R13, R14, R15.
Definition: HeadersFTM.h:232
StaticData()
Definition: HeadersFTM.h:245
int ResetCrate(const EventImp &evt)
Definition: ftmctrl.cc:1953
bool EnableFTU(int32_t board, bool enable)
Definition: ftmctrl.cc:854
uint16_t fMultiplicityCalib
Required trigger multiplicity for physcis triggers (0-40)
Definition: HeadersFTM.h:227
int ToggleFTU(const EventImp &evt)
Definition: ftmctrl.cc:1710
bool EnablePatch(int16_t idx, bool enable)
Definition: ftmctrl.cc:1176
virtual void HandleReadTimeout(const boost::system::error_code &)
Definition: Connection.h:138
DimDescribedService fDimStaticData
Definition: ftmctrl.cc:1250
bool IsEnabled(GeneralSettings type) const
Definition: HeadersFTM.h:306
void CmdStopRun()
Definition: ftmctrl.cc:530
A requested register value.
Definition: HeadersFTM.h:93
uint32_t fCounterStat
Definition: ftmctrl.cc:2008
bool GetBool() const
Definition: EventImp.h:90
int ConfigureFTM(const EventImp &evt)
Definition: ftmctrl.cc:2014
void SetVerbose(bool b)
Definition: ftmctrl.cc:605
virtual void UpdateHeader()
Definition: ftmctrl.cc:68
Veto trigger decision / artifical triggers.
Definition: HeadersFTM.h:207
bool SetDeadTime(uint32_t val)
Definition: ftmctrl.cc:935
FTM::FtuList fFtuList
Definition: ftmctrl.cc:52
virtual void UpdateStaticData()
Definition: ftmctrl.cc:94
Error()
Definition: HeadersFTM.h:197
(4ns * x + 8ns) At least N (multiplicity) rising edges (trigger signal) within this window ...
Definition: HeadersFTM.h:184
int RunShell(Configuration &conf)
Definition: ftmctrl.cc:2724
int TakeNevents(const EventImp &evt)
Definition: ftmctrl.cc:1541
Trigger output disabled, configuration possible.
Definition: HeadersFTM.h:21
uint16_t fDelayTimeMarker
(4ns * x + 8ns) FTM internal programmable delay between trigger decision and output ...
Definition: HeadersFTM.h:229
void CmdPing()
Definition: ftmctrl.cc:495
int main(int argc, const char *argv[])
Definition: ftmctrl.cc:2838
int SetTriggerWindow(const EventImp &evt)
Definition: ftmctrl.cc:1811
void UpdateFirstHeader()
Definition: ftmctrl.cc:1259
po::typed_value< bool > * po_bool(bool def=false)
int16_t GetShort() const
Definition: EventImp.h:91
void PrintUsage()
Definition: ftmctrl.cc:2801
End delimiter send after each data block.
Definition: HeadersFTM.h:101
Configure single FTU board.
Definition: HeadersFTM.h:65
void SetClockRegister(const uint64_t reg[])
Definition: HeadersFTM.h:362
uint16_t fDelayTrigger
Required trigger multiplicity calibration (LPext) triggers (0-40)
Definition: HeadersFTM.h:228
void CmdSendStatDat(const FTM::StaticData &data)
Definition: ftmctrl.cc:510
bool SetClockRegister(const uint64_t reg[])
Definition: ftmctrl.cc:1045
uint16_t fDelimiter
Start delimiter.
Definition: HeadersFTM.h:106
void SetDynamicOut(bool b)
Definition: ftmctrl.cc:615
int SetTriggerDelay(const EventImp &evt)
Definition: ftmctrl.cc:1732
T Get(size_t offset=0) const
Definition: EventImp.h:66
virtual void UpdateDynamicData()
Definition: ftmctrl.cc:105
void clear()
Definition: HeadersFTM.h:136
uint8_t fIntensityLPext
Ratio between trigger types send as artificial trigger (in this order) 3x5bit.
Definition: HeadersFTM.h:221
bool HasDef(const std::string &var, const T &val)
void EnableAllFTU()
Definition: HeadersFTM.h:277
FTM::Header fHeader
Definition: ftmctrl.cc:51
bool DoParse(int argc, const char **argv, const std::function< void()> &func=std::function< void()>())
bool SetCalibWindow(uint16_t win)
Definition: ftmctrl.cc:1028
bool CheckConfigVal(Configuration &conf, V max, const string &name, const string &sub)
Definition: ftmctrl.cc:2462
bool SetThreshold(int32_t patch, int32_t value)
Definition: ftmctrl.cc:667
Ping all FTUs (get FTU list)
Definition: HeadersFTM.h:62
Physics trigger decision (PhysicTrigger)
Definition: HeadersFTM.h:201
Trigger output enabled, configuration ignored.
Definition: HeadersFTM.h:23
bool SetTriggerMultiplicity(uint16_t n)
Definition: ftmctrl.cc:977
void UpdateFtuList()
Definition: ftmctrl.cc:1279
map< uint16_t, array< uint64_t, 8 > > fClockCondSetup
Definition: ftmctrl.cc:2459
bool SetVal(uint16_t *dest, uint32_t val, uint32_t max)
Definition: ftmctrl.cc:898
const T * Ptr(size_t offset=0) const
Definition: EventImp.h:74
ConnectionDimFTM(ba::io_service &ioservice, MessageImp &imp)
Definition: ftmctrl.cc:1375
uint64_t fTimeStamp
Definition: ftmctrl.cc:1254
DimDescribedService fDimFtuList
Definition: ftmctrl.cc:1249
bool CmdSetRegister(uint16_t addr, uint16_t val)
Definition: ftmctrl.cc:547
Set attribute Bold.
Definition: WindowLog.h:36
int SetThreshold(const EventImp &evt)
Definition: ftmctrl.cc:1634
int EnablePixel(const EventImp &evt, bool b)
Definition: ftmctrl.cc:1898
Error list (error when FTU communication failed)
Definition: HeadersFTM.h:92
virtual size_t GetSize() const
Definition: EventImp.h:55
uint16_t fDAC[5]
enable of 4x9 pixels coded as 4x9bits
Definition: HeadersFTM.h:187
uint32_t freq
Definition: HeadersSQM.h:90