source: trunk/FACT++/src/fadctrl.cc@ 10951

Last change on this file since 10951 was 10940, checked in by tbretz, 13 years ago
Adapted to latest changes in EventBuilder; added some Dim services.
File size: 44.0 KB
Line 
1#include <boost/bind.hpp>
2#include <boost/array.hpp>
3#if BOOST_VERSION < 104400
4#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4))
5#undef BOOST_HAS_RVALUE_REFS
6#endif
7#endif
8#include <boost/thread.hpp>
9//#include <boost/foreach.hpp>
10#include <boost/asio/error.hpp>
11#include <boost/asio/deadline_timer.hpp>
12#include <boost/date_time/posix_time/posix_time_types.hpp>
13
14#include "Dim.h"
15#include "Event.h"
16#include "Shell.h"
17#include "StateMachineDim.h"
18#include "Connection.h"
19#include "Configuration.h"
20#include "Console.h"
21#include "Converter.h"
22#include "LocalControl.h"
23#include "HeadersFAD.h"
24
25#include "tools.h"
26
27namespace ba = boost::asio;
28namespace bs = boost::system;
29
30using ba::ip::tcp;
31
32using namespace std;
33
34// ------------------------------------------------------------------------
35
36class ConnectionFAD : public Connection
37{
38 vector<uint16_t> fBuffer;
39
40protected:
41 FAD::EventHeader fEventHeader;
42 FAD::ChannelHeader fChannelHeader[FAD::kNumChannels];
43
44private:
45 bool fIsVerbose;
46 bool fIsHexOutput;
47 bool fIsDataOutput;
48
49 uint64_t fCounter;
50
51protected:
52 virtual void UpdateFirstHeader()
53 {
54 }
55
56 virtual void UpdateEventHeader()
57 {
58 // emit service with trigger counter from header
59 if (!fIsVerbose)
60 return;
61
62 Out() << endl << kBold << "Header received (N=" << dec << fCounter << "):" << endl;
63 Out() << fEventHeader;
64 if (fIsHexOutput)
65 Out() << Converter::GetHex<uint16_t>(fEventHeader, 16) << endl;
66 }
67
68 /*
69 virtual void UpdateChannelHeader(int i)
70 {
71 // emit service with trigger counter from header
72 if (!fIsVerbose)
73 return;
74
75 Out() << fChannelHeader[i];
76 if (fIsHexOutput)
77 Out() << Converter::GetHex<uint16_t>(fChannelHeader, 16) << endl;
78 }
79 */
80
81 virtual void UpdateChannelHeaders()
82 {
83 // emit service with trigger counter from header
84 if (!fIsVerbose)
85 return;
86
87 Out() << dec << endl;
88
89 Out() << kBold << "ID: Crate=" << fEventHeader.Crate() << " Board=" << fEventHeader.Board() << endl;
90 for (unsigned int c=0; c<FAD::kNumChips; c++)
91 {
92 Out() << "ReadoutWin #" << c << ":";
93 for (unsigned int ch=0; ch<FAD::kNumChannelsPerChip; ch++)
94 Out() << " " << setw(4) << fChannelHeader[c*FAD::kNumChannelsPerChip+ch].fRegionOfInterest;
95 Out() << endl;
96 }
97
98 for (unsigned int c=0; c<FAD::kNumChips; c++)
99 {
100 Out() << "StartCells #" << c << ":";
101 for (unsigned int ch=0; ch<FAD::kNumChannelsPerChip; ch++)
102 Out() << " " << setw(4) << fChannelHeader[c*FAD::kNumChannelsPerChip+ch].fStartCell;
103 }
104
105 if (fIsHexOutput)
106 Out() << Converter::GetHex<uint16_t>(fChannelHeader, 16) << endl;
107 }
108
109 virtual void UpdateData(const uint16_t *data, size_t sz)
110 {
111 // emit service with trigger counter from header
112 if (fIsVerbose && fIsDataOutput)
113 Out() << Converter::GetHex<uint16_t>(data, sz, 16, true) << endl;
114 }
115
116private:
117 enum
118 {
119 kReadHeader = 1,
120 kReadData = 2,
121 };
122
123 void HandleReceivedData(const bs::error_code& err, size_t bytes_received, int type)
124 {
125 // Do not schedule a new read if the connection failed.
126 if (bytes_received==0 || err)
127 {
128 if (err==ba::error::eof)
129 Warn("Connection closed by remote host (FAD).");
130
131 // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
132 // 125: Operation canceled
133 if (err && err!=ba::error::eof && // Connection closed by remote host
134 err!=ba::error::basic_errors::not_connected && // Connection closed by remote host
135 err!=ba::error::basic_errors::operation_aborted) // Connection closed by us
136 {
137 ostringstream str;
138 str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
139 Error(str);
140 }
141 PostClose(err!=ba::error::basic_errors::operation_aborted);
142 return;
143 }
144
145 if (type==kReadHeader)
146 {
147 if (bytes_received!=sizeof(FAD::EventHeader))
148 {
149 ostringstream str;
150 str << "Bytes received (" << bytes_received << " don't match header size " << sizeof(FAD::EventHeader);
151 Error(str);
152 PostClose(false);
153 return;
154 }
155
156 fEventHeader = fBuffer;
157
158 if (fEventHeader.fStartDelimiter!=FAD::kDelimiterStart)
159 {
160 ostringstream str;
161 str << "Invalid header received: start delimiter wrong, received ";
162 str << hex << fEventHeader.fStartDelimiter << ", expected " << FAD::kDelimiterStart << ".";
163 Error(str);
164 PostClose(false);
165 return;
166 }
167
168 if (fCounter==0)
169 UpdateFirstHeader();
170
171 UpdateEventHeader();
172
173 fCounter++;
174
175 fBuffer.resize(fEventHeader.fPackageLength-sizeof(FAD::EventHeader)/2);
176 AsyncRead(ba::buffer(fBuffer), kReadData);
177 AsyncWait(fInTimeout, 50, &Connection::HandleReadTimeout);
178
179 return;
180 }
181
182 fInTimeout.cancel();
183
184 if (ntohs(fBuffer.back())!=FAD::kDelimiterEnd)
185 {
186 ostringstream str;
187 str << "Invalid data received: end delimiter wrong, received ";
188 str << hex << ntohs(fBuffer.back()) << ", expected " << FAD::kDelimiterEnd << ".";
189 Error(str);
190 PostClose(false);
191 return;
192 }
193
194 uint8_t *ptr = reinterpret_cast<uint8_t*>(fBuffer.data());
195 uint8_t *end = ptr + fBuffer.size()*2;
196 for (unsigned int i=0; i<FAD::kNumChannels; i++)
197 {
198 if (ptr+sizeof(FAD::ChannelHeader) > end)
199 {
200 Error("Channel header exceeds buffer size.");
201 PostClose(false);
202 return;
203 }
204
205 fChannelHeader[i] = vector<uint16_t>((uint16_t*)ptr, (uint16_t*)ptr+sizeof(FAD::ChannelHeader)/2);
206 ptr += sizeof(FAD::ChannelHeader);
207
208 //UpdateChannelHeader(i);
209
210 if (ptr+fChannelHeader[i].fRegionOfInterest*2 > end)
211 {
212 Error("Data block exceeds buffer size.");
213 PostClose(false);
214 return;
215 }
216
217 uint16_t *data = reinterpret_cast<uint16_t*>(ptr);
218
219 /*
220 for (uint16_t *d=data; d<data+fChannelHeader[i].fRegionOfInterest; d++)
221 {
222 const bool sign = *d & 0x2000;
223 const bool overflow = *d & 0x1000;
224
225 if (sign)
226 *d |= 0xf000; // no overflow, nagative
227 else
228 *d &= 0x07ff; // no overlow, positive
229
230 // max = [-2047;2048]
231
232 if (overflow)
233 {
234 if (sign)
235 *d = 0xF800; // overflow, negative
236 else
237 *d = 0x0800; // overflow, positive
238 }
239 }
240 */
241
242 UpdateData(data, fChannelHeader[i].fRegionOfInterest*2);
243 ptr += fChannelHeader[i].fRegionOfInterest*2;
244 }
245
246 UpdateChannelHeaders();
247
248 fBuffer.resize(sizeof(FAD::EventHeader)/2);
249 AsyncRead(ba::buffer(fBuffer), kReadHeader);
250 }
251
252 void HandleReadTimeout(const bs::error_code &error)
253 {
254 if (error==ba::error::basic_errors::operation_aborted)
255 return;
256
257 if (error)
258 {
259 ostringstream str;
260 str << "Read timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
261 Error(str);
262
263 PostClose();
264 return;
265
266 }
267
268 if (!is_open())
269 {
270 // For example: Here we could schedule a new accept if we
271 // would not want to allow two connections at the same time.
272 return;
273 }
274
275 // Check whether the deadline has passed. We compare the deadline
276 // against the current time since a new asynchronous operation
277 // may have moved the deadline before this actor had a chance
278 // to run.
279 if (fInTimeout.expires_at() > ba::deadline_timer::traits_type::now())
280 return;
281
282 Error("Timeout reading data from "+URL());
283 PostClose();
284 }
285
286 // This is called when a connection was established
287 void ConnectionEstablished()
288 {
289 fEventHeader.clear();
290 for (unsigned int i=0; i<FAD::kNumChannels; i++)
291 fChannelHeader[i].clear();
292
293 fCounter = 0;
294
295 fBuffer.resize(sizeof(FAD::EventHeader)/2);
296 AsyncRead(ba::buffer(fBuffer), kReadHeader);
297
298// for (int i=0; i<36; i++)
299// CmdSetRoi(i, 100);
300
301 Cmd(FAD::kCmdTriggerLine, true);
302 Cmd(FAD::kCmdSingleTrigger);
303 }
304
305 void PostCmd(std::vector<uint16_t> cmd)
306 {
307#ifdef DEBUG_TX
308 ostringstream msg;
309 msg << "Sending command:" << hex;
310 msg << " 0x" << setw(4) << setfill('0') << cmd[0];
311 msg << " (+ " << cmd.size()-1 << " bytes data)";
312 Message(msg);
313#endif
314 transform(cmd.begin(), cmd.end(), cmd.begin(), htons);
315
316 PostMessage(cmd);
317 }
318
319 void PostCmd(uint16_t cmd)
320 {
321#ifdef DEBUG_TX
322 ostringstream msg;
323 msg << "Sending command:" << hex;
324 msg << " 0x" << setw(4) << setfill('0') << cmd;
325 Message(msg);
326#endif
327 cmd = htons(cmd);
328 PostMessage(&cmd, sizeof(uint16_t));
329 }
330
331 void PostCmd(uint16_t cmd, uint16_t data)
332 {
333#ifdef DEBUG_TX
334 ostringstream msg;
335 msg << "Sending command:" << hex;
336 msg << " 0x" << setw(4) << setfill('0') << cmd;
337 msg << " 0x" << setw(4) << setfill('0') << data;
338 Message(msg);
339#endif
340 const uint16_t d[2] = { htons(cmd), htons(data) };
341 PostMessage(d, sizeof(d));
342 }
343
344public:
345 ConnectionFAD(ba::io_service& ioservice, MessageImp &imp) :
346 Connection(ioservice, imp()),
347 fIsVerbose(false), fIsHexOutput(false), fIsDataOutput(false), fCounter(0)
348 {
349 // Maximum possible needed space:
350 // The full header, all channels with all DRS bins
351 // Two trailing shorts
352 fBuffer.reserve(sizeof(FAD::EventHeader) + FAD::kNumChannels*(sizeof(FAD::ChannelHeader) + FAD::kMaxBins*sizeof(uint16_t)) + 2*sizeof(uint16_t));
353
354 SetLogStream(&imp);
355 }
356
357 void Cmd(FAD::Enable cmd, bool on=true)
358 {
359 PostCmd(cmd + (on ? 0 : 0x100));
360 }
361
362 // ------------------------------
363
364 // IMPLEMENT: Abs/Rel
365 void CmdPhaseShift(int16_t val)
366 {
367 vector<uint16_t> cmd(abs(val)+2, FAD::kCmdPhaseApply);
368 cmd[0] = FAD::kCmdPhaseReset;
369 cmd[1] = val<0 ? FAD::kCmdPhaseDecrease : FAD::kCmdPhaseIncrease;
370 PostCmd(cmd);
371 }
372
373 bool CmdSetTriggerRate(int32_t val)
374 {
375 if (val<0 || val>0xffff)
376 return false;
377
378 PostCmd(FAD::kCmdWriteRate, val);//uint8_t(1000./val/12.5));
379 //PostCmd(kCmdContTriggerRate, uint8_t(80/val));
380
381 return true;
382 }
383
384 void CmdSetRunNumber(uint32_t num)
385 {
386 PostCmd(FAD::kCmdWriteRunNumberLSW, num&0xffff);
387 PostCmd(FAD::kCmdWriteRunNumberMSW, num>>16);
388 }
389
390 void CmdSetRegister(uint8_t addr, uint16_t val)
391 {
392 // Allowed addr: [0, MAX_ADDR]
393 // Allowed value: [0, MAX_VAL]
394 PostCmd(FAD::kCmdWrite + addr, val);
395 }
396
397 bool CmdSetDacValue(uint8_t addr, uint16_t val)
398 {
399 if (addr>FAD::kMaxDacAddr) // NDAC
400 return false;
401
402 PostCmd(FAD::kCmdWriteDac + addr, val);
403 return true;
404 }
405
406 bool CmdSetRoi(int8_t addr, uint16_t val)
407 {
408 if (val>FAD::kMaxRoiValue)
409 return false;
410
411 if (addr<0)
412 {
413 for (unsigned int i=0; i<=FAD::kMaxRoiAddr; i++)
414 PostCmd(FAD::kCmdWriteRoi + i, val);
415 return true;
416 }
417
418 if (uint8_t(addr)>FAD::kMaxRoiAddr)
419 return false;
420
421 PostCmd(FAD::kCmdWriteRoi + addr, val);
422 return true;
423 }
424
425 bool CmdSetRoi(uint16_t val) { return CmdSetRoi(-1, val); }
426
427 void AmplitudeCalibration()
428 {
429 // ------------- case baseline -----------------
430
431 CmdSetRoi(-1, FAD::kMaxBins);
432
433 CmdSetDacValue(1, 0);
434 CmdSetDacValue(2, 0);
435 CmdSetDacValue(3, 0);
436
437 // Take N events
438
439 /*
440 // ====== Part B: Baseline calibration =====
441
442 // Loop over all channels(ch) and time-slices (t)
443 T0 = TriggerCell[chip]
444 Sum[ch][(t+T0) % kMaxBins] += Data[ch][t];
445 // FIXME: Determine median instead of average
446
447 Baseline[ch][slice] = MEDIAN( sum[ch][slice] )
448 */
449
450 // --------------- case gain -------------------
451
452 // Set new DAC values and start accumulation
453 CmdSetDacValue(1, 50000);
454 CmdSetDacValue(2, 50000);
455 CmdSetDacValue(3, 50000);
456
457 // Take N events
458
459 /*
460 // ====== Part C: Gain calibration =====
461
462 T0 = TriggerCell[chip]
463 Sum[ch][(t+T0) % kMaxBins] += Data[ch][t];
464 // FIXME: Determine median instead of average
465
466 Gain[ch][slice] = MEDIAN( sum[ch][slice] ) - Baseline[ch][slice]
467 */
468
469 // --------------- secondary ------------------
470
471 // FIXME: Can most probably be done together with the baseline calibration
472 // FIXME: Why does the secondary baseline not influence the baseline?
473
474 CmdSetDacValue(1, 0);
475 CmdSetDacValue(2, 0);
476 CmdSetDacValue(3, 0);
477
478 // Take N events
479
480 /*
481 // ====== Part D: Secondary calibration =====
482
483 T0 = TriggerCell[chip]
484 Sum[ch][t] = Data[ch][t] - Baseline[ch][(i-T0) % kMaxBins];
485
486 // Determine secondary baseline if integration finished
487 SecondaryBaseline[ch][t] = MEDIAN( Sum[ch][t] )
488 */
489 }
490
491 void SetVerbose(bool b)
492 {
493 fIsVerbose = b;
494 }
495
496 void SetHexOutput(bool b)
497 {
498 fIsHexOutput = b;
499 }
500
501 void SetDataOutput(bool b)
502 {
503 fIsDataOutput = b;
504 }
505
506};
507
508// ------------------------------------------------------------------------
509#include "DimDescriptionService.h"
510#include "EventBuilderWrapper.h"
511
512// ------------------------------------------------------------------------
513
514template <class T>
515class StateMachineFAD : public T, public EventBuilderWrapper, public ba::io_service, public ba::io_service::work
516{
517private:
518 typedef pair<tcp::endpoint, ConnectionFAD*> Connection;
519 typedef vector<Connection> BoardList;
520
521 BoardList fBoards;
522
523 bool fIsVerbose;
524 bool fIsHexOutput;
525 bool fIsDataOutput;
526
527 bool CheckEventSize(size_t has, const char *name, size_t size)
528 {
529 if (has==size)
530 return true;
531
532 ostringstream msg;
533 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
534 T::Fatal(msg);
535 return false;
536 }
537
538 int Cmd(FAD::Enable command)
539 {
540 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
541 i->second->Cmd(command);
542
543 return T::GetCurrentState();
544 }
545
546 int CmdEnable(const EventImp &evt, FAD::Enable command)
547 {
548 if (!CheckEventSize(evt.GetSize(), "CmdEnable", 1))
549 return T::kSM_FatalError;
550
551 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
552 i->second->Cmd(command, evt.GetBool());
553
554 return T::GetCurrentState();
555 }
556
557 bool Check(const uint32_t *dat, uint32_t maxaddr, uint32_t maxval)
558 {
559 if (dat[0]>FAD::kMaxRegAddr)
560 {
561 ostringstream msg;
562 msg << hex << "Address " << dat[0] << " out of range, max=" << maxaddr << ".";
563 T::Error(msg);
564 return false;
565 }
566
567 if (dat[1]>FAD::kMaxRegValue)
568 {
569 ostringstream msg;
570 msg << hex << "Value " << dat[1] << " out of range, max=" << maxval << ".";
571 T::Error(msg);
572 return false;
573 }
574
575 return true;
576 }
577
578 int SetRegister(const EventImp &evt)
579 {
580 if (!CheckEventSize(evt.GetSize(), "SetRegister", 8))
581 return T::kSM_FatalError;
582
583 const uint32_t *dat = evt.Ptr<uint32_t>();
584
585 if (!Check(dat, FAD::kMaxRegAddr, FAD::kMaxRegValue))
586 return T::GetCurrentState();
587
588 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
589 i->second->CmdSetRegister(dat[0], dat[1]);
590
591 return T::GetCurrentState();
592 }
593
594 int SetRoi(const EventImp &evt)
595 {
596 if (!CheckEventSize(evt.GetSize(), "SetRoi", 8))
597 return T::kSM_FatalError;
598
599 // ---- was uint32_t
600 const int32_t *dat = evt.Ptr<int32_t>();
601
602 // ---- -1 for all
603 //if (!Check(dat, FAD::kMaxRoiAddr, FAD::kMaxRoiValue))
604 // return T::GetCurrentState();
605
606 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
607 i->second->CmdSetRoi(dat[0], dat[1]);
608
609 return T::GetCurrentState();
610 }
611
612 int SetDac(const EventImp &evt)
613 {
614 if (!CheckEventSize(evt.GetSize(), "SetDac", 8))
615 return T::kSM_FatalError;
616
617 const uint32_t *dat = evt.Ptr<uint32_t>();
618
619 if (!Check(dat, FAD::kMaxDacAddr, FAD::kMaxDacValue))
620 return T::GetCurrentState();
621
622 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
623 i->second->CmdSetDacValue(dat[0], dat[1]);
624
625 return T::GetCurrentState();
626 }
627
628 int Trigger(int n)
629 {
630 for (int nn=0; nn<n; nn++)
631 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
632 i->second->Cmd(FAD::kCmdSingleTrigger);
633
634 return T::GetCurrentState();
635 }
636
637 int SendTriggers(const EventImp &evt)
638 {
639 if (!CheckEventSize(evt.GetSize(), "SendTriggers", 4))
640 return T::kSM_FatalError;
641
642 Trigger(evt.GetUInt());
643
644 return T::GetCurrentState();
645 }
646
647 int StartRun(const EventImp &evt, bool start)
648 {
649 if (!CheckEventSize(evt.GetSize(), "StartRun", 0))
650 return T::kSM_FatalError;
651
652 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
653 i->second->Cmd(FAD::kCmdRun, start);
654
655 return T::GetCurrentState();
656 }
657
658 int PhaseShift(const EventImp &evt)
659 {
660 if (!CheckEventSize(evt.GetSize(), "PhaseShift", 2))
661 return T::kSM_FatalError;
662
663 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
664 i->second->CmdPhaseShift(evt.GetShort());
665
666 return T::GetCurrentState();
667 }
668
669 int SetTriggerRate(const EventImp &evt)
670 {
671 if (!CheckEventSize(evt.GetSize(), "SetTriggerRate", 4))
672 return T::kSM_FatalError;
673
674 if (evt.GetUShort()>0xff)
675 {
676 ostringstream msg;
677 msg << hex << "Value " << evt.GetUShort() << " out of range, max=" << 0xff << "(?)";
678 T::Error(msg);
679 return false;
680 }
681
682 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
683 i->second->CmdSetTriggerRate(evt.GetUInt());
684
685 return T::GetCurrentState();
686 }
687
688 int SetRunNumber(const EventImp &evt)
689 {
690 if (!CheckEventSize(evt.GetSize(), "SetRunNumber", 8))
691 return T::kSM_FatalError;
692
693 const uint64_t num = evt.GetUXtra();
694
695 if (num>FAD::kMaxRunNumber)
696 {
697 ostringstream msg;
698 msg << hex << "Value " << num << " out of range, max=" << FAD::kMaxRunNumber;
699 T::Error(msg);
700 return false;
701 }
702
703 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
704 i->second->CmdSetRunNumber(num);
705
706 return T::GetCurrentState();
707 }
708
709 int Test(const EventImp &evt)
710 {
711 if (!CheckEventSize(evt.GetSize(), "Test", 2))
712 return T::kSM_FatalError;
713
714
715 SetMode(evt.GetShort());
716
717 return T::GetCurrentState();
718 }
719
720
721 int SetVerbosity(const EventImp &evt)
722 {
723 if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
724 return T::kSM_FatalError;
725
726 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
727 i->second->SetVerbose(evt.GetBool());
728
729 return T::GetCurrentState();
730 }
731
732 int SetHexOutput(const EventImp &evt)
733 {
734 if (!CheckEventSize(evt.GetSize(), "SetHexOutput", 1))
735 return T::kSM_FatalError;
736
737 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
738 i->second->SetHexOutput(evt.GetBool());
739
740 return T::GetCurrentState();
741 }
742
743 int SetDataOutput(const EventImp &evt)
744 {
745 if (!CheckEventSize(evt.GetSize(), "SetDataOutput", 1))
746 return T::kSM_FatalError;
747
748 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
749 i->second->SetDataOutput(evt.GetBool());
750
751 return T::GetCurrentState();
752 }
753
754 int AddAddress(const EventImp &evt)
755 {
756 const string addr = Tools::Trim(evt.GetText());
757
758 const tcp::endpoint endpoint = GetEndpoint(addr);
759 if (endpoint==tcp::endpoint())
760 return T::GetCurrentState();
761
762 for (BoardList::const_iterator i=fBoards.begin(); i!=fBoards.end(); i++)
763 {
764 if (i->first==endpoint)
765 {
766 T::Warn("Address "+addr+" already known.... ignored.");
767 return T::GetCurrentState();
768 }
769 }
770
771 AddEndpoint(endpoint);
772
773 return T::GetCurrentState();
774 }
775
776 int RemoveSlot(const EventImp &evt)
777 {
778 if (!CheckEventSize(evt.GetSize(), "RemoveSlot", 2))
779 return T::kSM_FatalError;
780
781 const int16_t slot = evt.GetShort();
782
783 if (fBoards[slot].first==tcp::endpoint())
784 {
785 ostringstream str;
786 str << "Slot " << slot << " not found.";
787 T::Warn(str.str());
788 return T::GetCurrentState();
789 }
790
791 delete fBoards[slot].second;
792 fBoards[slot] = make_pair(tcp::endpoint(), (ConnectionFAD*)NULL);
793
794 return T::GetCurrentState();
795 }
796
797 int ListSlots()
798 {
799 for (int i=0; i<40; i++)
800 {
801 if (fBoards[i].first==tcp::endpoint())
802 continue;
803
804 ostringstream str;
805 str << "Slot " << setw(2) << i << ": " << fBoards[i].first;
806
807 const ConnectionFAD *c = fBoards[i].second;
808
809 if (c->IsConnecting())
810 str << " (0:connecting, ";
811 else
812 {
813 if (c->IsClosed())
814 str << " (0:disconnected, ";
815 if (c->IsConnected())
816 str << " (0:connected, ";
817 }
818
819 switch (fStatus2[i])
820 {
821 case 0: str << "1-7:not connected)"; break;
822 case 7: str << "1-7:connected)"; break;
823 default: str << "1-7:connecting [" << fStatus2[i] << "])"; break;
824 }
825
826 T::Out() << str.str() << endl;
827 }
828
829 T::Out() << "Thread :";
830 if (!IsThreadRunning())
831 T::Out() << " not";
832 T::Out() << " running" << endl;
833
834 // FIXME: Output state
835
836 return T::GetCurrentState();
837 }
838
839 void EnableSlot(int i, bool enable=true)
840 {
841 if (fBoards[i].first==tcp::endpoint())
842 return;
843
844 ConnectionFAD* &ptr = fBoards[i].second;
845 if (!ptr)
846 return;
847
848 if (!enable)
849 ptr->PostClose(false);
850 else
851 {
852 ostringstream str;
853 str << fBoards[i].first;
854 ptr->SetEndpoint(str.str());
855 ptr->StartConnect();
856 }
857 }
858
859 void EnableAll(bool enable=true)
860 {
861 for (int i=0; i<40; i++)
862 EnableSlot(i, enable);
863 }
864
865 int Disconnect()
866 {
867 Exit();
868 EnableAll(false);
869 return T::GetCurrentState();
870 }
871
872 int ForceDisconnect()
873 {
874 Abort();
875 EnableAll(false);
876 return T::GetCurrentState();
877 }
878
879 int CloseOpenFiles()
880 {
881 EventBuilderWrapper::CloseOpenFiles();
882 return T::GetCurrentState();
883 }
884
885 int Connect()
886 {
887 vector<tcp::endpoint> addr(40);
888
889 for (int i=0; i<40; i++)
890 addr[i] = fBoards[i].first;
891
892 Start(addr);
893 EnableAll(true);
894
895 return T::GetCurrentState();
896 }
897
898 vector<uint8_t> fStatus1;
899 vector<uint8_t> fStatus2;
900
901 int Execute()
902 {
903 // Dispatch (execute) at most one handler from the queue. In contrary
904 // to run_one(), it doesn't wait until a handler is available
905 // which can be dispatched, so poll_one() might return with 0
906 // handlers dispatched. The handlers are always dispatched/executed
907 // synchronously, i.e. within the call to poll_one()
908 poll_one();
909
910 // ===== Evaluate connection status =====
911
912 uint16_t nconnecting1 = 0;
913 uint16_t nconnecting2 = 0;
914 uint16_t nconnected1 = 0;
915 uint16_t nconnected2 = 0;
916
917 vector<uint8_t> stat1(40);
918 vector<uint8_t> stat2(40);
919
920 int cnt = 0; // counter for enbled board
921
922 for (int idx=0; idx<40; idx++)
923 {
924 // ----- Command socket -----
925 if (fBoards[idx].first!=tcp::endpoint())
926 {
927 const ConnectionFAD *c = fBoards[idx].second;
928 if (c->IsConnecting())
929 {
930 stat1[idx] = 1;
931 nconnecting1++;
932 }
933 if (c->IsConnected())
934 {
935 stat1[idx] = 2;
936 nconnected1++;
937 }
938
939 cnt++;
940 }
941
942 // ----- Event builder -----
943 stat2[idx] = GetNumConnected(idx);
944
945 if (!IsConnected(idx) && !IsDisconnected(idx))
946 nconnecting2++;
947
948 if (IsConnected(idx))
949 nconnected2++;
950 }
951
952 // ===== Send connection status via dim =====
953
954 if (fStatus1!=stat1 || fStatus2!=stat2)
955 {
956 fStatus1 = stat1;
957 fStatus2 = stat2;
958 UpdateConnectionStatus(stat1, stat2);
959 }
960
961 // ===== Return connection status =====
962
963 // fadctrl: Always connecting if not disabled
964 // event builder:
965
966 // FIXME: Evaluate event builder status
967 if (nconnected1==cnt && nconnected2==cnt && cnt>0)
968 return FAD::kConnected;
969
970 if (nconnected1!=0 || nconnected2!=0)
971 return FAD::kConnecting;
972
973 // nconnected1 == nconnected2 == 0
974 return IsThreadRunning() ? FAD::kDisconnected : FAD::kOffline;
975 }
976
977 void AddEndpoint(const tcp::endpoint &addr)
978 {
979 int i=0;
980 while (i<40)
981 {
982 if (fBoards[i].first==tcp::endpoint())
983 break;
984 i++;
985 }
986
987 if (i==40)
988 {
989 T::Warn("Not more than 40 slots allowed.");
990 return;
991 }
992
993 fBoards[i] = make_pair(addr, new ConnectionFAD(*this, *this));
994 fBoards[i].second->SetVerbose(fIsVerbose);
995 fBoards[i].second->SetHexOutput(fIsHexOutput);
996 fBoards[i].second->SetDataOutput(fIsDataOutput);
997 }
998
999
1000 DimDescribedService fDimConnection;
1001 /*
1002 template<class T>
1003 void Update(DimDescribedService &svc, const T &data) const
1004 {
1005 //cout << "Update: " << svc.getName() << " (" << sizeof(T) << ")" << endl;
1006 svc.setData(const_cast<T*>(&data), sizeof(T));
1007 svc.updateService();
1008 }
1009 */
1010 void UpdateConnectionStatus(const vector<uint8_t> &stat1, const vector<uint8_t> &stat2)
1011 {
1012 vector<uint8_t> stat(40);
1013
1014 for (int i=0; i<40; i++)
1015 stat[i] = stat1[i]+stat2[i];
1016
1017 fDimConnection.setData(stat.data(), 40);
1018 fDimConnection.updateService();
1019 }
1020
1021public:
1022 StateMachineFAD(ostream &out=cout) :
1023 T(out, "FAD_CONTROL"), EventBuilderWrapper(static_cast<MessageImp&>(*this)), ba::io_service::work(static_cast<ba::io_service&>(*this)),
1024 fBoards(40), fStatus1(40), fStatus2(40),
1025 fDimConnection("FAD_CONTROL/CONNECTIONS", "C:41", "")
1026 {
1027 // ba::io_service::work is a kind of keep_alive for the loop.
1028 // It prevents the io_service to go to stopped state, which
1029 // would prevent any consecutive calls to run()
1030 // or poll() to do nothing. reset() could also revoke to the
1031 // previous state but this might introduce some overhead of
1032 // deletion and creation of threads and more.
1033
1034 // State names
1035 T::AddStateName(FAD::kOffline, "Offline",
1036 "All enabled FAD boards are disconnected and the event-builer thread is not running.");
1037
1038 T::AddStateName(FAD::kDisconnected, "Disconnected",
1039 "All enabled FAD boards are disconnected, but the event-builder thread is running.");
1040
1041 T::AddStateName(FAD::kConnected, "Connected",
1042 "All enabled FAD boards are connected..");
1043
1044 T::AddStateName(FAD::kConnecting, "Connecting",
1045 "Only some enabled FAD boards are connected.");
1046
1047 // FAD Commands
1048 T::AddEvent("ENABLE_SRCLK", "B:1")
1049 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdSrclk))
1050 ("Set SRCLK");
1051 T::AddEvent("ENABLE_SCLK", "B:1")
1052 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdSclk))
1053 ("Set SCLK");
1054 T::AddEvent("ENABLE_DRS", "B:1")
1055 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdDrsEnable))
1056 ("Switch Domino wave");
1057 T::AddEvent("ENABLE_DWRITE", "B:1")
1058 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdDwrite))
1059 ("Set Dwrite (possibly high / always low)");
1060 T::AddEvent("SET_DEBUG_MODE", "B:1")
1061 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdSocket))
1062 ("Set debug mode (yes: dump events through command socket, no=dump events through other sockets)");
1063 T::AddEvent("ENABLE_TRIGGER_LINE", "B:1")
1064 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdTriggerLine))
1065 ("Incoming triggers can be accepted/will not be accepted");
1066 T::AddEvent("SET_TRIGGER_RATE", "I:1")
1067 (boost::bind(&StateMachineFAD::SetTriggerRate, this, _1))
1068 ("Enable continous trigger");
1069 T::AddEvent("SEND_SINGLE_TRIGGER")
1070 (boost::bind(&StateMachineFAD::Trigger, this, 1))
1071 ("Issue software triggers");
1072 T::AddEvent("SEND_N_TRIGGERS", "I")
1073 (boost::bind(&StateMachineFAD::SendTriggers, this, _1))
1074 ("Issue software triggers");
1075 T::AddEvent("START", "")
1076 (boost::bind(&StateMachineFAD::StartRun, this, _1, true))
1077 ("Set FAD DAQ mode. when started, no configurations must be send.");
1078 T::AddEvent("STOP")
1079 (boost::bind(&StateMachineFAD::StartRun, this, _1, false))
1080 ("");
1081 T::AddEvent("PHASE_SHIFT", "S:1")
1082 (boost::bind(&StateMachineFAD::PhaseShift, this, _1))
1083 ("Adjust ADC phase (in 'steps')");
1084
1085 T::AddEvent("CONTINOUS_TRIGGER_ON")
1086 (boost::bind(&StateMachineFAD::Cmd, this, FAD::kCmdContTriggerOn))
1087 ("");
1088 T::AddEvent("CONTINOUS_TRIGGER_OFF")
1089 (boost::bind(&StateMachineFAD::Cmd, this, FAD::kCmdContTriggerOff))
1090 ("");
1091
1092 T::AddEvent("RESET_TRIGGER_ID")
1093 (boost::bind(&StateMachineFAD::Cmd, this, FAD::kCmdResetTriggerId))
1094 ("");
1095
1096 T::AddEvent("SET_RUN_NUMBER", "X:1")
1097 (boost::bind(&StateMachineFAD::SetRunNumber, this, _1))
1098 ("");
1099
1100 T::AddEvent("SET_REGISTER", "I:2")
1101 (boost::bind(&StateMachineFAD::SetRegister, this, _1))
1102 ("set register to value"
1103 "|addr[short]:Address of register"
1104 "|val[short]:Value to be set");
1105
1106 // FIXME: Maybe add a mask which channels should be set?
1107 T::AddEvent("SET_REGION_OF_INTEREST", "I:2")
1108 (boost::bind(&StateMachineFAD::SetRoi, this, _1))
1109 ("Set region-of-interest to value"
1110 "|addr[short]:Address of register"
1111 "|val[short]:Value to be set");
1112
1113 // FIXME: Maybe add a mask which channels should be set?
1114 T::AddEvent("SET_DAC_VALUE", "I:2")
1115 (boost::bind(&StateMachineFAD::SetDac, this, _1))
1116 ("Set DAC numbers in range to value"
1117 "|addr[short]:Address of register"
1118 "|val[short]:Value to be set");
1119
1120 // Verbosity commands
1121 T::AddEvent("SET_VERBOSE", "B")
1122 (boost::bind(&StateMachineFAD::SetVerbosity, this, _1))
1123 ("set verbosity state"
1124 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
1125
1126 T::AddEvent("SET_HEX_OUTPUT", "B")
1127 (boost::bind(&StateMachineFAD::SetHexOutput, this, _1))
1128 ("enable or disable hex output for received data"
1129 "|hexout[bool]:disable or enable hex output for received data (yes/no)");
1130
1131 T::AddEvent("SET_DATA_OUTPUT", "B")
1132 (boost::bind(&StateMachineFAD::SetDataOutput, this, _1))
1133 ("");
1134
1135 // Conenction commands
1136 /*
1137 T::AddEvent("ENABLE", "S:1;B:1", FAD::kDisconnected)
1138 (boost::bind(&StateMachineFAD::Enable, this, _1))
1139 ("");*/
1140
1141 T::AddEvent("CONNECT", FAD::kOffline)
1142 (boost::bind(&StateMachineFAD::Connect, this))
1143 ("");
1144
1145 T::AddEvent("DISCONNECT", FAD::kDisconnected, FAD::kConnecting, FAD::kConnected)
1146 (boost::bind(&StateMachineFAD::Disconnect, this))
1147 ("");
1148
1149 T::AddEvent("FORCE_DISCONNECT", FAD::kDisconnected, FAD::kConnecting, FAD::kConnected)
1150 (boost::bind(&StateMachineFAD::ForceDisconnect, this))
1151 ("");
1152
1153 T::AddEvent("CLOSE_OPEN_FILES", FAD::kConnecting, FAD::kConnected)
1154 (boost::bind(&StateMachineFAD::CloseOpenFiles, this))
1155 ("");
1156
1157 T::AddEvent("TEST", "S:1")
1158 (boost::bind(&StateMachineFAD::Test, this, _1))
1159 ("");
1160
1161 T::AddEvent("ADD_ADDRESS", "C", FAD::kOffline)
1162 (boost::bind(&StateMachineFAD::AddAddress, this, _1))
1163 ("Add the address of a DRS4 board to the first free slot"
1164 "|IP[string]:address in the format <address:port>");
1165 T::AddEvent("REMOVE_SLOT", "S:1", FAD::kOffline)
1166 (boost::bind(&StateMachineFAD::RemoveSlot, this, _1))
1167 ("Remove the Iaddress in slot n. For a list see LIST"
1168 "|slot[int]:Remove the address in slot n from the list");
1169 T::AddEvent("LIST_SLOTS")
1170 (boost::bind(&StateMachineFAD::ListSlots, this))
1171 ("Print a list of all available board addressesa and whether they are enabled");
1172 }
1173
1174 ~StateMachineFAD()
1175 {
1176 for (BoardList::const_iterator i=fBoards.begin(); i!=fBoards.end(); i++)
1177 delete i->second;
1178 fBoards.clear();
1179 }
1180
1181 tcp::endpoint GetEndpoint(const string &base)
1182 {
1183 const size_t p0 = base.find_first_of(':');
1184 const size_t p1 = base.find_last_of(':');
1185
1186 if (p0==string::npos || p0!=p1)
1187 {
1188 T::Out() << kRed << "GetEndpoint - Wrong format ('host:port' expected)" << endl;
1189 return tcp::endpoint();
1190 }
1191
1192 tcp::resolver resolver(get_io_service());
1193
1194 boost::system::error_code ec;
1195
1196 const tcp::resolver::query query(base.substr(0, p0), base.substr(p0+1));
1197 const tcp::resolver::iterator iterator = resolver.resolve(query, ec);
1198
1199 if (ec)
1200 {
1201 T::Out() << kRed << "GetEndpoint - Couldn't resolve endpoint '" << base << "': " << ec.message();
1202 return tcp::endpoint();
1203 }
1204
1205 return *iterator;
1206 }
1207
1208 bool SetConfiguration(const Configuration &conf)
1209 {
1210 fIsVerbose = !conf.Get<bool>("quiet");
1211 fIsHexOutput = conf.Get<bool>("hex-out");
1212 fIsDataOutput = conf.Get<bool>("data-out");
1213
1214 SetMaxMemory(conf.Get<unsigned int>("max-mem"));
1215
1216 // vvvvv for debugging vvvvv
1217 if (conf.Has("debug-addr"))
1218 {
1219 const string addr = conf.Get<string>("debug-addr");
1220 const int num = conf.Get<unsigned int>("debug-num");
1221
1222 const tcp::endpoint endpoint = GetEndpoint(addr);
1223 if (endpoint==tcp::endpoint())
1224 return false;
1225
1226 for (int i=0; i<num; i++)
1227 AddEndpoint(tcp::endpoint(endpoint.address(), endpoint.port()+8*i));
1228
1229 Connect();
1230 return true;
1231 }
1232 // ^^^^^ for debugging ^^^^^
1233
1234 if (!(conf.Has("base-addr") ^ conf.Has("addr")))
1235 {
1236 T::Out() << kRed << "SetConfiguration - Only --base-addr or --addr allowed." << endl;
1237 return false;
1238 }
1239
1240 if (conf.Has("base-addr"))
1241 {
1242 const string base = conf.Get<string>("base-addr");
1243
1244 const tcp::endpoint endpoint = GetEndpoint(base);
1245 if (endpoint==tcp::endpoint())
1246 return false;
1247
1248 const ba::ip::address_v4::bytes_type ip = endpoint.address().to_v4().to_bytes();
1249
1250 if (ip[2]>250 || ip[3]>244)
1251 {
1252 T::Out() << kRed << "SetConfiguration - IP address given by --base-addr out-of-range." << endl;
1253 return false;
1254 }
1255
1256 for (int crate=0; crate<4; crate++)
1257 for (int board=0; board<10; board++)
1258 {
1259 ba::ip::address_v4::bytes_type target = endpoint.address().to_v4().to_bytes();
1260 target[2] += crate;
1261 target[3] += board;
1262
1263 AddEndpoint(tcp::endpoint(ba::ip::address_v4(target), endpoint.port()));
1264 }
1265 }
1266
1267 if (conf.Has("addr"))
1268 {
1269 const vector<string> addrs = conf.Get<vector<string>>("addr");
1270 for (vector<string>::const_iterator i=addrs.begin(); i<addrs.end(); i++)
1271 {
1272 const tcp::endpoint endpoint = GetEndpoint(*i);
1273 if (endpoint==tcp::endpoint())
1274 return false;
1275
1276 AddEndpoint(endpoint);
1277 }
1278 }
1279
1280 Connect();
1281
1282 return true;
1283 }
1284
1285};
1286
1287// ------------------------------------------------------------------------
1288
1289
1290void RunThread(StateMachineImp *io_service)
1291{
1292 // This is necessary so that the StateMachien Thread can signal the
1293 // Readline to exit
1294 io_service->Run();
1295 Readline::Stop();
1296}
1297
1298template<class S>
1299int RunDim(Configuration &conf)
1300{
1301 /*
1302 initscr(); // Start curses mode
1303 cbreak(); // Line buffering disabled, Pass on
1304 intrflush(stdscr, FALSE);
1305 start_color(); // Initialize ncurses colors
1306 use_default_colors(); // Assign terminal default colors to -1
1307 for (int i=1; i<8; i++)
1308 init_pair(i, i, -1); // -1: def background
1309 scrollok(stdscr, true);
1310 */
1311
1312 WindowLog wout;
1313
1314 //log.SetWindow(stdscr);
1315 if (conf.Has("log"))
1316 if (!wout.OpenLogFile(conf.Get<string>("log")))
1317 wout << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl;
1318
1319 // Start io_service.Run to use the StateMachineImp::Run() loop
1320 // Start io_service.run to only use the commandHandler command detaching
1321 StateMachineFAD<S> io_service(wout);
1322 if (!io_service.SetConfiguration(conf))
1323 return -1;
1324
1325 io_service.Run();
1326
1327 return 0;
1328}
1329
1330template<class T, class S>
1331int RunShell(Configuration &conf)
1332{
1333 static T shell(conf.GetName().c_str(), conf.Get<int>("console")!=1);
1334
1335 WindowLog &win = shell.GetStreamIn();
1336 WindowLog &wout = shell.GetStreamOut();
1337
1338 if (conf.Has("log"))
1339 if (!wout.OpenLogFile(conf.Get<string>("log")))
1340 win << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl;
1341
1342 StateMachineFAD<S> io_service(wout);
1343 if (!io_service.SetConfiguration(conf))
1344 return -1;
1345
1346 shell.SetReceiver(io_service);
1347
1348 boost::thread t(boost::bind(RunThread, &io_service));
1349 //boost::thread t(boost::bind(&StateMachineFAD<S>::Run, &io_service));
1350
1351 shell.Run(); // Run the shell
1352 io_service.Stop(); // Signal Loop-thread to stop
1353
1354 // Wait until the StateMachine has finished its thread
1355 // before returning and destroying the dim objects which might
1356 // still be in use.
1357 t.join();
1358
1359 return 0;
1360}
1361
1362void SetupConfiguration(Configuration &conf)
1363{
1364 const string n = conf.GetName()+".log";
1365
1366 po::options_description config("Program options");
1367 config.add_options()
1368 ("dns", var<string>("localhost"), "Dim nameserver host name (Overwites DIM_DNS_NODE environment variable)")
1369 ("log,l", var<string>(n), "Write log-file")
1370 ("no-dim,d", po_switch(), "Disable dim services")
1371 ("console,c", var<int>(), "Use console (0=shell, 1=simple buffered, X=simple unbuffered)")
1372 ;
1373
1374 po::options_description control("FAD control options");
1375 control.add_options()
1376 ("quiet,q", po_bool(), "Disable printing contents of all received messages in clear text.")
1377 ("hex-out", po_bool(), "Enable printing contents of all printed messages also as hex data.")
1378 ("data-out", po_bool(), "Enable printing received event data.")
1379 ;
1380
1381 po::options_description builder("Event builder options");
1382 builder.add_options()
1383 ("max-mem,m", var<unsigned int>(100), "Maximum memory the event builder thread is allowed to consume for its event buffer")
1384 ;
1385
1386 po::options_description connect("FAD connection options");
1387 connect.add_options()
1388 ("addr", vars<string>(), "Network address of FAD")
1389 ("base-addr", var<string>(), "Base address of all FAD")
1390 ("debug-num,n", var<unsigned int>(40), "Sets the number of fake boards to be connected locally")
1391 ("debug-addr", var<string>(), "")
1392 ;
1393
1394 conf.AddEnv("dns", "DIM_DNS_NODE");
1395
1396 conf.AddOptions(config);
1397 conf.AddOptions(control);
1398 conf.AddOptions(builder);
1399 conf.AddOptions(connect);
1400}
1401
1402void PrintUsage()
1403{
1404 cout <<
1405 "The fadctrl controls the FAD boards.\n"
1406 "\n"
1407 "The default is that the program is started without user intercation. "
1408 "All actions are supposed to arrive as DimCommands. Using the -c "
1409 "option, a local shell can be initialized. With h or help a short "
1410 "help message about the usuage can be brought to the screen.\n"
1411 "\n"
1412 "Usage: fadctrl [-c type] [OPTIONS]\n"
1413 " or: fadctrl [OPTIONS]\n";
1414 cout << endl;
1415}
1416
1417void PrintHelp()
1418{
1419 /* Additional help text which is printed after the configuration
1420 options goes here */
1421}
1422
1423int main(int argc, const char* argv[])
1424{
1425 Configuration conf(argv[0]);
1426 conf.SetPrintUsage(PrintUsage);
1427 SetupConfiguration(conf);
1428
1429 po::variables_map vm;
1430 try
1431 {
1432 vm = conf.Parse(argc, argv);
1433 }
1434#if BOOST_VERSION > 104000
1435 catch (po::multiple_occurrences &e)
1436 {
1437 cerr << "Program options invalid due to: " << e.what() << " of '" << e.get_option_name() << "'." << endl;
1438 return -1;
1439 }
1440#endif
1441 catch (exception& e)
1442 {
1443 cerr << "Program options invalid due to: " << e.what() << endl;
1444 return -1;
1445 }
1446
1447 if (conf.HasVersion() || conf.HasPrint())
1448 return -1;
1449
1450 if (conf.HasHelp())
1451 {
1452 PrintHelp();
1453 return -1;
1454 }
1455
1456 Dim::Setup(conf.Get<string>("dns"));
1457
1458// try
1459 {
1460 // No console access at all
1461 if (!conf.Has("console"))
1462 {
1463 if (conf.Get<bool>("no-dim"))
1464 return RunDim<StateMachine>(conf);
1465 else
1466 return RunDim<StateMachineDim>(conf);
1467 }
1468 // Cosole access w/ and w/o Dim
1469 if (conf.Get<bool>("no-dim"))
1470 {
1471 if (conf.Get<int>("console")==0)
1472 return RunShell<LocalShell, StateMachine>(conf);
1473 else
1474 return RunShell<LocalConsole, StateMachine>(conf);
1475 }
1476 else
1477 {
1478 if (conf.Get<int>("console")==0)
1479 return RunShell<LocalShell, StateMachineDim>(conf);
1480 else
1481 return RunShell<LocalConsole, StateMachineDim>(conf);
1482 }
1483 }
1484/* catch (std::exception& e)
1485 {
1486 cerr << "Exception: " << e.what() << endl;
1487 return -1;
1488 }*/
1489
1490 return 0;
1491}
Note: See TracBrowser for help on using the repository browser.