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

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