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

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