source: trunk/FACT++/src/ftmctrl.cc@ 11480

Last change on this file since 11480 was 11480, checked in by tbretz, 13 years ago
Removed obsolete include.
File size: 76.5 KB
Line 
1#include <array>
2
3#include "Dim.h"
4#include "Event.h"
5#include "Shell.h"
6#include "StateMachineDim.h"
7#include "Connection.h"
8#include "Configuration.h"
9#include "Console.h"
10#include "Converter.h"
11
12#include "tools.h"
13
14#include "HeadersFTM.h"
15
16
17namespace ba = boost::asio;
18namespace bs = boost::system;
19
20using namespace std;
21
22// ------------------------------------------------------------------------
23
24class ConnectionFTM : public Connection
25{
26public:
27 enum States
28 {
29 // State Machine states
30 kDisconnected = 1,
31 kConnected,
32 kIdle,
33 kConfigured, // Returned if idle and fBufStaticData==fStaticData
34 kTakingData,
35 };
36
37private:
38 vector<uint16_t> fBuffer;
39
40 bool fHasHeader;
41 FTM::States fState;
42
43 bool fIsVerbose;
44 bool fIsDynamicOut;
45 bool fIsHexOutput;
46
47// string fDefaultSetup;
48
49 // --verbose
50 // --hex-out
51 // --dynamic-out
52 // --load-file
53 // --leds
54 // --trigger-interval
55 // --physcis-coincidence
56 // --calib-coincidence
57 // --physcis-window
58 // --physcis-window
59 // --trigger-delay
60 // --time-marker-delay
61 // --dead-time
62 // --clock-conditioner-r0
63 // --clock-conditioner-r1
64 // --clock-conditioner-r8
65 // --clock-conditioner-r9
66 // --clock-conditioner-r11
67 // --clock-conditioner-r13
68 // --clock-conditioner-r14
69 // --clock-conditioner-r15
70 // ...
71
72protected:
73 map<uint16_t, uint32_t> fCounter;
74
75 FTM::Header fHeader;
76 FTM::FtuList fFtuList;
77 FTM::StaticData fStaticData;
78 FTM::DynamicData fDynamicData;
79 FTM::Error fError;
80
81 FTM::StaticData fBufStaticData;
82
83 virtual void UpdateFirstHeader()
84 {
85 // FIXME: Message() ?
86 Out() << endl << kBold << "First header received:" << endl;
87 Out() << fHeader;
88 if (fIsHexOutput)
89 Out() << Converter::GetHex<uint16_t>(fHeader, 16) << endl;
90 }
91
92 virtual void UpdateHeader()
93 {
94 // emit service with trigger counter from header
95 if (!fIsVerbose)
96 return;
97
98 if (fHeader.fType==FTM::kDynamicData && !fIsDynamicOut)
99 return;
100
101 Out() << endl << kBold << "Header received:" << endl;
102 Out() << fHeader;
103 if (fIsHexOutput)
104 Out() << Converter::GetHex<uint16_t>(fHeader, 16) << endl;
105 }
106
107 virtual void UpdateFtuList()
108 {
109 if (!fIsVerbose)
110 return;
111
112 Out() << endl << kBold << "FtuList received:" << endl;
113 Out() << fFtuList;
114 if (fIsHexOutput)
115 Out() << Converter::GetHex<uint16_t>(fFtuList, 16) << endl;
116 }
117
118 virtual void UpdateStaticData()
119 {
120 if (!fIsVerbose)
121 return;
122
123 Out() << endl << kBold << "Static data received:" << endl;
124 Out() << fStaticData;
125 if (fIsHexOutput)
126 Out() << Converter::GetHex<uint16_t>(fStaticData, 16) << endl;
127 }
128
129 virtual void UpdateDynamicData()
130 {
131 if (!fIsDynamicOut)
132 return;
133
134 Out() << endl << kBold << "Dynamic data received:" << endl;
135 Out() << fDynamicData;
136 if (fIsHexOutput)
137 Out() << Converter::GetHex<uint16_t>(fDynamicData, 16) << endl;
138 }
139
140 virtual void UpdateError()
141 {
142 if (!fIsVerbose)
143 return;
144
145 Out() << endl << kRed << "Error received:" << endl;
146 Out() << fError;
147 if (fIsHexOutput)
148 Out() << Converter::GetHex<uint16_t>(fError, 16) << endl;
149 }
150
151 virtual void UpdateCounter()
152 {
153 if (!fIsVerbose)
154 return;
155
156 if (!fIsDynamicOut)
157 return;
158
159 Out() << "Received: ";
160 Out() << "H=" << fCounter[FTM::kHeader] << " ";
161 Out() << "S=" << fCounter[FTM::kStaticData] << " ";
162 Out() << "D=" << fCounter[FTM::kDynamicData] << " ";
163 Out() << "F=" << fCounter[FTM::kFtuList] << " ";
164 Out() << "E=" << fCounter[FTM::kErrorList] << " ";
165 Out() << "R=" << fCounter[FTM::kRegister] << endl;
166 }
167
168 bool CheckConsistency(FTM::StaticData &data)
169 {
170 bool warn1 = false;
171 if (data.IsEnabled(FTM::StaticData::kPedestal) != (data.GetSequencePed() >0) ||
172 data.IsEnabled(FTM::StaticData::kLPint) != (data.GetSequenceLPint()>0) ||
173 data.IsEnabled(FTM::StaticData::kLPext) != (data.GetSequenceLPext()>0))
174 {
175 warn1 = true;
176 data.Enable(FTM::StaticData::kPedestal, data.GetSequencePed()>0);
177 data.Enable(FTM::StaticData::kLPint, data.GetSequenceLPint()>0);
178 data.Enable(FTM::StaticData::kLPext, data.GetSequenceLPext()>0);
179 }
180
181 bool warn2 = false;
182 const uint16_t ref = data[0].fPrescaling;
183 for (int i=1; i<40; i++)
184 {
185 if (data[i].fPrescaling != ref)
186 {
187 warn2 = true;
188 data[i].fPrescaling = ref;
189 }
190 }
191
192 if (warn1)
193 Warn("GeneralSettings not consistent with trigger sequence.");
194 if (warn2)
195 Warn("Prescaling not consistent for all boards.");
196
197 return !warn1 && !warn2;
198 }
199
200private:
201 void HandleReceivedData(const bs::error_code& err, size_t bytes_received, int /*type*/)
202 {
203 // Do not schedule a new read if the connection failed.
204 if (bytes_received==0 || err)
205 {
206 if (err==ba::error::eof)
207 Warn("Connection closed by remote host (FTM).");
208
209 // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
210 // 125: Operation canceled
211 if (err && err!=ba::error::eof && // Connection closed by remote host
212 err!=ba::error::basic_errors::not_connected && // Connection closed by remote host
213 err!=ba::error::basic_errors::operation_aborted) // Connection closed by us
214 {
215 ostringstream str;
216 str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
217 Error(str);
218 }
219 PostClose(err!=ba::error::basic_errors::operation_aborted);
220 return;
221 }
222
223 // If we have not yet received a header we expect one now
224 // This could be moved to a HandleReceivedHeader function
225 if (!fHasHeader)
226 {
227 if (bytes_received!=sizeof(FTM::Header))
228 {
229 ostringstream str;
230 str << "Excepted " << sizeof(FTM::Header) << " bytes (FTM::Header) but received " << bytes_received << ".";
231 Error(str);
232 PostClose(false);
233 return;
234 }
235
236 fHeader = fBuffer;
237
238 // Check the data integrity
239 if (fHeader.fDelimiter!=FTM::kDelimiterStart)
240 {
241 ostringstream str;
242 str << "Invalid header received: start delimiter wrong, received ";
243 str << hex << fHeader.fDelimiter << ", expected " << FTM::kDelimiterStart << ".";
244 Error(str);
245 PostClose(false);
246 return;
247 }
248
249 fHasHeader = true;
250
251 // Convert FTM state into FtmCtrl state
252 if (++fCounter[FTM::kHeader]==1)
253 UpdateFirstHeader();
254
255 UpdateCounter();
256 UpdateHeader();
257
258 // Start reading of data
259 switch (fHeader.fType)
260 {
261 case FTM::kStaticData:
262 case FTM::kDynamicData:
263 case FTM::kFtuList:
264 case FTM::kRegister:
265 case FTM::kErrorList:
266 // This is not very efficient because the space is reallocated
267 // maybe we can check if the capacity of the std::vector
268 // is ever decreased. If not, everythign is fine.
269 fBuffer.resize(fHeader.fDataSize);
270 AsyncRead(ba::buffer(fBuffer));
271 AsyncWait(fInTimeout, 50, &Connection::HandleReadTimeout);
272 return;
273
274 default:
275 ostringstream str;
276 str << "Unknonw type " << fHeader.fType << " in received header." << endl;
277 Error(str);
278 PostClose(false);
279 return;
280 }
281
282 return;
283 }
284
285 // Check the data integrity (check end delimiter)
286 if (ntohs(fBuffer.back())!=FTM::kDelimiterEnd)
287 {
288 ostringstream str;
289 str << "Invalid data received: end delimiter wrong, received ";
290 str << hex << ntohs(fBuffer.back()) << ", expected " << FTM::kDelimiterEnd << ".";
291 Error(str);
292 PostClose(false);
293 return;
294 }
295
296 // Remove end delimiter
297 fBuffer.pop_back();
298
299 try
300 {
301 // If we have already received a header this is the data now
302 // This could be moved to a HandleReceivedData function
303
304 fCounter[fHeader.fType]++;
305 UpdateCounter();
306
307 switch (fHeader.fType)
308 {
309 case FTM::kFtuList:
310 fFtuList = fBuffer;
311 UpdateFtuList();
312 break;
313
314 case FTM::kStaticData:
315 if (fCounter[FTM::kStaticData]==1)
316 {
317 // This check is only done at startup
318 FTM::StaticData data(fBuffer);
319 if (!CheckConsistency(data))
320 {
321 CmdSendStatDat(data);
322 break;
323 }
324 }
325
326 fStaticData = fBuffer;
327 UpdateStaticData();
328 break;
329
330 case FTM::kDynamicData:
331 fDynamicData = fBuffer;
332 UpdateDynamicData();
333 break;
334
335 case FTM::kRegister:
336 if (fIsVerbose)
337 {
338 Out() << endl << kBold << "Register received: " << endl;
339 Out() << "Addr: " << ntohs(fBuffer[0]) << endl;
340 Out() << "Value: " << ntohs(fBuffer[1]) << endl;
341 }
342 break;
343
344 case FTM::kErrorList:
345 fError = fBuffer;
346 UpdateError();
347 break;
348
349 default:
350 ostringstream str;
351 str << "Unknonw type " << fHeader.fType << " in header." << endl;
352 Error(str);
353 PostClose(false);
354 return;
355 }
356 }
357 catch (const logic_error &e)
358 {
359 ostringstream str;
360 str << "Exception converting buffer into data structure: " << e.what();
361 Error(str);
362 PostClose(false);
363 return;
364 }
365
366 fInTimeout.cancel();
367
368 //fHeader.clear();
369 fHasHeader = false;
370 fBuffer.resize(sizeof(FTM::Header)/2);
371 AsyncRead(ba::buffer(fBuffer));
372 }
373
374 // This is called when a connection was established
375 void ConnectionEstablished()
376 {
377 fCounter.clear();
378 fBufStaticData.clear();
379
380 fHeader.clear();
381 fHasHeader = false;
382 fBuffer.resize(sizeof(FTM::Header)/2);
383 AsyncRead(ba::buffer(fBuffer));
384
385// if (!fDefaultSetup.empty())
386// LoadStaticData(fDefaultSetup);
387
388 // Get a header and configdata!
389 CmdReqStatDat();
390
391 // get the DNA of the FTUs
392 CmdPing();
393 }
394
395 void HandleReadTimeout(const bs::error_code &error)
396 {
397 if (error==ba::error::basic_errors::operation_aborted)
398 return;
399
400 if (error)
401 {
402 ostringstream str;
403 str << "Read timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
404 Error(str);
405
406 PostClose();
407 return;
408
409 }
410
411 if (!is_open())
412 {
413 // For example: Here we could schedule a new accept if we
414 // would not want to allow two connections at the same time.
415 return;
416 }
417
418 // Check whether the deadline has passed. We compare the deadline
419 // against the current time since a new asynchronous operation
420 // may have moved the deadline before this actor had a chance
421 // to run.
422 if (fInTimeout.expires_at() > ba::deadline_timer::traits_type::now())
423 return;
424
425 Error("Timeout reading data from "+URL());
426
427 PostClose();
428 }
429
430
431 template<size_t N>
432 void PostCmd(array<uint16_t, N> dat, uint16_t u1=0, uint16_t u2=0, uint16_t u3=0, uint16_t u4=0)
433 {
434 array<uint16_t, 5> cmd = {{ '@', u1, u2, u3, u4 }};
435
436 ostringstream msg;
437 msg << "Sending command:" << hex;
438 msg << " 0x" << setw(4) << setfill('0') << cmd[0];
439 msg << " 0x" << setw(4) << setfill('0') << u1;
440 msg << " 0x" << setw(4) << setfill('0') << u2;
441 msg << " 0x" << setw(4) << setfill('0') << u3;
442 msg << " 0x" << setw(4) << setfill('0') << u4;
443 msg << " (+" << dec << dat.size() << " words)";
444 Message(msg);
445
446 vector<uint16_t> out(cmd.size()+dat.size());
447
448 transform(cmd.begin(), cmd.end(), out.begin(), htons);
449 transform(dat.begin(), dat.end(), out.begin()+cmd.size(), htons);
450
451 PostMessage(out);
452 }
453
454 void PostCmd(vector<uint16_t> dat, uint16_t u1=0, uint16_t u2=0, uint16_t u3=0, uint16_t u4=0)
455 {
456 array<uint16_t, 5> cmd = {{ '@', u1, u2, u3, u4 }};
457
458 ostringstream msg;
459 msg << "Sending command:" << hex;
460 msg << " 0x" << setw(4) << setfill('0') << cmd[0];
461 msg << " 0x" << setw(4) << setfill('0') << u1;
462 msg << " 0x" << setw(4) << setfill('0') << u2;
463 msg << " 0x" << setw(4) << setfill('0') << u3;
464 msg << " 0x" << setw(4) << setfill('0') << u4;
465 msg << " (+" << dec << dat.size() << " words)";
466 Message(msg);
467
468 vector<uint16_t> out(cmd.size()+dat.size());
469
470 transform(cmd.begin(), cmd.end(), out.begin(), htons);
471 copy(dat.begin(), dat.end(), out.begin()+cmd.size());
472
473 PostMessage(out);
474 }
475
476 void PostCmd(uint16_t u1=0, uint16_t u2=0, uint16_t u3=0, uint16_t u4=0)
477 {
478 PostCmd(array<uint16_t, 0>(), u1, u2, u3, u4);
479 }
480public:
481
482// static const uint16_t kMaxAddr;
483
484public:
485 ConnectionFTM(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()),
486 fIsVerbose(true), fIsDynamicOut(true), fIsHexOutput(true)
487 {
488 SetLogStream(&imp);
489 }
490
491 void CmdToggleLed()
492 {
493 PostCmd(FTM::kCmdToggleLed);
494 }
495
496 void CmdPing()
497 {
498 PostCmd(FTM::kCmdPing);
499 }
500
501 void CmdReqDynDat()
502 {
503 PostCmd(FTM::kCmdRead, FTM::kCmdDynamicData);
504 }
505
506 void CmdReqStatDat()
507 {
508 PostCmd(FTM::kCmdRead, FTM::kCmdStaticData);
509 }
510
511 void CmdSendStatDat(const FTM::StaticData &data)
512 {
513 fBufStaticData = data;
514
515 PostCmd(data.HtoN(), FTM::kCmdWrite, FTM::kCmdStaticData);
516
517 // Request the changed configuration to ensure the
518 // change is distributed in the network
519 CmdReqStatDat();
520 }
521
522 void CmdStartRun()
523 {
524 PostCmd(FTM::kCmdStartRun, FTM::kStartRun);
525
526 // Update state information by requesting a new header
527 CmdGetRegister(0);
528 }
529
530 void CmdStopRun()
531 {
532 PostCmd(FTM::kCmdStopRun);
533
534 // Update state information by requesting a new header
535 CmdGetRegister(0);
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 fBufStaticData.clear();
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
582 return true;
583 }
584
585 bool CmdResetCamera()
586 {
587 PostCmd(FTM::kCmdCrateReset, FTM::kResetCrate0);
588 PostCmd(FTM::kCmdCrateReset, FTM::kResetCrate1);
589 PostCmd(FTM::kCmdCrateReset, FTM::kResetCrate2);
590 PostCmd(FTM::kCmdCrateReset, FTM::kResetCrate3);
591
592 return true;
593 }
594
595 bool CmdDisableReports(bool b)
596 {
597 PostCmd(FTM::kCmdDisableReports, b ? uint16_t(0) : uint16_t(1));
598 return true;
599 }
600
601 void SetVerbose(bool b)
602 {
603 fIsVerbose = b;
604 }
605
606 void SetHexOutput(bool b)
607 {
608 fIsHexOutput = b;
609 }
610
611 void SetDynamicOut(bool b)
612 {
613 fIsDynamicOut = b;
614 }
615/*
616 void SetDefaultSetup(const string &file)
617 {
618 fDefaultSetup = file;
619 }
620*/
621
622 bool LoadStaticData(string name)
623 {
624 if (name.rfind(".bin")!=name.length()-4)
625 name += ".bin";
626
627 ifstream fin(name);
628 if (!fin)
629 return false;
630
631 FTM::StaticData data;
632
633 fin.read(reinterpret_cast<char*>(&data), sizeof(FTM::StaticData));
634
635 if (fin.gcount()<streamsize(sizeof(FTM::StaticData)))
636 return false;
637
638 if (fin.fail() || fin.eof())
639 return false;
640
641 if (fin.peek()!=-1)
642 return false;
643
644 CmdSendStatDat(data);
645
646 return true;
647 }
648
649 bool SaveStaticData(string name) const
650 {
651 if (name.rfind(".bin")!=name.length()-4)
652 name += ".bin";
653
654 ofstream fout(name);
655 if (!fout)
656 return false;
657
658 fout.write(reinterpret_cast<const char*>(&fStaticData), sizeof(FTM::StaticData));
659
660 return !fout.bad();
661 }
662
663 bool SetThreshold(int32_t patch, int32_t value)
664 {
665 if (patch>159)
666 return false;
667
668 if (value<0 || value>0xffff)
669 return false;
670
671 FTM::StaticData data(fStaticData);
672
673 if (patch<0)
674 {
675 bool ident = true;
676 for (int i=0; i<160; i++)
677 if (data[i/4].fDAC[patch%4] != value)
678 {
679 ident = false;
680 break;
681 }
682
683 if (ident)
684 return true;
685
686 for (int i=0; i<160; i++)
687 data[i/4].fDAC[i%4] = value;
688 }
689 else
690 {
691 if (data[patch/4].fDAC[patch%4] == value)
692 return true;
693
694 data[patch/4].fDAC[patch%4] = value;
695 }
696
697 // Maybe move to a "COMMIT" command?
698 CmdSendStatDat(data);
699
700 return true;
701 }
702
703 bool SetPrescaling(uint32_t value)
704 {
705 if (value>0xffff)
706 return false;
707
708 FTM::StaticData data(fStaticData);
709
710 bool ident = true;
711 for (int i=0; i<40; i++)
712 if (data[i].fPrescaling != value)
713 {
714 ident = false;
715 break;
716 }
717
718 if (ident)
719 return true;
720
721 data.SetPrescaling(value);
722
723 // Maybe move to a "COMMIT" command?
724 CmdSendStatDat(data);
725
726 return true;
727 }
728
729 bool EnableFTU(int32_t board, bool enable)
730 {
731 if (board>39)
732 return false;
733
734 FTM::StaticData data(fStaticData);
735
736 if (board<0)
737 {
738 if (enable)
739 data.EnableAllFTU();
740 else
741 data.DisableAllFTU();
742 }
743 else
744 {
745 if (enable)
746 data.EnableFTU(board);
747 else
748 data.DisableFTU(board);
749
750 }
751
752 // Maybe move to a "COMMIT" command?
753 CmdSendStatDat(data);
754
755 return true;
756 }
757
758 bool ToggleFTU(uint32_t board)
759 {
760 if (board>39)
761 return false;
762
763 FTM::StaticData data(fStaticData);
764
765 data.ToggleFTU(board);
766
767 // Maybe move to a "COMMIT" command?
768 CmdSendStatDat(data);
769
770 return true;
771 }
772
773 bool SetVal(uint16_t *dest, uint32_t val, uint32_t max)
774 {
775 if (val>max)
776 return false;
777
778 if (*dest==val)
779 return true;
780
781 FTM::StaticData data(fStaticData);
782
783 dest = reinterpret_cast<uint16_t*>(&data) + (dest - reinterpret_cast<uint16_t*>(&fStaticData));
784
785 *dest = val;
786
787 CmdSendStatDat(data);
788
789 return true;
790 }
791
792 bool SetTriggerInterval(uint32_t val)
793 {
794 return SetVal(&fStaticData.fTriggerInterval, val,
795 FTM::StaticData::kMaxTriggerInterval);
796 }
797
798 bool SetTriggerDelay(uint32_t val)
799 {
800 return SetVal(&fStaticData.fDelayTrigger, val,
801 FTM::StaticData::kMaxDelayTrigger);
802 }
803
804 bool SetTimeMarkerDelay(uint32_t val)
805 {
806 return SetVal(&fStaticData.fDelayTimeMarker, val,
807 FTM::StaticData::kMaxDelayTimeMarker);
808 }
809
810 bool SetDeadTime(uint32_t val)
811 {
812 return SetVal(&fStaticData.fDeadTime, val,
813 FTM::StaticData::kMaxDeadTime);
814 }
815
816 void Enable(FTM::StaticData::GeneralSettings type, bool enable)
817 {
818 //if (fStaticData.IsEnabled(type)==enable)
819 // return;
820
821 FTM::StaticData data(fStaticData);
822 data.Enable(type, enable);
823 CmdSendStatDat(data);
824 }
825
826 bool SetTriggerSeq(const uint16_t d[3])
827 {
828 if (d[0]>FTM::StaticData::kMaxSequence ||
829 d[1]>FTM::StaticData::kMaxSequence ||
830 d[2]>FTM::StaticData::kMaxSequence)
831 return false;
832
833 FTM::StaticData data(fStaticData);
834
835 /*
836 data.Enable(FTM::StaticData::kPedestal, d[0]>0);
837 data.Enable(FTM::StaticData::kLPext, d[1]>0);
838 data.Enable(FTM::StaticData::kLPint, d[2]>0);
839 */
840
841 data.SetSequence(d[0], d[2], d[1]);
842
843 //if (fStaticData.fTriggerSeq !=data.fTriggerSequence ||
844 // fStaticData.fGeneralSettings!=data.fGeneralSettings)
845 // CmdSendStatDat(data);
846
847 CmdSendStatDat(data);
848
849 return true;
850 }
851
852 bool SetTriggerMultiplicity(uint16_t n)
853 {
854 if (n==0 || n>FTM::StaticData::kMaxMultiplicity)
855 return false;
856
857 if (n==fStaticData.fMultiplicityPhysics)
858 return true;
859
860 FTM::StaticData data(fStaticData);
861
862 data.fMultiplicityPhysics = n;
863
864 CmdSendStatDat(data);
865
866 return true;
867 }
868
869 bool SetTriggerWindow(uint16_t win)
870 {
871 if (win>FTM::StaticData::kMaxWindow)
872 return false;
873
874 if (win==fStaticData.fWindowPhysics)
875 return true;
876
877 FTM::StaticData data(fStaticData);
878
879 data.fWindowPhysics = win;
880
881 CmdSendStatDat(data);
882
883 return true;
884 }
885
886 bool SetCalibMultiplicity(uint16_t n)
887 {
888 if (n==0 || n>FTM::StaticData::kMaxMultiplicity)
889 return false;
890
891 if (n==fStaticData.fMultiplicityCalib)
892 return true;
893
894 FTM::StaticData data(fStaticData);
895
896 data.fMultiplicityCalib = n;
897
898 CmdSendStatDat(data);
899
900 return true;
901 }
902
903 bool SetCalibWindow(uint16_t win)
904 {
905 if (win>FTM::StaticData::kMaxWindow)
906 return false;
907
908 if (win==fStaticData.fWindowCalib)
909 return true;
910
911 FTM::StaticData data(fStaticData);
912
913 data.fWindowCalib = win;
914
915 CmdSendStatDat(data);
916
917 return true;
918 }
919
920 bool SetClockRegister(const uint64_t reg[])
921 {
922 FTM::StaticData data(fStaticData);
923
924 for (int i=0; i<8; i++)
925 if (reg[i]>0xffffffff)
926 return false;
927
928 data.SetClockRegister(reg);
929
930 CmdSendStatDat(data);
931
932 return true;
933 }
934
935 bool EnablePixel(int16_t idx, bool enable)
936 {
937 if (idx<-1 || idx>FTM::StaticData::kMaxPixelIdx)
938 return false;
939
940 FTM::StaticData data(fStaticData);
941
942 if (idx==-1)
943 for (int i=0; i<=FTM::StaticData::kMaxPixelIdx; i++)
944 data.EnablePixel(i, enable);
945 else
946 data.EnablePixel(idx, enable);
947
948 CmdSendStatDat(data);
949
950 return true;
951 }
952
953 bool DisableAllPixelsExcept(uint16_t idx)
954 {
955 if (idx>FTM::StaticData::kMaxPixelIdx)
956 return false;
957
958 FTM::StaticData data(fStaticData);
959
960 for (int i=0; i<=FTM::StaticData::kMaxPixelIdx; i++)
961 data.EnablePixel(i, i==idx);
962
963 CmdSendStatDat(data);
964
965 return true;
966 }
967
968 bool DisableAllPatchesExcept(uint16_t idx)
969 {
970 if (idx>FTM::StaticData::kMaxPatchIdx)
971 return false;
972
973 FTM::StaticData data(fStaticData);
974
975 for (int i=0; i<=FTM::StaticData::kMaxPixelIdx; i++)
976 data.EnablePixel(i, i/9==idx);
977
978 CmdSendStatDat(data);
979
980 return true;
981 }
982
983 bool TogglePixel(uint16_t idx)
984 {
985 if (idx>FTM::StaticData::kMaxPixelIdx)
986 return false;
987
988 FTM::StaticData data(fStaticData);
989
990 data.EnablePixel(idx, !fStaticData.Enabled(idx));
991
992 CmdSendStatDat(data);
993
994 return true;
995 }
996
997 States GetState() const
998 {
999 if (!IsConnected())
1000 return kDisconnected;
1001
1002 switch (fHeader.fState)
1003 {
1004 case FTM::kFtmUndefined:
1005 return kConnected;
1006
1007 case FTM::kFtmRunning:
1008 case FTM::kFtmCalib:
1009 return kTakingData;
1010
1011 case FTM::kFtmIdle:
1012 case FTM::kFtmConfig:
1013 return fStaticData == fBufStaticData ? kConfigured : kIdle;
1014 }
1015
1016 throw runtime_error("ConnectionFTM::GetState - Impossible code reached.");
1017 }
1018
1019 int GetCounter(FTM::Types type) { return fCounter[type]; }
1020
1021 const FTM::StaticData &GetStaticData() const { return fStaticData; }
1022};
1023
1024//const uint16_t ConnectionFTM::kMaxAddr = 0xfff;
1025
1026// ------------------------------------------------------------------------
1027
1028#include "DimDescriptionService.h"
1029
1030class ConnectionDimFTM : public ConnectionFTM
1031{
1032private:
1033
1034 DimDescribedService fDimPassport;
1035 DimDescribedService fDimTriggerCounter;
1036 DimDescribedService fDimError;
1037 DimDescribedService fDimFtuList;
1038 DimDescribedService fDimStaticData;
1039 DimDescribedService fDimDynamicData;
1040 DimDescribedService fDimCounter;
1041
1042 void UpdateFirstHeader()
1043 {
1044 ConnectionFTM::UpdateFirstHeader();
1045
1046 const FTM::DimPassport data(fHeader);
1047 fDimPassport.Update(data);
1048 }
1049
1050 void UpdateHeader()
1051 {
1052 ConnectionFTM::UpdateHeader();
1053
1054 if (fHeader.fType!=FTM::kDynamicData)
1055 return;
1056
1057 const FTM::DimTriggerCounter data(fHeader);
1058 fDimTriggerCounter.Update(data);
1059 }
1060
1061 void UpdateFtuList()
1062 {
1063 ConnectionFTM::UpdateFtuList();
1064
1065 const FTM::DimFtuList data(fHeader, fFtuList);
1066 fDimFtuList.Update(data);
1067 }
1068
1069 void UpdateStaticData()
1070 {
1071 ConnectionFTM::UpdateStaticData();
1072
1073 const FTM::DimStaticData data(fHeader, fStaticData);
1074 fDimStaticData.Update(data);
1075 }
1076
1077 void UpdateDynamicData()
1078 {
1079 ConnectionFTM::UpdateDynamicData();
1080
1081 const FTM::DimDynamicData data(fHeader, fDynamicData);
1082 fDimDynamicData.Update(data);
1083 }
1084
1085 void UpdateError()
1086 {
1087 ConnectionFTM::UpdateError();
1088
1089 const FTM::DimError data(fHeader, fError);
1090 fDimError.Update(data);
1091 }
1092
1093 void UpdateCounter()
1094 {
1095 ConnectionFTM::UpdateCounter();
1096
1097 const uint32_t counter[6] =
1098 {
1099 fCounter[FTM::kHeader],
1100 fCounter[FTM::kStaticData],
1101 fCounter[FTM::kDynamicData],
1102 fCounter[FTM::kFtuList],
1103 fCounter[FTM::kErrorList],
1104 fCounter[FTM::kRegister],
1105 };
1106
1107 fDimCounter.Update(counter);
1108 }
1109
1110public:
1111 ConnectionDimFTM(ba::io_service& ioservice, MessageImp &imp) :
1112 ConnectionFTM(ioservice, imp),
1113 fDimPassport ("FTM_CONTROL/PASSPORT", "X:1;S:1", ""),
1114 fDimTriggerCounter("FTM_CONTROL/TRIGGER_COUNTER", "X:1;I:1", ""),
1115 fDimError ("FTM_CONTROL/ERROR", "X:1;S:1;S:28", ""),
1116 fDimFtuList ("FTM_CONTROL/FTU_LIST", "X:1;X:1;S:1;C:4;X:40;C:40;C:40", ""),
1117 fDimStaticData ("FTM_CONTROL/STATIC_DATA", "X:1;S:1;S:1;X:1;S:1;S:3;S:1;S:1;S:1;S:1;S:1;S:1;I:1;I:8;S:90;S:160;S:40;S:40", ""),
1118 fDimDynamicData ("FTM_CONTROL/DYNAMIC_DATA", "X:1;X:1;F:4;I:160;I:40;S:40;S:40", ""),
1119 fDimCounter ("FTM_CONTROL/COUNTER", "I:6", "")
1120 {
1121 }
1122
1123 // 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
1124};
1125
1126// ------------------------------------------------------------------------
1127
1128template <class T, class S>
1129class StateMachineFTM : public T, public ba::io_service, public ba::io_service::work
1130{
1131 int Wrap(boost::function<void()> f)
1132 {
1133 f();
1134 return T::GetCurrentState();
1135 }
1136
1137 boost::function<int(const EventImp &)> Wrapper(boost::function<void()> func)
1138 {
1139 return boost::bind(&StateMachineFTM::Wrap, this, func);
1140 }
1141
1142private:
1143 S fFTM;
1144
1145 bool CheckEventSize(size_t has, const char *name, size_t size)
1146 {
1147 if (has==size)
1148 return true;
1149
1150 ostringstream msg;
1151 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
1152 T::Fatal(msg);
1153 return false;
1154 }
1155
1156 int SetRegister(const EventImp &evt)
1157 {
1158 if (!CheckEventSize(evt.GetSize(), "SetRegister", 8))
1159 return T::kSM_FatalError;
1160
1161 const uint32_t *dat = evt.Ptr<uint32_t>();
1162
1163 if (dat[1]>uint16_t(-1))
1164 {
1165 ostringstream msg;
1166 msg << hex << "Value " << dat[1] << " out of range.";
1167 T::Error(msg);
1168 return T::GetCurrentState();
1169 }
1170
1171
1172 if (dat[0]>uint16_t(-1) || !fFTM.CmdSetRegister(dat[0], dat[1]))
1173 {
1174 ostringstream msg;
1175 msg << hex << "Address " << dat[0] << " out of range.";
1176 T::Error(msg);
1177 }
1178
1179 return T::GetCurrentState();
1180 }
1181
1182 int GetRegister(const EventImp &evt)
1183 {
1184 if (!CheckEventSize(evt.GetSize(), "GetRegister", 4))
1185 return T::kSM_FatalError;
1186
1187 const unsigned int addr = evt.GetInt();
1188 if (addr>uint16_t(-1) || !fFTM.CmdGetRegister(addr))
1189 {
1190 ostringstream msg;
1191 msg << hex << "Address " << addr << " out of range.";
1192 T::Error(msg);
1193 }
1194
1195 return T::GetCurrentState();
1196 }
1197
1198 int TakeNevents(const EventImp &evt)
1199 {
1200 if (!CheckEventSize(evt.GetSize(), "TakeNevents", 4))
1201 return T::kSM_FatalError;
1202
1203 const unsigned int dat = evt.GetUInt();
1204
1205 /*
1206 if (dat[1]>uint32_t(-1))
1207 {
1208 ostringstream msg;
1209 msg << hex << "Value " << dat[1] << " out of range.";
1210 T::Error(msg);
1211 return T::GetCurrentState();
1212 }*/
1213
1214 fFTM.CmdTakeNevents(dat);
1215
1216 return T::GetCurrentState();
1217 }
1218
1219 int DisableReports(const EventImp &evt)
1220 {
1221 if (!CheckEventSize(evt.GetSize(), "DisableReports", 1))
1222 return T::kSM_FatalError;
1223
1224 fFTM.CmdDisableReports(evt.GetBool());
1225
1226 return T::GetCurrentState();
1227 }
1228
1229 int SetVerbosity(const EventImp &evt)
1230 {
1231 if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
1232 return T::kSM_FatalError;
1233
1234 fFTM.SetVerbose(evt.GetBool());
1235
1236 return T::GetCurrentState();
1237 }
1238
1239 int SetHexOutput(const EventImp &evt)
1240 {
1241 if (!CheckEventSize(evt.GetSize(), "SetHexOutput", 1))
1242 return T::kSM_FatalError;
1243
1244 fFTM.SetHexOutput(evt.GetBool());
1245
1246 return T::GetCurrentState();
1247 }
1248
1249 int SetDynamicOut(const EventImp &evt)
1250 {
1251 if (!CheckEventSize(evt.GetSize(), "SetDynamicOut", 1))
1252 return T::kSM_FatalError;
1253
1254 fFTM.SetDynamicOut(evt.GetBool());
1255
1256 return T::GetCurrentState();
1257 }
1258
1259 int LoadStaticData(const EventImp &evt)
1260 {
1261 if (fFTM.LoadStaticData(evt.GetString()))
1262 return T::GetCurrentState();
1263
1264 ostringstream msg;
1265 msg << "Loading static data from file '" << evt.GetString() << "' failed ";
1266
1267 if (errno)
1268 msg << "(" << strerror(errno) << ")";
1269 else
1270 msg << "(wrong size, expected " << sizeof(FTM::StaticData) << " bytes)";
1271
1272 T::Warn(msg);
1273
1274 return T::GetCurrentState();
1275 }
1276
1277 int SaveStaticData(const EventImp &evt)
1278 {
1279 if (fFTM.SaveStaticData(evt.GetString()))
1280 return T::GetCurrentState();
1281
1282 ostringstream msg;
1283 msg << "Writing static data to file '" << evt.GetString() << "' failed ";
1284 msg << "(" << strerror(errno) << ")";
1285
1286 T::Warn(msg);
1287
1288 return T::GetCurrentState();
1289 }
1290
1291 int SetThreshold(const EventImp &evt)
1292 {
1293 if (!CheckEventSize(evt.GetSize(), "SetThreshold", 8))
1294 return T::kSM_FatalError;
1295
1296 const int32_t *data = evt.Ptr<int32_t>();
1297
1298 if (!fFTM.SetThreshold(data[0], data[1]))
1299 T::Warn("SetThreshold - Maximum allowed patch number 159, valid value range 0-0xffff");
1300
1301 return T::GetCurrentState();
1302 }
1303
1304 int EnableFTU(const EventImp &evt)
1305 {
1306 if (!CheckEventSize(evt.GetSize(), "EnableFTU", 5))
1307 return T::kSM_FatalError;
1308
1309 const int32_t &board = evt.Get<int32_t>();
1310 const int8_t &enable = evt.Get<int8_t>(4);
1311
1312 if (!fFTM.EnableFTU(board, enable))
1313 T::Warn("EnableFTU - Board number must be <40.");
1314
1315 return T::GetCurrentState();
1316 }
1317
1318 int ToggleFTU(const EventImp &evt)
1319 {
1320 if (!CheckEventSize(evt.GetSize(), "ToggleFTU", 4))
1321 return T::kSM_FatalError;
1322
1323 if (!fFTM.ToggleFTU(evt.GetInt()))
1324 T::Warn("ToggleFTU - Allowed range of boards 0-39.");
1325
1326 return T::GetCurrentState();
1327 }
1328
1329 int SetTriggerInterval(const EventImp &evt)
1330 {
1331 if (!CheckEventSize(evt.GetSize(), "SetTriggerInterval", 4))
1332 return T::kSM_FatalError;
1333
1334 if (!fFTM.SetTriggerInterval(evt.GetInt()))
1335 T::Warn("SetTriggerInterval - Value out of range.");
1336
1337 return T::GetCurrentState();
1338 }
1339
1340 int SetTriggerDelay(const EventImp &evt)
1341 {
1342 if (!CheckEventSize(evt.GetSize(), "SetTriggerDelay", 4))
1343 return T::kSM_FatalError;
1344
1345 if (!fFTM.SetTriggerDelay(evt.GetInt()))
1346 T::Warn("SetTriggerDealy - Value out of range.");
1347
1348 return T::GetCurrentState();
1349 }
1350
1351 int SetTimeMarkerDelay(const EventImp &evt)
1352 {
1353 if (!CheckEventSize(evt.GetSize(), "SetTimeMarkerDelay", 4))
1354 return T::kSM_FatalError;
1355
1356 if (!fFTM.SetTimeMarkerDelay(evt.GetInt()))
1357 T::Warn("SetTimeMarkerDelay - Value out of range.");
1358
1359 return T::GetCurrentState();
1360 }
1361
1362 int SetPrescaling(const EventImp &evt)
1363 {
1364 if (!CheckEventSize(evt.GetSize(), "SetPrescaling", 4))
1365 return T::kSM_FatalError;
1366
1367 if (!fFTM.SetPrescaling(evt.GetInt()-1))
1368 T::Warn("SetPrescaling - Value out of range.");
1369
1370 return T::GetCurrentState();
1371 }
1372
1373 int SetTriggerSeq(const EventImp &evt)
1374 {
1375 if (!CheckEventSize(evt.GetSize(), "SetTriggerSeq", 6))
1376 return T::kSM_FatalError;
1377
1378 const uint16_t *data = evt.Ptr<uint16_t>();
1379
1380 if (!fFTM.SetTriggerSeq(data))
1381 T::Warn("SetTriggerSeq - Value out of range.");
1382
1383 return T::GetCurrentState();
1384 }
1385
1386 int SetDeadTime(const EventImp &evt)
1387 {
1388 if (!CheckEventSize(evt.GetSize(), "SetDeadTime", 4))
1389 return T::kSM_FatalError;
1390
1391 if (!fFTM.SetDeadTime(evt.GetInt()))
1392 T::Warn("SetDeadTime - Value out of range.");
1393
1394 return T::GetCurrentState();
1395 }
1396
1397 int SetTriggerMultiplicity(const EventImp &evt)
1398 {
1399 if (!CheckEventSize(evt.GetSize(), "SetTriggerMultiplicity", 2))
1400 return T::kSM_FatalError;
1401
1402 if (!fFTM.SetTriggerMultiplicity(evt.GetUShort()))
1403 T::Warn("SetTriggerMultiplicity - Value out of range.");
1404
1405 return T::GetCurrentState();
1406 }
1407
1408 int SetCalibMultiplicity(const EventImp &evt)
1409 {
1410 if (!CheckEventSize(evt.GetSize(), "SetCalibMultiplicity", 2))
1411 return T::kSM_FatalError;
1412
1413 if (!fFTM.SetCalibMultiplicity(evt.GetUShort()))
1414 T::Warn("SetCalibMultiplicity - Value out of range.");
1415
1416 return T::GetCurrentState();
1417 }
1418
1419 int SetTriggerWindow(const EventImp &evt)
1420 {
1421 if (!CheckEventSize(evt.GetSize(), "SetTriggerWindow", 2))
1422 return T::kSM_FatalError;
1423
1424 if (!fFTM.SetTriggerWindow(evt.GetUShort()))
1425 T::Warn("SetTriggerWindow - Value out of range.");
1426
1427 return T::GetCurrentState();
1428 }
1429
1430 int SetCalibWindow(const EventImp &evt)
1431 {
1432 if (!CheckEventSize(evt.GetSize(), "SetCalibWindow", 2))
1433 return T::kSM_FatalError;
1434
1435 if (!fFTM.SetCalibWindow(evt.GetUShort()))
1436 T::Warn("SetCalibWindow - Value out of range.");
1437
1438 return T::GetCurrentState();
1439 }
1440
1441 int SetClockRegister(const EventImp &evt)
1442 {
1443 if (!CheckEventSize(evt.GetSize(), "SetClockRegister", 8*8))
1444 return T::kSM_FatalError;
1445
1446 const uint64_t *reg = evt.Ptr<uint64_t>();
1447
1448 if (!fFTM.SetClockRegister(reg))
1449 T::Warn("SetClockRegister - Value out of range.");
1450
1451 return T::GetCurrentState();
1452 }
1453
1454 int SetClockFrequency(const EventImp &evt)
1455 {
1456 if (!CheckEventSize(evt.GetSize(), "SetClockFrequency", 2))
1457 return T::kSM_FatalError;
1458
1459 const map<uint16_t,array<uint64_t, 8>>::const_iterator it =
1460 fClockCondSetup.find(evt.GetUShort());
1461
1462 if (it==fClockCondSetup.end())
1463 {
1464 T::Warn("SetClockFrequency - Frequency not supported.");
1465 return T::GetCurrentState();
1466 }
1467
1468 if (!fFTM.SetClockRegister(it->second.data()))
1469 T::Warn("SetClockFrequency - Register values out of range.");
1470
1471 return T::GetCurrentState();
1472 }
1473
1474 int Enable(const EventImp &evt, FTM::StaticData::GeneralSettings type)
1475 {
1476 if (!CheckEventSize(evt.GetSize(), "Enable", 1))
1477 return T::kSM_FatalError;
1478
1479 fFTM.Enable(type, evt.GetBool());
1480
1481 return T::GetCurrentState();
1482 }
1483
1484 int EnablePixel(const EventImp &evt, bool b)
1485 {
1486 if (!CheckEventSize(evt.GetSize(), "EnablePixel", 2))
1487 return T::kSM_FatalError;
1488
1489 if (!fFTM.EnablePixel(evt.GetUShort(), b))
1490 T::Warn("EnablePixel - Value out of range.");
1491
1492 return T::GetCurrentState();
1493 }
1494
1495 int DisableAllPixelsExcept(const EventImp &evt)
1496 {
1497 if (!CheckEventSize(evt.GetSize(), "DisableAllPixelsExcept", 2))
1498 return T::kSM_FatalError;
1499
1500 if (!fFTM.DisableAllPixelsExcept(evt.GetUShort()))
1501 T::Warn("DisableAllPixelsExcept - Value out of range.");
1502
1503 return T::GetCurrentState();
1504 }
1505
1506 int DisableAllPatchesExcept(const EventImp &evt)
1507 {
1508 if (!CheckEventSize(evt.GetSize(), "DisableAllPatchesExcept", 2))
1509 return T::kSM_FatalError;
1510
1511 if (!fFTM.DisableAllPatchesExcept(evt.GetUShort()))
1512 T::Warn("DisableAllPatchesExcept - Value out of range.");
1513
1514 return T::GetCurrentState();
1515 }
1516
1517 int TogglePixel(const EventImp &evt)
1518 {
1519 if (!CheckEventSize(evt.GetSize(), "TogglePixel", 2))
1520 return T::kSM_FatalError;
1521
1522 if (!fFTM.TogglePixel(evt.GetUShort()))
1523 T::Warn("TogglePixel - Value out of range.");
1524
1525 return T::GetCurrentState();
1526 }
1527
1528 int ResetCrate(const EventImp &evt)
1529 {
1530 if (!CheckEventSize(evt.GetSize(), "ResetCrate", 2))
1531 return T::kSM_FatalError;
1532
1533 fFTM.CmdResetCrate(evt.GetUShort());
1534
1535 return T::GetCurrentState();
1536 }
1537
1538 int Disconnect()
1539 {
1540 // Close all connections
1541 fFTM.PostClose(false);
1542
1543 /*
1544 // Now wait until all connection have been closed and
1545 // all pending handlers have been processed
1546 poll();
1547 */
1548
1549 return T::GetCurrentState();
1550 }
1551
1552 int Reconnect(const EventImp &evt)
1553 {
1554 // Close all connections to supress the warning in SetEndpoint
1555 fFTM.PostClose(false);
1556
1557 // Now wait until all connection have been closed and
1558 // all pending handlers have been processed
1559 poll();
1560
1561 if (evt.GetBool())
1562 fFTM.SetEndpoint(evt.GetString());
1563
1564 // Now we can reopen the connection
1565 fFTM.PostClose(true);
1566
1567 return T::GetCurrentState();
1568 }
1569
1570 /*
1571 int Transition(const Event &evt)
1572 {
1573 switch (evt.GetTargetState())
1574 {
1575 case kDisconnected:
1576 case kConnected:
1577 }
1578
1579 return T::kSM_FatalError;
1580 }*/
1581
1582 int64_t fCounterReg;
1583 int64_t fCounterStat;
1584
1585 typedef map<string, FTM::StaticData> Configs;
1586 Configs fConfigs;
1587 Configs::const_iterator fTargetConfig;
1588
1589 int ConfigureFTM(const EventImp &evt)
1590 {
1591 const string name = evt.GetText();
1592
1593 fTargetConfig = fConfigs.find(name);
1594 if (fTargetConfig==fConfigs.end())
1595 {
1596 T::Error("ConfigureFTM - Run-type '"+name+"' not found.");
1597 return T::GetCurrentState();
1598 }
1599
1600 T::Message("Starting configuration for '"+name+"'");
1601
1602 fCounterReg = fFTM.GetCounter(FTM::kRegister);
1603 fFTM.CmdStopRun();
1604
1605 return FTM::kConfiguring1;
1606 }
1607
1608 int ResetConfig()
1609 {
1610 return fFTM.GetState();
1611 }
1612
1613 int Execute()
1614 {
1615 // Dispatch (execute) at most one handler from the queue. In contrary
1616 // to run_one(), it doesn't wait until a handler is available
1617 // which can be dispatched, so poll_one() might return with 0
1618 // handlers dispatched. The handlers are always dispatched/executed
1619 // synchronously, i.e. within the call to poll_one()
1620 poll_one();
1621
1622 // If FTM is neither in data taking nor idle,
1623 // leave configuration state
1624 switch (fFTM.GetState())
1625 {
1626 case ConnectionFTM::kDisconnected: return FTM::kDisconnected;
1627 case ConnectionFTM::kConnected: return FTM::kConnected;
1628 default:
1629 break;
1630 }
1631
1632 switch (T::GetCurrentState())
1633 {
1634 case FTM::kConfiguring1:
1635 // If FTM has received an anwer to the stop_run command
1636 // the counter for the registers has been increased
1637 if (fFTM.GetCounter(FTM::kRegister)<=fCounterReg)
1638 break;
1639
1640 // If now the state is not idle as expected this means we had
1641 // an error (maybe old events waiting in the queue)
1642 if (fFTM.GetState()!=ConnectionFTM::kIdle &&
1643 fFTM.GetState()!=ConnectionFTM::kConfigured)
1644 return FTM::kConfigError1;
1645
1646 fCounterStat = fFTM.GetCounter(FTM::kStaticData);
1647
1648 T::Message("Trigger successfully disabled... sending new configuration.");
1649
1650 fFTM.CmdSendStatDat(fTargetConfig->second);
1651
1652 // Next state is: wait for the answer to our configuration
1653 return FTM::kConfiguring2;
1654
1655 case FTM::kConfiguring2:
1656 case FTM::kConfigured:
1657 // If FTM has received an anwer to the stop_run command
1658 // the counter for the registers has been increased
1659 if (fFTM.GetCounter(FTM::kStaticData)<=fCounterStat)
1660 break;
1661
1662 // If now the configuration is not what we expected
1663 // we had an error (maybe old events waiting in the queue?)
1664 // ======================
1665 if (fFTM.GetState()!=ConnectionFTM::kConfigured)
1666 return FTM::kConfigError2;
1667 // ======================
1668
1669 // Check configuration again when a new static data block
1670 // will be received
1671 fCounterStat = fFTM.GetCounter(FTM::kStaticData);
1672
1673 T::Message("Sending new configuration was successfull.");
1674
1675 // Next state is: wait for the answer to our configuration
1676 return FTM::kConfigured;
1677
1678 default:
1679 switch (fFTM.GetState())
1680 {
1681 case ConnectionFTM::kIdle: return FTM::kIdle;
1682 case ConnectionFTM::kConfigured: return FTM::kIdle;
1683 case ConnectionFTM::kTakingData: return FTM::kTakingData;
1684 default:
1685 throw runtime_error("StateMachienFTM - Execute() - Inavlid state.");
1686 }
1687 }
1688
1689 if (T::GetCurrentState()==FTM::kConfigured &&
1690 fFTM.GetState()==ConnectionFTM::kTakingData)
1691 return FTM::kTakingData;
1692
1693 return T::GetCurrentState();
1694 }
1695
1696public:
1697 StateMachineFTM(ostream &out=cout) :
1698 T(out, "FTM_CONTROL"), ba::io_service::work(static_cast<ba::io_service&>(*this)),
1699 fFTM(*this, *this)
1700 {
1701 // ba::io_service::work is a kind of keep_alive for the loop.
1702 // It prevents the io_service to go to stopped state, which
1703 // would prevent any consecutive calls to run()
1704 // or poll() to do nothing. reset() could also revoke to the
1705 // previous state but this might introduce some overhead of
1706 // deletion and creation of threads and more.
1707
1708 // State names
1709 T::AddStateName(FTM::kDisconnected, "Disconnected",
1710 "FTM board not connected via ethernet.");
1711
1712 T::AddStateName(FTM::kConnected, "Connected",
1713 "Ethernet connection to FTM established (no state received yet).");
1714
1715 T::AddStateName(FTM::kIdle, "Idle",
1716 "Ethernet connection to FTM established, FTM in idle state.");
1717
1718 T::AddStateName(FTM::kConfiguring1, "Configuring1",
1719 "Command to diable run sent... waiting for response.");
1720 T::AddStateName(FTM::kConfiguring2, "Configuring2",
1721 "New configuration sent... waiting for response.");
1722 T::AddStateName(FTM::kConfigured, "Configured",
1723 "Received answer identical with target configuration.");
1724
1725 T::AddStateName(FTM::kTakingData, "TakingData",
1726 "Ethernet connection to FTM established, FTM is in taking data state.");
1727
1728 T::AddStateName(FTM::kConfigError1, "ErrorInConfig1", "");
1729 T::AddStateName(FTM::kConfigError2, "ErrorInConfig2", "");
1730
1731 // FTM Commands
1732 T::AddEvent("TOGGLE_LED", FTM::kIdle)
1733 (Wrapper(boost::bind(&ConnectionFTM::CmdToggleLed, &fFTM)))
1734 ("toggle led");
1735
1736 T::AddEvent("PING", FTM::kIdle)
1737 (Wrapper(boost::bind(&ConnectionFTM::CmdPing, &fFTM)))
1738 ("send ping");
1739
1740 T::AddEvent("REQUEST_DYNAMIC_DATA", FTM::kIdle)
1741 (Wrapper(boost::bind(&ConnectionFTM::CmdReqDynDat, &fFTM)))
1742 ("request transmission of dynamic data block");
1743
1744 T::AddEvent("REQUEST_STATIC_DATA", FTM::kIdle)
1745 (Wrapper(boost::bind(&ConnectionFTM::CmdReqStatDat, &fFTM)))
1746 ("request transmission of static data from FTM to memory");
1747
1748 T::AddEvent("GET_REGISTER", "I", FTM::kIdle)
1749 (boost::bind(&StateMachineFTM::GetRegister, this, _1))
1750 ("read register from address addr"
1751 "|addr[short]:Address of register");
1752
1753 T::AddEvent("SET_REGISTER", "I:2", FTM::kIdle)
1754 (boost::bind(&StateMachineFTM::SetRegister, this, _1))
1755 ("set register to value"
1756 "|addr[short]:Address of register"
1757 "|val[short]:Value to be set");
1758
1759 T::AddEvent("START_RUN", FTM::kIdle, FTM::kConfigured)
1760 (Wrapper(boost::bind(&ConnectionFTM::CmdStartRun, &fFTM)))
1761 ("start a run (start distributing triggers)");
1762
1763 T::AddEvent("STOP_RUN", FTM::kTakingData)
1764 (Wrapper(boost::bind(&ConnectionFTM::CmdStopRun, &fFTM)))
1765 ("stop a run (stop distributing triggers)");
1766
1767 T::AddEvent("TAKE_N_EVENTS", "I", FTM::kIdle)
1768 (boost::bind(&StateMachineFTM::TakeNevents, this, _1))
1769 ("take n events (distribute n triggers)|number[int]:Number of events to be taken");
1770
1771 T::AddEvent("DISABLE_REPORTS", "B", FTM::kIdle)
1772 (boost::bind(&StateMachineFTM::DisableReports, this, _1))
1773 ("disable sending rate reports"
1774 "|status[bool]:disable or enable that the FTM sends rate reports (yes/no)");
1775
1776 T::AddEvent("SET_THRESHOLD", "I:2", FTM::kIdle)
1777 (boost::bind(&StateMachineFTM::SetThreshold, this, _1))
1778 ("Set the comparator threshold"
1779 "|Patch[idx]:Index of the patch (0-159), -1 for all"
1780 "|Threshold[counts]:Threshold to be set in binary counts");
1781
1782 T::AddEvent("SET_PRESCALING", "I:1", FTM::kIdle)
1783 (boost::bind(&StateMachineFTM::SetPrescaling, this, _1))
1784 (""
1785 "|[]:");
1786
1787 T::AddEvent("ENABLE_FTU", "I:1;B:1", FTM::kIdle)
1788 (boost::bind(&StateMachineFTM::EnableFTU, this, _1))
1789 ("Enable or disable FTU"
1790 "|Board[idx]:Index of the board (0-39), -1 for all"
1791 "|Enable[bool]:Whether FTU should be enabled or disabled (yes/no)");
1792
1793 T::AddEvent("DISABLE_PIXEL", "S:1", FTM::kIdle)
1794 (boost::bind(&StateMachineFTM::EnablePixel, this, _1, false))
1795 ("(-1 or all)");
1796
1797 T::AddEvent("ENABLE_PIXEL", "S:1", FTM::kIdle)
1798 (boost::bind(&StateMachineFTM::EnablePixel, this, _1, true))
1799 ("(-1 or all)");
1800
1801 T::AddEvent("DISABLE_ALL_PIXELS_EXCEPT", "S:1", FTM::kIdle)
1802 (boost::bind(&StateMachineFTM::DisableAllPixelsExcept, this, _1))
1803 ("");
1804
1805 T::AddEvent("DISABLE_ALL_PATCHES_EXCEPT", "S:1", FTM::kIdle)
1806 (boost::bind(&StateMachineFTM::DisableAllPatchesExcept, this, _1))
1807 ("");
1808
1809 T::AddEvent("TOGGLE_PIXEL", "S:1", FTM::kIdle)
1810 (boost::bind(&StateMachineFTM::TogglePixel, this, _1))
1811 ("");
1812
1813 T::AddEvent("TOGGLE_FTU", "I:1", FTM::kIdle)
1814 (boost::bind(&StateMachineFTM::ToggleFTU, this, _1))
1815 ("Toggle status of FTU (this is mainly meant to be used in the GUI)"
1816 "|Board[idx]:Index of the board (0-39)");
1817
1818 T::AddEvent("SET_TRIGGER_INTERVAL", "I:1", FTM::kIdle)
1819 (boost::bind(&StateMachineFTM::SetTriggerInterval, this, _1))
1820 ("Sets the trigger interval which is the distance between two consecutive artificial triggers."
1821 "|interval[int]:The applied trigger interval is: interval*4ns+8ns");
1822
1823 T::AddEvent("SET_TRIGGER_DELAY", "I:1", FTM::kIdle)
1824 (boost::bind(&StateMachineFTM::SetTriggerDelay, this, _1))
1825 (""
1826 "|delay[int]:The applied trigger delay is: delay*4ns+8ns");
1827
1828 T::AddEvent("SET_TIME_MARKER_DELAY", "I:1", FTM::kIdle)
1829 (boost::bind(&StateMachineFTM::SetTimeMarkerDelay, this, _1))
1830 (""
1831 "|delay[int]:The applied time marker delay is: delay*4ns+8ns");
1832
1833 T::AddEvent("SET_DEAD_TIME", "I:1", FTM::kIdle)
1834 (boost::bind(&StateMachineFTM::SetDeadTime, this, _1))
1835 (""
1836 "|dead_time[int]:The applied dead time is: dead_time*4ns+8ns");
1837
1838 T::AddEvent("ENABLE_TRIGGER", "B:1", FTM::kIdle)
1839 (boost::bind(&StateMachineFTM::Enable, this, _1, FTM::StaticData::kTrigger))
1840 ("Switch on the physics trigger"
1841 "|Enable[bool]:Enable physics trigger (yes/no)");
1842
1843 // FIXME: Switch on/off depending on sequence
1844 T::AddEvent("ENABLE_EXT1", "B:1", FTM::kIdle)
1845 (boost::bind(&StateMachineFTM::Enable, this, _1, FTM::StaticData::kExt1))
1846 ("Switch on the triggers through the first external line"
1847 "|Enable[bool]:Enable ext1 trigger (yes/no)");
1848
1849 // FIXME: Switch on/off depending on sequence
1850 T::AddEvent("ENABLE_EXT2", "B:1", FTM::kIdle)
1851 (boost::bind(&StateMachineFTM::Enable, this, _1, FTM::StaticData::kExt2))
1852 ("Switch on the triggers through the second external line"
1853 "|Enable[bool]:Enable ext2 trigger (yes/no)");
1854
1855 T::AddEvent("ENABLE_VETO", "B:1", FTM::kIdle)
1856 (boost::bind(&StateMachineFTM::Enable, this, _1, FTM::StaticData::kVeto))
1857 ("Enable veto line"
1858 "|Enable[bool]:Enable veto (yes/no)");
1859
1860 T::AddEvent("ENABLE_CLOCK_CONDITIONER", "B:1", FTM::kIdle)
1861 (boost::bind(&StateMachineFTM::Enable, this, _1, FTM::StaticData::kClockConditioner))
1862 ("Enable clock conidtioner output in favor of time marker output"
1863 "|Enable[bool]:Enable clock conditioner (yes/no)");
1864
1865 T::AddEvent("SET_TRIGGER_SEQUENCE", "S:3", FTM::kIdle)
1866 (boost::bind(&StateMachineFTM::SetTriggerSeq, this, _1))
1867 ("Setup the sequence of artificial triggers produced by the FTM"
1868 "|Ped[short]:number of pedestal triggers in a row"
1869 "|LPext[short]:number of triggers of the external light pulser"
1870 "|LPint[short]:number of triggers of the internal light pulser");
1871
1872 T::AddEvent("SET_TRIGGER_MULTIPLICITY", "S:1", FTM::kIdle)
1873 (boost::bind(&StateMachineFTM::SetTriggerMultiplicity, this, _1))
1874 ("Setup the Multiplicity condition for physcis triggers"
1875 "|N[int]:Number of requirered coincident triggers from sum-patches (1-40)");
1876
1877 T::AddEvent("SET_TRIGGER_WINDOW", "S:1", FTM::kIdle)
1878 (boost::bind(&StateMachineFTM::SetTriggerWindow, this, _1))
1879 ("");
1880
1881 T::AddEvent("SET_CALIBRATION_MULTIPLICITY", "S:1", FTM::kIdle)
1882 (boost::bind(&StateMachineFTM::SetCalibMultiplicity, this, _1))
1883 ("Setup the Multiplicity condition for artificial (calibration) triggers"
1884 "|N[int]:Number of requirered coincident triggers from sum-patches (1-40)");
1885
1886 T::AddEvent("SET_CALIBRATION_WINDOW", "S:1", FTM::kIdle)
1887 (boost::bind(&StateMachineFTM::SetCalibWindow, this, _1))
1888 ("");
1889
1890 T::AddEvent("SET_CLOCK_FREQUENCY", "S:1", FTM::kIdle)
1891 (boost::bind(&StateMachineFTM::SetClockFrequency, this, _1))
1892 ("");
1893
1894 T::AddEvent("SET_CLOCK_REGISTER", "X:8", FTM::kIdle)
1895 (boost::bind(&StateMachineFTM::SetClockRegister, this, _1))
1896 ("");
1897
1898 // A new configure will first stop the FTM this means
1899 // we can allow it in idle _and_ taking data
1900 T::AddEvent("CONFIGURE", "C", FTM::kIdle, FTM::kTakingData)
1901 (boost::bind(&StateMachineFTM::ConfigureFTM, this, _1))
1902 ("");
1903
1904 T::AddEvent("RESET_CONFIGURE", FTM::kConfiguring1, FTM::kConfiguring2, FTM::kConfigured, FTM::kConfigError1, FTM::kConfigError2)
1905 (boost::bind(&StateMachineFTM::ResetConfig, this))
1906 ("");
1907
1908
1909
1910 T::AddEvent("RESET_CRATE", "S:1", FTM::kIdle)
1911 (boost::bind(&StateMachineFTM::ResetCrate, this, _1))
1912 ("Reset one of the crates 0-3"
1913 "|crate[short]:Crate number to be reseted (0-3)");
1914
1915 T::AddEvent("RESET_CAMERA", FTM::kIdle)
1916 (Wrapper(boost::bind(&ConnectionFTM::CmdResetCamera, &fFTM)))
1917 ("Reset all crates. The commands are sent in the order 0,1,2,3");
1918
1919
1920 // Load/save static data block
1921 T::AddEvent("SAVE", "C", FTM::kIdle)
1922 (boost::bind(&StateMachineFTM::SaveStaticData, this, _1))
1923 ("Saves the static data (FTM configuration) from memory to a file"
1924 "|filename[string]:Filename (can include a path), .bin is automatically added");
1925
1926 T::AddEvent("LOAD", "C", FTM::kIdle)
1927 (boost::bind(&StateMachineFTM::LoadStaticData, this, _1))
1928 ("Loads the static data (FTM configuration) from a file into memory and sends it to the FTM"
1929 "|filename[string]:Filename (can include a path), .bin is automatically added");
1930
1931
1932
1933 // Verbosity commands
1934 T::AddEvent("SET_VERBOSE", "B")
1935 (boost::bind(&StateMachineFTM::SetVerbosity, this, _1))
1936 ("set verbosity state"
1937 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
1938
1939 T::AddEvent("SET_HEX_OUTPUT", "B")
1940 (boost::bind(&StateMachineFTM::SetHexOutput, this, _1))
1941 ("enable or disable hex output for received data"
1942 "|hexout[bool]:disable or enable hex output for received data (yes/no)");
1943
1944 T::AddEvent("SET_DYNAMIC_OUTPUT", "B")
1945 (boost::bind(&StateMachineFTM::SetDynamicOut, this, _1))
1946 ("enable or disable output for received dynamic data (data is still broadcasted via Dim)"
1947 "|dynout[bool]:disable or enable output for dynamic data (yes/no)");
1948
1949
1950 // Conenction commands
1951 T::AddEvent("DISCONNECT", FTM::kConnected, FTM::kIdle)
1952 (boost::bind(&StateMachineFTM::Disconnect, this))
1953 ("disconnect from ethernet");
1954
1955 T::AddEvent("RECONNECT", "O", FTM::kDisconnected, FTM::kConnected, FTM::kIdle, FTM::kConfigured)
1956 (boost::bind(&StateMachineFTM::Reconnect, this, _1))
1957 ("(Re)connect ethernet connection to FTM, a new address can be given"
1958 "|[host][string]:new ethernet address in the form <host:port>");
1959
1960 fFTM.StartConnect();
1961 }
1962
1963 void SetEndpoint(const string &url)
1964 {
1965 fFTM.SetEndpoint(url);
1966 }
1967
1968 map<uint16_t, array<uint64_t, 8>> fClockCondSetup;
1969
1970 template<class V>
1971 bool CheckConfigVal(const Configuration &conf, V max, const string &name, const string &sub)
1972 {
1973 if (!conf.HasDef(name, sub))
1974 {
1975 T::Error("Neither "+name+"default nor "+name+sub+" found.");
1976 return false;
1977 }
1978
1979 const V val = conf.GetDef<V>(name, sub);
1980
1981 if (val<=max)
1982 return true;
1983
1984 ostringstream str;
1985 str << name << sub << "=" << val << " exceeds allowed maximum of " << max << "!";
1986 T::Error(str);
1987
1988 return false;
1989 }
1990
1991 int EvalConfiguration(const Configuration &conf)
1992 {
1993 // ---------- General setup ----------
1994 fFTM.SetVerbose(!conf.Get<bool>("quiet"));
1995 fFTM.SetHexOutput(conf.Get<bool>("hex-out"));
1996 fFTM.SetDynamicOut(conf.Get<bool>("dynamic-out"));
1997
1998 // ---------- Setup clock conditioner frequencies ----------
1999 const vector<uint16_t> freq = conf.Vec<uint16_t>("clock-conditioner.frequency");
2000 if (freq.size()==0)
2001 T::Warn("No frequencies for the clock-conditioner defined.");
2002 else
2003 T::Message("Defining clock conditioner frequencies");
2004 for (vector<uint16_t>::const_iterator it=freq.begin();
2005 it!=freq.end(); it++)
2006 {
2007 if (fClockCondSetup.count(*it)>0)
2008 {
2009 T::Error("clock-conditioner frequency defined twice.");
2010 return 1;
2011 }
2012
2013 if (!conf.HasDef("clock-conditioner.R0.", *it) ||
2014 !conf.HasDef("clock-conditioner.R1.", *it) ||
2015 !conf.HasDef("clock-conditioner.R8.", *it) ||
2016 !conf.HasDef("clock-conditioner.R9.", *it) ||
2017 !conf.HasDef("clock-conditioner.R11.", *it) ||
2018 !conf.HasDef("clock-conditioner.R13.", *it) ||
2019 !conf.HasDef("clock-conditioner.R14.", *it) ||
2020 !conf.HasDef("clock-conditioner.R15.", *it))
2021 {
2022 T::Error("clock-conditioner values incomplete.");
2023 return 1;
2024 }
2025
2026 array<uint64_t, 8> &arr = fClockCondSetup[*it];
2027
2028 arr[0] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R0.", *it);
2029 arr[1] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R1.", *it);
2030 arr[2] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R8.", *it);
2031 arr[3] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R9.", *it);
2032 arr[4] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R11.", *it);
2033 arr[5] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R13.", *it);
2034 arr[6] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R14.", *it);
2035 arr[7] = conf.GetDef<Hex<uint32_t>>("clock-conditioner.R15.", *it);
2036
2037 ostringstream out;
2038 out << " -> " << setw(4) << *it << "MHz:" << hex << setfill('0');
2039 for (int i=0; i<8; i++)
2040 out << " " << setw(8) << arr[i];
2041 T::Message(out.str());
2042 }
2043
2044 // ---------- Setup run types ---------
2045 const vector<string> types = conf.Vec<string>("run-type");
2046 if (types.size()==0)
2047 T::Warn("No run-types defined.");
2048 else
2049 T::Message("Defining run-types");
2050 for (vector<string>::const_iterator it=types.begin();
2051 it!=types.end(); it++)
2052 {
2053 T::Message(" -> "+ *it);
2054
2055 if (fConfigs.count(*it)>0)
2056 {
2057 T::Error("Run-type "+*it+" defined twice.");
2058 return 2;
2059 }
2060
2061 FTM::StaticData data;
2062
2063 const uint16_t frq = conf.GetDef<uint16_t>("sampling-frequency.", *it);
2064 if (fClockCondSetup.count(frq)==0)
2065 {
2066 T::Error("sampling-frequency."+*it+" - frequency not available.");
2067 return 2;
2068 }
2069
2070 data.SetClockRegister(fClockCondSetup[frq].data());
2071
2072 // Trigger sequence ped:lp1:lp2
2073 // (data. is used here as an abbreviation for FTM::StaticData::
2074 if (!CheckConfigVal<bool> (conf, true, "enable-trigger.", *it) ||
2075 !CheckConfigVal<bool> (conf, true, "enable-external-1.", *it) ||
2076 !CheckConfigVal<bool> (conf, true, "enable-external-2.", *it) ||
2077 !CheckConfigVal<bool> (conf, true, "enable-veto.", *it) ||
2078 !CheckConfigVal<bool> (conf, true, "enable-clock-conditioner.", *it) ||
2079 !CheckConfigVal<uint16_t>(conf, data.kMaxSequence, "trigger-sequence-ped.", *it) ||
2080 !CheckConfigVal<uint16_t>(conf, data.kMaxSequence, "trigger-sequence-lp-ext.", *it) ||
2081 !CheckConfigVal<uint16_t>(conf, data.kMaxSequence, "trigger-sequence-lp-int.", *it) ||
2082 !CheckConfigVal<uint16_t>(conf, data.kMaxTriggerInterval, "trigger-interval.", *it) ||
2083 !CheckConfigVal<uint16_t>(conf, data.kMaxMultiplicity, "multiplicity-physics.", *it) ||
2084 !CheckConfigVal<uint16_t>(conf, data.kMaxMultiplicity, "multiplicity-calib.", *it) ||
2085 !CheckConfigVal<uint16_t>(conf, data.kMaxWindow, "coincidence-window-physics.", *it) ||
2086 !CheckConfigVal<uint16_t>(conf, data.kMaxWindow, "coincidence-window-calib.", *it) ||
2087 !CheckConfigVal<uint16_t>(conf, data.kMaxDeadTime, "dead-time.", *it) ||
2088 !CheckConfigVal<uint16_t>(conf, data.kMaxDelayTrigger, "trigger-delay.", *it) ||
2089 !CheckConfigVal<uint16_t>(conf, data.kMaxDelayTimeMarker, "time-marker-delay.", *it) ||
2090 !CheckConfigVal<uint16_t>(conf, 0xffff, "ftu-report-interval.", *it) ||
2091 0)
2092 return 2;
2093
2094 data.Enable(data.kTrigger, conf.GetDef<bool>("enable-trigger.", *it));
2095 data.Enable(data.kExt1, conf.GetDef<bool>("enable-external-1.", *it));
2096 data.Enable(data.kExt2, conf.GetDef<bool>("enable-external-2.", *it));
2097 data.Enable(data.kVeto, conf.GetDef<bool>("enable-veto.", *it));
2098 data.Enable(data.kClockConditioner, conf.GetDef<bool>("enable-clock-conditioner.", *it));
2099
2100 // [ms] Interval between two artificial triggers (no matter which type) minimum 1ms, 10 bit
2101 data.fTriggerInterval = conf.GetDef<uint16_t>("trigger-interval.", *it);
2102 data.fMultiplicityPhysics = conf.GetDef<uint16_t>("multiplicity-physics.", *it);
2103 data.fMultiplicityCalib = conf.GetDef<uint16_t>("multiplicity-calib.", *it);
2104 data.fWindowPhysics = conf.GetDef<uint16_t>("coincidence-window-physics.", *it); /// (4ns * x + 8ns)
2105 data.fWindowCalib = conf.GetDef<uint16_t>("coincidence-window-calib.", *it); /// (4ns * x + 8ns)
2106 data.fDelayTrigger = conf.GetDef<uint16_t>("trigger-delay.", *it); /// (4ns * x + 8ns)
2107 data.fDelayTimeMarker = conf.GetDef<uint16_t>("time-marker-delay.", *it); /// (4ns * x + 8ns)
2108 data.fDeadTime = conf.GetDef<uint16_t>("dead-time.", *it); /// (4ns * x + 8ns)
2109
2110 data.SetPrescaling(conf.GetDef<uint16_t>("ftu-report-interval.", *it));
2111
2112 const uint16_t seqped = conf.GetDef<uint16_t>("trigger-sequence-ped.", *it);
2113 const uint16_t seqint = conf.GetDef<uint16_t>("trigger-sequence-lp-int.", *it);
2114 const uint16_t seqext = conf.GetDef<uint16_t>("trigger-sequence-lp-ext.", *it);
2115
2116 data.SetSequence(seqped, seqint, seqext);
2117
2118 data.EnableAllFTU();
2119 data.EnableAllPixel();
2120
2121 const vector<uint16_t> pat1 = conf.Vec<uint16_t>("disable-patch.default");
2122 const vector<uint16_t> pat2 = conf.Vec<uint16_t>("disable-patch."+*it);
2123
2124 const vector<uint16_t> pix1 = conf.Vec<uint16_t>("disable-pixel.default");
2125 const vector<uint16_t> pix2 = conf.Vec<uint16_t>("disable-pixel."+*it);
2126
2127 vector<uint16_t> pat, pix;
2128 pat.insert(pat.end(), pat1.begin(), pat1.end());
2129 pat.insert(pat.end(), pat2.begin(), pat2.end());
2130 pix.insert(pix.end(), pix1.begin(), pix1.end());
2131 pix.insert(pix.end(), pix2.begin(), pix2.end());
2132
2133 for (vector<uint16_t>::const_iterator ip=pat.begin(); ip!=pat.end(); ip++)
2134 {
2135 if (*ip>FTM::StaticData::kMaxPatchIdx)
2136 {
2137 ostringstream str;
2138 str << "disable-patch.*=" << *ip << " exceeds allowed maximum of " << FTM::StaticData::kMaxPatchIdx << "!";
2139 T::Error(str);
2140 return 2;
2141 }
2142 data.DisableFTU(*ip);
2143 }
2144 for (vector<uint16_t>::const_iterator ip=pix.begin(); ip!=pix.end(); ip++)
2145 {
2146 if (*ip>FTM::StaticData::kMaxPixelIdx)
2147 {
2148 ostringstream str;
2149 str << "disable-pixel.*=" << *ip << " exceeds allowed maximum of " << FTM::StaticData::kMaxPixelIdx << "!";
2150 T::Error(str);
2151 return 2;
2152 }
2153 data.EnablePixel(*ip, false);
2154 }
2155
2156 fConfigs[*it] = data;
2157
2158 /*
2159 threshold-A data[n].fDAC[0] = val
2160 threshold-B data[n].fDAC[1] = val
2161 threshold-C data[n].fDAC[2] = val
2162 threshold-D data[n].fDAC[3] = val
2163 threshold-H data[n].fDAC[4] = val
2164 */
2165
2166 // kMaxDAC = 0xfff,
2167 }
2168
2169 // FIXME: Add a check about unsused configurations
2170
2171 // ---------- FOR TESTING PURPOSE ---------
2172
2173 // fFTM.SetDefaultSetup(conf.Get<string>("default-setup"));
2174 fConfigs["test"] = FTM::StaticData();
2175
2176 // ---------- Setup connection endpoint ---------
2177 SetEndpoint(conf.Get<string>("addr"));
2178
2179 return -1;
2180 }
2181};
2182
2183// ------------------------------------------------------------------------
2184
2185#include "Main.h"
2186
2187/*
2188void RunThread(StateMachineImp *io_service)
2189{
2190 // This is necessary so that the StateMachien Thread can signal the
2191 // Readline to exit
2192 io_service->Run();
2193 Readline::Stop();
2194}
2195*/
2196/*
2197template<class S, class T>
2198int RunDim(Configuration &conf)
2199{
2200 WindowLog wout;
2201
2202 ReadlineColor::PrintBootMsg(wout, conf.GetName(), false);
2203
2204 if (conf.Has("log"))
2205 if (!wout.OpenLogFile(conf.Get<string>("log")))
2206 wout << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl;
2207
2208 // Start io_service.Run to use the StateMachineImp::Run() loop
2209 // Start io_service.run to only use the commandHandler command detaching
2210 StateMachineFTM<S, T> io_service(wout);
2211 if (!io_service.EvalConfiguration(conf))
2212 return -1;
2213
2214 io_service.Run();
2215
2216 return 0;
2217}
2218*/
2219
2220template<class T, class S, class R>
2221int RunShell(Configuration &conf)
2222{
2223 return Main<T, StateMachineFTM<S, R>>(conf);
2224/*
2225 static T shell(conf.GetName().c_str(), conf.Get<int>("console")!=1);
2226
2227 WindowLog &win = shell.GetStreamIn();
2228 WindowLog &wout = shell.GetStreamOut();
2229
2230 if (conf.Has("log"))
2231 if (!wout.OpenLogFile(conf.Get<string>("log")))
2232 win << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl;
2233
2234 StateMachineFTM<S, R> io_service(wout);
2235 if (!io_service.EvalConfiguration(conf))
2236 return -1;
2237
2238 shell.SetReceiver(io_service);
2239
2240 boost::thread t(boost::bind(RunThread, &io_service));
2241 // boost::thread t(boost::bind(&StateMachineFTM<S>::Run, &io_service));
2242
2243 if (conf.Has("cmd"))
2244 {
2245 const vector<string> v = conf.Get<vector<string>>("cmd");
2246 for (vector<string>::const_iterator it=v.begin(); it!=v.end(); it++)
2247 shell.ProcessLine(*it);
2248 }
2249
2250 if (conf.Has("exec"))
2251 {
2252 const vector<string> v = conf.Get<vector<string>>("exec");
2253 for (vector<string>::const_iterator it=v.begin(); it!=v.end(); it++)
2254 shell.Execute(*it);
2255 }
2256
2257 if (conf.Get<bool>("quit"))
2258 shell.Stop();
2259
2260 shell.Run(); // Run the shell
2261 io_service.Stop(); // Signal Loop-thread to stop
2262 // io_service.Close(); // Obsolete, done by the destructor
2263
2264 // Wait until the StateMachine has finished its thread
2265 // before returning and destroying the dim objects which might
2266 // still be in use.
2267 t.join();
2268
2269 return 0;
2270 */
2271}
2272
2273void SetupConfiguration(Configuration &conf)
2274{
2275 const string n = conf.GetName()+".log";
2276
2277 po::options_description config("Program options");
2278 config.add_options()
2279 ("dns", var<string>("localhost"), "Dim nameserver host name (Overwites DIM_DNS_NODE environment variable)")
2280 ("log,l", var<string>(n), "Write log-file")
2281 ("no-dim,d", po_bool(), "Disable dim services")
2282 ("console,c", var<int>(), "Use console (0=shell, 1=simple buffered, X=simple unbuffered)")
2283 ("cmd", vars<string>(), "Execute one or more commands at startup")
2284 ("exec,e", vars<string>(), "Execute one or more scrips at startup")
2285 ("quit", po_switch(), "Quit after startup");
2286 ;
2287
2288 po::options_description control("Control options");
2289 control.add_options()
2290 ("addr,a", var<string>("localhost:5000"), "Network address of FTM")
2291 ("quiet,q", po_bool(), "Disable printing contents of all received messages (except dynamic data) in clear text.")
2292 ("hex-out", po_bool(), "Enable printing contents of all printed messages also as hex data.")
2293 ("dynamic-out", po_bool(), "Enable printing received dynamic data.")
2294// ("default-setup", var<string>(), "Binary file with static data loaded whenever a connection to the FTM was established.")
2295 ;
2296
2297 po::options_description runtype("Run type configuration");
2298 runtype.add_options()
2299 ("clock-conditioner.frequency", vars<uint16_t>(), "Frequencies for which to setup the clock-conditioner")
2300 ("clock-conditioner.R0.*", var<Hex<uint32_t>>(), "Clock-conditioner R0 (replace * by the defined frequency)")
2301 ("clock-conditioner.R1.*", var<Hex<uint32_t>>(), "Clock-conditioner R1 (replace * by the defined frequency)")
2302 ("clock-conditioner.R8.*", var<Hex<uint32_t>>(), "Clock-conditioner R8 (replace * by the defined frequency)")
2303 ("clock-conditioner.R9.*", var<Hex<uint32_t>>(), "Clock-conditioner R9 (replace * by the defined frequency)")
2304 ("clock-conditioner.R11.*", var<Hex<uint32_t>>(), "Clock-conditioner R11 (replace * by the defined frequency)")
2305 ("clock-conditioner.R13.*", var<Hex<uint32_t>>(), "Clock-conditioner R13 (replace * by the defined frequency)")
2306 ("clock-conditioner.R14.*", var<Hex<uint32_t>>(), "Clock-conditioner R14 (replace * by the defined frequency)")
2307 ("clock-conditioner.R15.*", var<Hex<uint32_t>>(), "Clock-conditioner R15 (replace * by the defined frequency)")
2308 ("run-type", vars<string>(), "")
2309 ("sampling-frequency.*", var<uint16_t>(), "")
2310 ("enable-trigger.*", var<bool>(), "")
2311 ("enable-external-1.*", var<bool>(), "")
2312 ("enable-external-2.*", var<bool>(), "")
2313 ("enable-veto.*", var<bool>(), "")
2314 ("enable-clock-conditioner.*", var<bool>(), "")
2315 ("trigger-interval.*", var<uint16_t>(), "")
2316 ("trigger-sequence-ped.*", var<uint16_t>(), "")
2317 ("trigger-sequence-lp-int.*", var<uint16_t>(), "")
2318 ("trigger-sequence-lp-ext.*", var<uint16_t>(), "")
2319 ("multiplicity-physics.*", var<uint16_t>(), "")
2320 ("multiplicity-calib.*", var<uint16_t>(), "")
2321 ("coincidence-window-physics.*", var<uint16_t>(), "")
2322 ("coincidence-window-calib.*", var<uint16_t>(), "")
2323 ("dead-time.*", var<uint16_t>(), "")
2324 ("trigger-delay.*", var<uint16_t>(), "")
2325 ("time-marker-delay.*", var<uint16_t>(), "")
2326 ("diable-pixel.*", vars<uint16_t>(), "")
2327 ("diable-patch.*", vars<uint16_t>(), "")
2328 ("ftu-report-interval.*", var<uint16_t>(), "")
2329 ;
2330
2331 conf.AddEnv("dns", "DIM_DNS_NODE");
2332
2333 conf.AddOptions(config);
2334 conf.AddOptions(control);
2335 conf.AddOptions(runtype);
2336}
2337
2338/*
2339 Extract usage clause(s) [if any] for SYNOPSIS.
2340 Translators: "Usage" and "or" here are patterns (regular expressions) which
2341 are used to match the usage synopsis in program output. An example from cp
2342 (GNU coreutils) which contains both strings:
2343 Usage: cp [OPTION]... [-T] SOURCE DEST
2344 or: cp [OPTION]... SOURCE... DIRECTORY
2345 or: cp [OPTION]... -t DIRECTORY SOURCE...
2346 */
2347void PrintUsage()
2348{
2349 cout <<
2350 "The ftmctrl controls the FTM (FACT Trigger Master) board.\n"
2351 "\n"
2352 "The default is that the program is started without user intercation. "
2353 "All actions are supposed to arrive as DimCommands. Using the -c "
2354 "option, a local shell can be initialized. With h or help a short "
2355 "help message about the usuage can be brought to the screen.\n"
2356 "\n"
2357 "Usage: ftmctrl [-c type] [OPTIONS]\n"
2358 " or: ftmctrl [OPTIONS]\n";
2359 cout << endl;
2360}
2361
2362void PrintHelp()
2363{
2364 /* Additional help text which is printed after the configuration
2365 options goes here */
2366
2367 /*
2368 cout << "bla bla bla" << endl << endl;
2369 cout << endl;
2370 cout << "Environment:" << endl;
2371 cout << "environment" << endl;
2372 cout << endl;
2373 cout << "Examples:" << endl;
2374 cout << "test exam" << endl;
2375 cout << endl;
2376 cout << "Files:" << endl;
2377 cout << "files" << endl;
2378 cout << endl;
2379 */
2380}
2381
2382int main(int argc, const char* argv[])
2383{
2384 Configuration conf(argv[0]);
2385 conf.SetPrintUsage(PrintUsage);
2386 SetupConfiguration(conf);
2387
2388 po::variables_map vm;
2389 try
2390 {
2391 vm = conf.Parse(argc, argv);
2392 }
2393#if BOOST_VERSION > 104000
2394 catch (po::multiple_occurrences &e)
2395 {
2396 cerr << "Program options invalid due to: " << e.what() << " of '" << e.get_option_name() << "'." << endl;
2397 return -1;
2398 }
2399#endif
2400 catch (exception& e)
2401 {
2402 cerr << "Program options invalid due to: " << e.what() << endl;
2403 return -1;
2404 }
2405
2406 if (conf.HasVersion() || conf.HasPrint())
2407 return -1;
2408
2409 if (conf.HasHelp())
2410 {
2411 PrintHelp();
2412 return -1;
2413 }
2414
2415 Dim::Setup(conf.Get<string>("dns"));
2416
2417 //try
2418 {
2419 // No console access at all
2420 if (!conf.Has("console"))
2421 {
2422 if (conf.Get<bool>("no-dim"))
2423 return RunShell<LocalStream, StateMachine, ConnectionFTM>(conf);
2424 else
2425 return RunShell<LocalStream, StateMachineDim, ConnectionDimFTM>(conf);
2426 }
2427 // Cosole access w/ and w/o Dim
2428 if (conf.Get<bool>("no-dim"))
2429 {
2430 if (conf.Get<int>("console")==0)
2431 return RunShell<LocalShell, StateMachine, ConnectionFTM>(conf);
2432 else
2433 return RunShell<LocalConsole, StateMachine, ConnectionFTM>(conf);
2434 }
2435 else
2436 {
2437 if (conf.Get<int>("console")==0)
2438 return RunShell<LocalShell, StateMachineDim, ConnectionDimFTM>(conf);
2439 else
2440 return RunShell<LocalConsole, StateMachineDim, ConnectionDimFTM>(conf);
2441 }
2442 }
2443 /*catch (std::exception& e)
2444 {
2445 cerr << "Exception: " << e.what() << endl;
2446 return -1;
2447 }*/
2448
2449 return 0;
2450}
Note: See TracBrowser for help on using the repository browser.