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

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