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

Last change on this file since 11480 was 11480, checked in by tbretz, 13 years ago
Removed obsolete include.
File size: 68.8 KB
Line 
1#include "Dim.h"
2#include "Event.h"
3#include "Shell.h"
4#include "StateMachineDim.h"
5#include "Connection.h"
6#include "Configuration.h"
7#include "Console.h"
8#include "Converter.h"
9#include "HeadersFAD.h"
10
11#include "tools.h"
12
13#include "DimDescriptionService.h"
14#include "EventBuilderWrapper.h"
15
16namespace ba = boost::asio;
17namespace bs = boost::system;
18
19using ba::ip::tcp;
20
21using namespace std;
22
23// ------------------------------------------------------------------------
24
25class ConnectionFAD : public Connection
26{
27 uint16_t fSlot;
28// tcp::endpoint fEndpoint;
29
30 vector<uint16_t> fBuffer;
31
32protected:
33 FAD::EventHeader fEventHeader;
34 FAD::ChannelHeader fChannelHeader[FAD::kNumChannels];
35
36private:
37 bool fIsVerbose;
38 bool fIsHexOutput;
39 bool fIsDataOutput;
40 bool fBlockTransmission;
41
42 uint64_t fCounter;
43
44 FAD::EventHeader fBufEventHeader;
45 vector<uint16_t> fTargetRoi;
46
47protected:
48 void PrintEventHeader()
49 {
50 Out() << endl << kBold << "Header received (N=" << dec << fCounter << "):" << endl;
51 Out() << fEventHeader;
52 if (fIsHexOutput)
53 Out() << Converter::GetHex<uint16_t>(fEventHeader, 16) << endl;
54 }
55
56 void PrintChannelHeaders()
57 {
58 Out() << dec << endl;
59
60 for (unsigned int c=0; c<FAD::kNumChips; c++)
61 {
62 Out() << "ROI|" << fEventHeader.Crate() << ":" << fEventHeader.Board() << ":" << c << ":";
63 for (unsigned int ch=0; ch<FAD::kNumChannelsPerChip; ch++)
64 Out() << " " << setw(4) << fChannelHeader[c+ch*FAD::kNumChips].fRegionOfInterest;
65 Out() << endl;
66 }
67
68 Out() << "CEL|" << fEventHeader.Crate() << ":" <<fEventHeader.Board() << ": ";
69 for (unsigned int c=0; c<FAD::kNumChips; c++)
70 {
71 if (0)//fIsFullChannelHeader)
72 {
73 for (unsigned int ch=0; ch<FAD::kNumChannelsPerChip; ch++)
74 Out() << " " << setw(4) << fChannelHeader[c+ch*FAD::kNumChips].fStartCell;
75 Out() << endl;
76 }
77 else
78 {
79 Out() << " ";
80 const uint16_t cel = fChannelHeader[c*FAD::kNumChannelsPerChip].fStartCell;
81 for (unsigned int ch=1; ch<FAD::kNumChannelsPerChip; ch++)
82 if (cel!=fChannelHeader[c+ch*FAD::kNumChips].fStartCell)
83 {
84 Out() << "!";
85 break;
86 }
87 Out() << cel;
88 }
89 }
90 Out() << endl;
91
92 if (fIsHexOutput)
93 Out() << Converter::GetHex<uint16_t>(fChannelHeader, 16) << endl;
94
95 }
96
97 virtual void UpdateFirstHeader()
98 {
99 }
100
101 virtual void UpdateEventHeader()
102 {
103 // emit service with trigger counter from header
104 if (fIsVerbose)
105 PrintEventHeader();
106 }
107
108 virtual void UpdateChannelHeaders()
109 {
110 // emit service with trigger counter from header
111 if (fIsVerbose)
112 PrintChannelHeaders();
113
114 }
115
116 virtual void UpdateData(const uint16_t *data, size_t sz)
117 {
118 // emit service with trigger counter from header
119 if (fIsVerbose && fIsDataOutput)
120 Out() << Converter::GetHex<uint16_t>(data, sz, 16, true) << endl;
121 }
122
123private:
124 enum
125 {
126 kReadHeader = 1,
127 kReadData = 2,
128 };
129
130 void HandleReceivedData(const bs::error_code& err, size_t bytes_received, int type)
131 {
132 // Do not schedule a new read if the connection failed.
133 if (bytes_received==0 || err)
134 {
135 if (err==ba::error::eof)
136 Warn("Connection closed by remote host (FAD).");
137
138 // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
139 // 125: Operation canceled
140 if (err && err!=ba::error::eof && // Connection closed by remote host
141 err!=ba::error::basic_errors::not_connected && // Connection closed by remote host
142 err!=ba::error::basic_errors::operation_aborted) // Connection closed by us
143 {
144 ostringstream str;
145 str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
146 Error(str);
147 }
148 PostClose(err!=ba::error::basic_errors::operation_aborted);
149 return;
150 }
151
152 EventBuilderWrapper::This->debugStream(fSlot*7, fBuffer.data(), bytes_received);
153
154 if (type==kReadHeader)
155 {
156 if (bytes_received!=sizeof(FAD::EventHeader))
157 {
158 ostringstream str;
159 str << "Bytes received (" << bytes_received << " don't match header size " << sizeof(FAD::EventHeader);
160 Error(str);
161 PostClose(false);
162 return;
163 }
164
165 fEventHeader = fBuffer;
166
167 if (fEventHeader.fStartDelimiter!=FAD::kDelimiterStart)
168 {
169 ostringstream str;
170 str << "Invalid header received: start delimiter wrong, received ";
171 str << hex << fEventHeader.fStartDelimiter << ", expected " << FAD::kDelimiterStart << ".";
172 Error(str);
173 PostClose(false);
174 return;
175 }
176
177 if (fCounter==0)
178 UpdateFirstHeader();
179
180 UpdateEventHeader();
181
182 EventBuilderWrapper::This->debugHead(fSlot*7, fEventHeader);
183
184 fBuffer.resize(fEventHeader.fPackageLength-sizeof(FAD::EventHeader)/2);
185 AsyncRead(ba::buffer(fBuffer), kReadData);
186 AsyncWait(fInTimeout, 2000, &Connection::HandleReadTimeout);
187
188 return;
189 }
190
191 fInTimeout.cancel();
192
193 if (ntohs(fBuffer.back())!=FAD::kDelimiterEnd)
194 {
195 ostringstream str;
196 str << "Invalid data received: end delimiter wrong, received ";
197 str << hex << ntohs(fBuffer.back()) << ", expected " << FAD::kDelimiterEnd << ".";
198 Error(str);
199 PostClose(false);
200 return;
201 }
202
203 uint8_t *ptr = reinterpret_cast<uint8_t*>(fBuffer.data());
204 uint8_t *end = ptr + fBuffer.size()*2;
205 for (unsigned int i=0; i<FAD::kNumChannels; i++)
206 {
207 if (ptr+sizeof(FAD::ChannelHeader) > end)
208 {
209 Error("Channel header exceeds buffer size.");
210 PostClose(false);
211 return;
212 }
213
214 fChannelHeader[i] = vector<uint16_t>((uint16_t*)ptr, (uint16_t*)ptr+sizeof(FAD::ChannelHeader)/2);
215 ptr += sizeof(FAD::ChannelHeader);
216
217 //UpdateChannelHeader(i);
218
219 if (ptr+fChannelHeader[i].fRegionOfInterest*2 > end)
220 {
221 Error("Data block exceeds buffer size.");
222 PostClose(false);
223 return;
224 }
225
226 const uint16_t *data = reinterpret_cast<uint16_t*>(ptr);
227 UpdateData(data, fChannelHeader[i].fRegionOfInterest*2);
228 ptr += fChannelHeader[i].fRegionOfInterest*2;
229 }
230
231 if (fIsVerbose)
232 UpdateChannelHeaders();
233
234 fCounter++;
235
236 fBuffer.resize(sizeof(FAD::EventHeader)/2);
237 AsyncRead(ba::buffer(fBuffer), kReadHeader);
238 }
239
240 void HandleReadTimeout(const bs::error_code &error)
241 {
242 if (error==ba::error::basic_errors::operation_aborted)
243 return;
244
245 if (error)
246 {
247 ostringstream str;
248 str << "Read timeout of " << URL() << ": " << error.message() << " (" << error << ")";// << endl;
249 Error(str);
250
251 PostClose();
252 return;
253
254 }
255
256 if (!is_open())
257 {
258 // For example: Here we could schedule a new accept if we
259 // would not want to allow two connections at the same time.
260 return;
261 }
262
263 // Check whether the deadline has passed. We compare the deadline
264 // against the current time since a new asynchronous operation
265 // may have moved the deadline before this actor had a chance
266 // to run.
267 if (fInTimeout.expires_at() > ba::deadline_timer::traits_type::now())
268 return;
269
270 Error("Timeout reading data from "+URL());
271 PostClose();
272 }
273
274 // This is called when a connection was established
275 void ConnectionEstablished()
276 {
277 fBufEventHeader.clear();
278 fBufEventHeader.fEventCounter = 1;
279 fBufEventHeader.fStatus = 0xf000|
280 FAD::EventHeader::kDenable|
281 FAD::EventHeader::kDwrite|
282 FAD::EventHeader::kDcmLocked|
283 FAD::EventHeader::kDcmReady|
284 FAD::EventHeader::kSpiSclk;
285
286 fEventHeader.clear();
287 for (unsigned int i=0; i<FAD::kNumChannels; i++)
288 fChannelHeader[i].clear();
289
290 fCounter = 0;
291
292 fBuffer.resize(sizeof(FAD::EventHeader)/2);
293 AsyncRead(ba::buffer(fBuffer), kReadHeader);
294
295// for (int i=0; i<36; i++)
296// CmdSetRoi(i, 100);
297
298// Cmd(FAD::kCmdTriggerLine, true);
299// Cmd(FAD::kCmdSingleTrigger);
300 }
301
302public:
303 void PostCmd(std::vector<uint16_t> cmd)
304 {
305 if (fBlockTransmission || !IsConnected())
306 return;
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 if (fBlockTransmission || !IsConnected())
323 return;
324
325#ifdef DEBUG_TX
326 ostringstream msg;
327 msg << "Sending command:" << hex;
328 msg << " 0x" << setw(4) << setfill('0') << cmd;
329 Message(msg);
330#endif
331 cmd = htons(cmd);
332 PostMessage(&cmd, sizeof(uint16_t));
333 }
334
335 void PostCmd(uint16_t cmd, uint16_t data)
336 {
337 if (fBlockTransmission || !IsConnected())
338 return;
339
340#ifdef DEBUG_TX
341 ostringstream msg;
342 msg << "Sending command:" << hex;
343 msg << " 0x" << setw(4) << setfill('0') << cmd;
344 msg << " 0x" << setw(4) << setfill('0') << data;
345 Message(msg);
346#endif
347 const uint16_t d[2] = { htons(cmd), htons(data) };
348 PostMessage(d, sizeof(d));
349 }
350
351public:
352 ConnectionFAD(ba::io_service& ioservice, MessageImp &imp, uint16_t slot) :
353 Connection(ioservice, imp()), fSlot(slot),
354 fIsVerbose(false), fIsHexOutput(false), fIsDataOutput(false),
355 fBlockTransmission(false), fCounter(0),
356 fTargetRoi(FAD::kNumChannels)
357 {
358 // Maximum possible needed space:
359 // The full header, all channels with all DRS bins
360 // Two trailing shorts
361 fBuffer.reserve(sizeof(FAD::EventHeader) + FAD::kNumChannels*(sizeof(FAD::ChannelHeader) + FAD::kMaxBins*sizeof(uint16_t)) + 2*sizeof(uint16_t));
362
363 SetLogStream(&imp);
364 }
365
366 void Cmd(FAD::Enable cmd, bool on=true)
367 {
368 switch (cmd)
369 {
370 case FAD::kCmdDrsEnable: fBufEventHeader.Enable(FAD::EventHeader::kDenable, on); break;
371 case FAD::kCmdDwrite: fBufEventHeader.Enable(FAD::EventHeader::kDwrite, on); break;
372 case FAD::kCmdTriggerLine: fBufEventHeader.Enable(FAD::EventHeader::kTriggerLine, on); break;
373 case FAD::kCmdBusy: fBufEventHeader.Enable(FAD::EventHeader::kBusy, on); break;
374 case FAD::kCmdContTrigger: fBufEventHeader.Enable(FAD::EventHeader::kContTrigger, on); break;
375 case FAD::kCmdSocket: fBufEventHeader.Enable(FAD::EventHeader::kSock17, !on); break;
376 default:
377 break;
378 }
379
380 PostCmd(cmd + (on ? 0 : 0x100));
381 }
382
383 // ------------------------------
384
385 // IMPLEMENT: Abs/Rel
386 void CmdPhaseShift(int16_t val)
387 {
388 vector<uint16_t> cmd(abs(val)+2, FAD::kCmdPhaseApply);
389 cmd[0] = FAD::kCmdPhaseReset;
390 cmd[1] = val<0 ? FAD::kCmdPhaseDecrease : FAD::kCmdPhaseIncrease;
391 PostCmd(cmd);
392 }
393
394 bool CmdSetTriggerRate(int32_t val)
395 {
396 if (val<0 || val>0xffff)
397 return false;
398
399 fBufEventHeader.fTriggerGeneratorPrescaler = val;
400 PostCmd(FAD::kCmdWriteRate, val);//uint8_t(1000./val/12.5));
401 //PostCmd(FAD::kCmdWriteExecute);
402
403 return true;
404 }
405
406 void CmdSetRunNumber(uint32_t num)
407 {
408 fBufEventHeader.fRunNumber = num;
409
410 PostCmd(FAD::kCmdWriteRunNumberLSW, num&0xffff);
411 PostCmd(FAD::kCmdWriteRunNumberMSW, num>>16);
412 PostCmd(FAD::kCmdWriteExecute);
413 }
414
415 void CmdSetRegister(uint8_t addr, uint16_t val)
416 {
417 // Allowed addr: [0, MAX_ADDR]
418 // Allowed value: [0, MAX_VAL]
419 PostCmd(FAD::kCmdWrite + addr, val);
420 PostCmd(FAD::kCmdWriteExecute);
421 }
422
423 bool CmdSetDacValue(int8_t addr, uint16_t val)
424 {
425 if (addr<0)
426 {
427 for (unsigned int i=0; i<=FAD::kMaxDacAddr; i++)
428 {
429 fBufEventHeader.fDac[i] = val;
430 PostCmd(FAD::kCmdWriteDac + i, val);
431 }
432 PostCmd(FAD::kCmdWriteExecute);
433 return true;
434 }
435
436 if (uint8_t(addr)>FAD::kMaxDacAddr) // NDAC
437 return false;
438
439 fBufEventHeader.fDac[addr] = val;
440
441 PostCmd(FAD::kCmdWriteDac + addr, val);
442 PostCmd(FAD::kCmdWriteExecute);
443 return true;
444 }
445
446 bool CmdSetRoi(int8_t addr, uint16_t val)
447 {
448 if (val>FAD::kMaxRoiValue)
449 return false;
450
451 if (addr<0)
452 {
453 for (unsigned int i=0; i<=FAD::kMaxRoiAddr; i++)
454 {
455 fTargetRoi[i] = val;
456 PostCmd(FAD::kCmdWriteRoi + i, val);
457 }
458 PostCmd(FAD::kCmdWriteExecute);
459 return true;
460 }
461
462 if (uint8_t(addr)>FAD::kMaxRoiAddr)
463 return false;
464
465 fTargetRoi[addr] = val;
466
467 PostCmd(FAD::kCmdWriteRoi + addr, val);
468 PostCmd(FAD::kCmdWriteExecute);
469 return true;
470 }
471
472 bool CmdSetRoi(uint16_t val) { return CmdSetRoi(-1, val); }
473
474 void AmplitudeCalibration()
475 {
476 // ------------- case baseline -----------------
477
478 CmdSetRoi(-1, FAD::kMaxBins);
479
480 CmdSetDacValue(1, 0);
481 CmdSetDacValue(2, 0);
482 CmdSetDacValue(3, 0);
483
484 // Take N events
485
486 /*
487 // ====== Part B: Baseline calibration =====
488
489 // Loop over all channels(ch) and time-slices (t)
490 T0 = TriggerCell[chip]
491 Sum[ch][(t+T0) % kMaxBins] += Data[ch][t];
492 // FIXME: Determine median instead of average
493
494 Baseline[ch][slice] = MEDIAN( sum[ch][slice] )
495 */
496
497 // --------------- case gain -------------------
498
499 // Set new DAC values and start accumulation
500 CmdSetDacValue(1, 50000);
501 CmdSetDacValue(2, 50000);
502 CmdSetDacValue(3, 50000);
503
504 // Take N events
505
506 /*
507 // ====== Part C: Gain calibration =====
508
509 T0 = TriggerCell[chip]
510 Sum[ch][(t+T0) % kMaxBins] += Data[ch][t];
511 // FIXME: Determine median instead of average
512
513 Gain[ch][slice] = MEDIAN( sum[ch][slice] ) - Baseline[ch][slice]
514 */
515
516 // --------------- secondary ------------------
517
518 // FIXME: Can most probably be done together with the baseline calibration
519 // FIXME: Why does the secondary baseline not influence the baseline?
520
521 CmdSetDacValue(1, 0);
522 CmdSetDacValue(2, 0);
523 CmdSetDacValue(3, 0);
524
525 // Take N events
526
527 /*
528 // ====== Part D: Secondary calibration =====
529
530 T0 = TriggerCell[chip]
531 Sum[ch][t] = Data[ch][t] - Baseline[ch][(i-T0) % kMaxBins];
532
533 // Determine secondary baseline if integration finished
534 SecondaryBaseline[ch][t] = MEDIAN( Sum[ch][t] )
535 */
536 }
537
538 void SetVerbose(bool b)
539 {
540 fIsVerbose = b;
541 }
542
543 void SetHexOutput(bool b)
544 {
545 fIsHexOutput = b;
546 }
547
548 void SetDataOutput(bool b)
549 {
550 fIsDataOutput = b;
551 }
552
553 void SetBlockTransmission(bool b)
554 {
555 fBlockTransmission = b;
556 }
557
558 bool IsTransmissionBlocked() const
559 {
560 return fBlockTransmission;
561 }
562
563 void PrintEvent()
564 {
565 if (fCounter>0)
566 {
567 PrintEventHeader();
568 PrintChannelHeaders();
569 }
570 else
571 Out() << "No event received yet." << endl;
572 }
573
574 bool IsConfigured() const
575 {
576 bool identical = true;
577 for (int i=0; i<FAD::kNumChannels; i++)
578 if (fTargetRoi[i]!=fChannelHeader[i].fRegionOfInterest)
579 {
580 identical = false;
581 break;
582 }
583
584 return fEventHeader==fBufEventHeader && identical;
585 }
586};
587
588// ------------------------------------------------------------------------
589
590template <class T>
591class StateMachineFAD : public T, public EventBuilderWrapper, public ba::io_service, public ba::io_service::work
592{
593private:
594 typedef map<uint8_t, ConnectionFAD*> BoardList;
595
596 BoardList fBoards;
597
598 bool fIsVerbose;
599 bool fIsHexOutput;
600 bool fIsDataOutput;
601 bool fDebugTx;
602
603 bool CheckEventSize(size_t has, const char *name, size_t size)
604 {
605 if (has==size)
606 return true;
607
608 ostringstream msg;
609 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
610 T::Fatal(msg);
611 return false;
612 }
613
614 int Cmd(FAD::Enable command)
615 {
616 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
617 i->second->Cmd(command);
618
619 return T::GetCurrentState();
620 }
621
622 int SendCmd(const EventImp &evt)
623 {
624 if (!CheckEventSize(evt.GetSize(), "SendCmd", 4))
625 return T::kSM_FatalError;
626
627 if (evt.GetUInt()>0xffff)
628 {
629 T::Warn("Command value out of range (0-65535).");
630 return T::GetCurrentState();
631 }
632
633 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
634 i->second->PostCmd(evt.GetUInt());
635
636 return T::GetCurrentState();
637 }
638
639 int SendCmdData(const EventImp &evt)
640 {
641 if (!CheckEventSize(evt.GetSize(), "SendCmdData", 8))
642 return T::kSM_FatalError;
643
644 const uint32_t *ptr = evt.Ptr<uint32_t>();
645
646 if (ptr[0]>0xffff)
647 {
648 T::Warn("Command value out of range (0-65535).");
649 return T::GetCurrentState();
650 }
651
652 if (ptr[1]>0xffff)
653 {
654 T::Warn("Data value out of range (0-65535).");
655 return T::GetCurrentState();
656 }
657
658 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
659 i->second->PostCmd(ptr[0], ptr[1]);
660
661 return T::GetCurrentState();
662 }
663
664 int CmdEnable(const EventImp &evt, FAD::Enable command)
665 {
666 if (!CheckEventSize(evt.GetSize(), "CmdEnable", 1))
667 return T::kSM_FatalError;
668
669 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
670 i->second->Cmd(command, evt.GetBool());
671
672 return T::GetCurrentState();
673 }
674
675 bool Check(const uint32_t *dat, uint32_t maxaddr, uint32_t maxval)
676 {
677 if (dat[0]>maxaddr)
678 {
679 ostringstream msg;
680 msg << hex << "Address " << dat[0] << " out of range, max=" << maxaddr << ".";
681 T::Error(msg);
682 return false;
683 }
684
685 if (dat[1]>maxval)
686 {
687 ostringstream msg;
688 msg << hex << "Value " << dat[1] << " out of range, max=" << maxval << ".";
689 T::Error(msg);
690 return false;
691 }
692
693 return true;
694 }
695
696 int SetRegister(const EventImp &evt)
697 {
698 if (!CheckEventSize(evt.GetSize(), "SetRegister", 8))
699 return T::kSM_FatalError;
700
701 const uint32_t *dat = evt.Ptr<uint32_t>();
702
703 if (!Check(dat, FAD::kMaxRegAddr, FAD::kMaxRegValue))
704 return T::GetCurrentState();
705
706 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
707 i->second->CmdSetRegister(dat[0], dat[1]);
708
709 return T::GetCurrentState();
710 }
711
712 int SetRoi(const EventImp &evt)
713 {
714 if (!CheckEventSize(evt.GetSize(), "SetRoi", 8))
715 return T::kSM_FatalError;
716
717 const int32_t *dat = evt.Ptr<int32_t>();
718
719 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
720 if (!i->second->CmdSetRoi(dat[0], dat[1]))
721 {
722 ostringstream msg;
723 msg << hex << "Channel " << dat[0] << " or Value " << dat[1] << " out of range.";
724 T::Error(msg);
725 return false;
726 }
727
728
729 return T::GetCurrentState();
730 }
731
732 int SetDac(const EventImp &evt)
733 {
734 if (!CheckEventSize(evt.GetSize(), "SetDac", 8))
735 return T::kSM_FatalError;
736
737 const int32_t *dat = evt.Ptr<int32_t>();
738
739 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
740 if (!i->second->CmdSetDacValue(dat[0], dat[1]))
741 {
742 ostringstream msg;
743 msg << hex << "Channel " << dat[0] << " or Value " << dat[1] << " out of range.";
744 T::Error(msg);
745 return false;
746 }
747
748 return T::GetCurrentState();
749 }
750
751 int Trigger(int n)
752 {
753 for (int nn=0; nn<n; nn++)
754 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
755 i->second->Cmd(FAD::kCmdSingleTrigger);
756
757 return T::GetCurrentState();
758 }
759
760 int SendTriggers(const EventImp &evt)
761 {
762 if (!CheckEventSize(evt.GetSize(), "SendTriggers", 4))
763 return T::kSM_FatalError;
764
765 Trigger(evt.GetUInt());
766
767 return T::GetCurrentState();
768 }
769
770 int StartRun(const EventImp &evt, bool start)
771 {
772 if (!CheckEventSize(evt.GetSize(), "StartRun", 0))
773 return T::kSM_FatalError;
774
775 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
776 i->second->Cmd(FAD::kCmdRun, start);
777
778 return T::GetCurrentState();
779 }
780
781 int PhaseShift(const EventImp &evt)
782 {
783 if (!CheckEventSize(evt.GetSize(), "PhaseShift", 2))
784 return T::kSM_FatalError;
785
786 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
787 i->second->CmdPhaseShift(evt.GetShort());
788
789 return T::GetCurrentState();
790 }
791
792 int SetTriggerRate(const EventImp &evt)
793 {
794 if (!CheckEventSize(evt.GetSize(), "SetTriggerRate", 4))
795 return T::kSM_FatalError;
796
797 if (evt.GetUInt()>0xffff)
798 {
799 ostringstream msg;
800 msg << hex << "Value " << evt.GetUShort() << " out of range, max=" << 0xffff << "(?)";
801 T::Error(msg);
802 return false;
803 }
804
805 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
806 i->second->CmdSetTriggerRate(evt.GetUInt());
807
808 return T::GetCurrentState();
809 }
810
811 int SetRunNumber(const EventImp &evt)
812 {
813 if (!CheckEventSize(evt.GetSize(), "SetRunNumber", 8))
814 return T::kSM_FatalError;
815
816 const uint64_t num = evt.GetUXtra();
817
818 if (num>FAD::kMaxRunNumber)
819 {
820 ostringstream msg;
821 msg << hex << "Value " << num << " out of range, max=" << FAD::kMaxRunNumber;
822 T::Error(msg);
823 return false;
824 }
825
826 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
827 i->second->CmdSetRunNumber(num);
828
829 return T::GetCurrentState();
830 }
831
832 int SetMaxMemoryBuffer(const EventImp &evt)
833 {
834 if (!CheckEventSize(evt.GetSize(), "SetMaxMemoryBuffer", 2))
835 return T::kSM_FatalError;
836
837 const int16_t mem = evt.GetShort();
838
839 if (mem<=0)
840 {
841 ostringstream msg;
842 msg << hex << "Value " << mem << " out of range.";
843 T::Error(msg);
844 return false;
845 }
846
847 SetMaxMemory(mem);
848
849 return T::GetCurrentState();
850 }
851
852 int SetFileFormat(const EventImp &evt)
853 {
854 if (!CheckEventSize(evt.GetSize(), "SetFileFormat", 2))
855 return T::kSM_FatalError;
856
857 const uint16_t fmt = evt.GetUShort();
858
859 switch (fmt)
860 {
861 case 0: SetOutputFormat(kNone); break;
862 case 1: SetOutputFormat(kDebug); break;
863 case 2: SetOutputFormat(kFits); break;
864 case 3: SetOutputFormat(kRaw); break;
865 default:
866 T::Error("File format unknonw.");
867 return false;
868 }
869
870 return T::GetCurrentState();
871 }
872
873 int Test(const EventImp &evt)
874 {
875 if (!CheckEventSize(evt.GetSize(), "Test", 2))
876 return T::kSM_FatalError;
877
878
879 SetMode(evt.GetShort());
880
881 return T::GetCurrentState();
882 }
883
884
885 int SetVerbosity(const EventImp &evt)
886 {
887 if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
888 return T::kSM_FatalError;
889
890 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
891 i->second->SetVerbose(evt.GetBool());
892
893 return T::GetCurrentState();
894 }
895
896 int SetHexOutput(const EventImp &evt)
897 {
898 if (!CheckEventSize(evt.GetSize(), "SetHexOutput", 1))
899 return T::kSM_FatalError;
900
901 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
902 i->second->SetHexOutput(evt.GetBool());
903
904 return T::GetCurrentState();
905 }
906
907 int SetDataOutput(const EventImp &evt)
908 {
909 if (!CheckEventSize(evt.GetSize(), "SetDataOutput", 1))
910 return T::kSM_FatalError;
911
912 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
913 i->second->SetDataOutput(evt.GetBool());
914
915 return T::GetCurrentState();
916 }
917
918 int SetDebugTx(const EventImp &evt)
919 {
920 if (!CheckEventSize(evt.GetSize(), "SetDebugTx", 1))
921 return T::kSM_FatalError;
922
923 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
924 i->second->SetDebugTx(evt.GetBool());
925
926 return T::GetCurrentState();
927 }
928
929 int SetDebugEb(const EventImp &evt)
930 {
931 if (!CheckEventSize(evt.GetSize(), "SetDebugEb", 1))
932 return T::kSM_FatalError;
933
934 SetDebugLog(evt.GetBool());
935
936 return T::GetCurrentState();
937 }
938
939 const BoardList::iterator GetSlot(uint16_t slot)
940 {
941 const BoardList::iterator it=fBoards.find(slot);
942 if (it==fBoards.end())
943 {
944 ostringstream str;
945 str << "Slot " << slot << " not found.";
946 T::Warn(str);
947 }
948
949 return it;
950 }
951
952 int PrintEvent(const EventImp &evt)
953 {
954 if (!CheckEventSize(evt.GetSize(), "PrintEvent", 2))
955 return T::kSM_FatalError;
956
957 const int16_t slot = evt.Get<int16_t>();
958
959 if (slot<0)
960 {
961 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
962 i->second->PrintEvent();
963 }
964 else
965 {
966 const BoardList::iterator it=GetSlot(slot);
967 if (it!=fBoards.end())
968 it->second->PrintEvent();
969 }
970
971 return T::GetCurrentState();
972 }
973
974 int SetBlockTransmission(const EventImp &evt)
975 {
976 if (!CheckEventSize(evt.GetSize(), "SetBlockTransmission", 3))
977 return T::kSM_FatalError;
978
979 const int16_t slot = evt.Get<int32_t>();
980
981 const BoardList::iterator it=GetSlot(slot);
982 if (it!=fBoards.end())
983 it->second->SetBlockTransmission(evt.Get<uint8_t>(2));
984
985 return T::GetCurrentState();
986 }
987
988 int SetBlockTransmissionRange(const EventImp &evt)
989 {
990 if (!CheckEventSize(evt.GetSize(), "SetBlockTransmissionRange", 5))
991 return T::kSM_FatalError;
992
993 const int16_t *slot = evt.Ptr<int16_t>();
994 const bool block = evt.Get<uint8_t>(4);
995
996 for (int i=slot[0]; i<=slot[1]; i++)
997 {
998 const BoardList::iterator it=GetSlot(i);
999 if (it!=fBoards.end())
1000 it->second->SetBlockTransmission(block);
1001 }
1002
1003 return T::GetCurrentState();
1004 }
1005
1006 int SetIgnoreSlot(const EventImp &evt)
1007 {
1008 if (!CheckEventSize(evt.GetSize(), "SetIgnoreSlot", 3))
1009 return T::kSM_FatalError;
1010
1011 const uint16_t slot = evt.Get<uint16_t>();
1012
1013 if (slot>39)
1014 {
1015 T::Warn("Slot out of range (0-39).");
1016 return T::GetCurrentState();
1017 }
1018
1019 SetIgnore(slot, evt.Get<uint8_t>(2));
1020
1021 return T::GetCurrentState();
1022 }
1023
1024 int SetIgnoreSlots(const EventImp &evt)
1025 {
1026 if (!CheckEventSize(evt.GetSize(), "SetIgnoreSlots", 5))
1027 return T::kSM_FatalError;
1028
1029 const int16_t *slot = evt.Ptr<int16_t>();
1030 const bool block = evt.Get<uint8_t>(4);
1031
1032 if (slot[0]<0 || slot[1]>39 || slot[0]>slot[1])
1033 {
1034 T::Warn("Slot out of range.");
1035 return T::GetCurrentState();
1036 }
1037
1038 for (int i=slot[0]; i<=slot[1]; i++)
1039 SetIgnore(i, block);
1040
1041 return T::GetCurrentState();
1042 }
1043
1044 int SetDumpStream(const EventImp &evt)
1045 {
1046 if (!CheckEventSize(evt.GetSize(), "SetDumpStream", 1))
1047 return T::kSM_FatalError;
1048
1049 SetDebugStream(evt.Get<uint8_t>());
1050
1051 return T::GetCurrentState();
1052 }
1053
1054 int SetDumpRecv(const EventImp &evt)
1055 {
1056 if (!CheckEventSize(evt.GetSize(), "SetDumpRecv", 1))
1057 return T::kSM_FatalError;
1058
1059 SetDebugRead(evt.Get<uint8_t>());
1060
1061 return T::GetCurrentState();
1062 }
1063
1064 int StartConfigure(const EventImp &evt)
1065 {
1066 const string name = evt.GetText();
1067
1068 fTargetConfig = fConfigs.find(name);
1069 if (fTargetConfig==fConfigs.end())
1070 {
1071 T::Error("StartConfigure - Run-type '"+name+"' not found.");
1072 return T::GetCurrentState();
1073 }
1074
1075 const uint32_t runno = StartNewRun();
1076
1077 ostringstream str;
1078 str << "Starting configuration for run " << runno << " (" << name << ")";
1079 T::Message(str.str());
1080
1081 for (BoardList::iterator it=fBoards.begin(); it!=fBoards.end(); it++)
1082 {
1083 const FAD::Configuration &conf = fTargetConfig->second;
1084
1085 ConnectionFAD &fad = *it->second;
1086
1087 fad.Cmd(FAD::kCmdTriggerLine, false);
1088 fad.Cmd(FAD::kCmdContTrigger, false);
1089 fad.Cmd(FAD::kCmdSocket, true);
1090 fad.Cmd(FAD::kCmdBusy, false);
1091
1092 fad.Cmd(FAD::kCmdDwrite, conf.fDenable);
1093 fad.Cmd(FAD::kCmdDrsEnable, conf.fDwrite);
1094 fad.Cmd(FAD::kCmdContTrigger, conf.fContinousTrigger);
1095
1096 for (int i=0; i<FAD::kNumDac; i++)
1097 fad.CmdSetDacValue(i, conf.fDac[i]);
1098
1099 for (int i=0; i<FAD::kNumChips; i++)
1100 for (int j=0; j<FAD::kNumChannelsPerChip; j++)
1101 fad.CmdSetRoi(i*FAD::kNumChannelsPerChip+j, conf.fRoi[j]);
1102
1103 fad.CmdSetTriggerRate(conf.fTriggerRate);
1104 fad.CmdSetRunNumber(runno);
1105 fad.Cmd(FAD::kCmdResetEventCounter);
1106 fad.Cmd(FAD::kCmdSingleTrigger);
1107 }
1108
1109 return FAD::kConfiguring;
1110 }
1111
1112 int ResetConfig()
1113 {
1114 return FAD::kConnected;
1115 }
1116
1117 int AddAddress(const EventImp &evt)
1118 {
1119 const string addr = Tools::Trim(evt.GetText());
1120
1121 const tcp::endpoint endpoint = GetEndpoint(addr);
1122 if (endpoint==tcp::endpoint())
1123 return T::GetCurrentState();
1124
1125 for (BoardList::const_iterator i=fBoards.begin(); i!=fBoards.end(); i++)
1126 {
1127 if (i->second->GetEndpoint()==endpoint)
1128 {
1129 T::Warn("Address "+addr+" already known.... ignored.");
1130 return T::GetCurrentState();
1131 }
1132 }
1133
1134 AddEndpoint(endpoint);
1135
1136 return T::GetCurrentState();
1137 }
1138
1139 int RemoveSlot(const EventImp &evt)
1140 {
1141 if (!CheckEventSize(evt.GetSize(), "RemoveSlot", 2))
1142 return T::kSM_FatalError;
1143
1144 const int16_t slot = evt.GetShort();
1145
1146 const BoardList::iterator it = GetSlot(slot);
1147
1148 if (it==fBoards.end())
1149 return T::GetCurrentState();
1150
1151 ConnectSlot(slot, tcp::endpoint());
1152
1153 delete it->second;
1154 fBoards.erase(it);
1155
1156 return T::GetCurrentState();
1157 }
1158
1159 int ListSlots()
1160 {
1161 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
1162 {
1163 const int &idx = i->first;
1164 const ConnectionFAD *fad = i->second;
1165
1166 ostringstream str;
1167 str << "Slot " << setw(2) << idx << ": " << fad->GetEndpoint();
1168
1169 if (fad->IsConnecting())
1170 str << " (0:connecting, ";
1171 else
1172 {
1173 if (fad->IsClosed())
1174 str << " (0:disconnected, ";
1175 if (fad->IsConnected())
1176 str << " (0:connected, ";
1177 }
1178
1179 switch (fStatus2[idx])
1180 {
1181 case 0: str << "1-7:not connected)"; break;
1182 case 8: str << "1-7:connected)"; break;
1183 default: str << "1-7:connecting [" << (int)(fStatus2[idx]-1) << "])"; break;
1184 }
1185
1186 if (fad->IsTransmissionBlocked())
1187 str << " [cmd_blocked]";
1188
1189 if (fStatus2[idx]==8 && IsIgnored(idx))
1190 str << " [data_ignored]";
1191
1192 if (fStatusC[idx])
1193 str << " [configured]";
1194
1195 T::Out() << str.str() << endl;
1196 }
1197
1198 T::Out() << "Event builder thread:";
1199 if (!IsThreadRunning())
1200 T::Out() << " not";
1201 T::Out() << " running" << endl;
1202
1203 // FIXME: Output state
1204
1205 return T::GetCurrentState();
1206 }
1207
1208 void EnableConnection(ConnectionFAD *ptr, bool enable=true)
1209 {
1210 if (!enable)
1211 {
1212 ptr->PostClose(false);
1213 return;
1214 }
1215
1216 if (!ptr->IsDisconnected())
1217 {
1218 ostringstream str;
1219 str << ptr->GetEndpoint();
1220
1221 T::Warn("Connection to "+str.str()+" already in progress.");
1222 return;
1223 }
1224
1225 ptr->StartConnect();
1226 }
1227
1228 void EnableAll(bool enable=true)
1229 {
1230 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
1231 EnableConnection(i->second, enable);
1232 }
1233
1234 int CloseOpenFiles()
1235 {
1236 EventBuilderWrapper::CloseOpenFiles();
1237 return T::GetCurrentState();
1238 }
1239
1240 int EnableSlot(const EventImp &evt, bool enable)
1241 {
1242 if (!CheckEventSize(evt.GetSize(), "EnableSlot", 2))
1243 return T::kSM_FatalError;
1244
1245 const int16_t slot = evt.GetShort();
1246
1247 const BoardList::iterator it = GetSlot(slot);
1248 if (it==fBoards.end())
1249 return T::GetCurrentState();
1250
1251 EnableConnection(it->second, enable);
1252 ConnectSlot(it->first, enable ? it->second->GetEndpoint() : tcp::endpoint());
1253
1254 return T::GetCurrentState();
1255 }
1256
1257 int ToggleSlot(const EventImp &evt)
1258 {
1259 if (!CheckEventSize(evt.GetSize(), "ToggleSlot", 2))
1260 return T::kSM_FatalError;
1261
1262 const int16_t slot = evt.GetShort();
1263
1264 const BoardList::iterator it = GetSlot(slot);
1265 if (it==fBoards.end())
1266 return T::GetCurrentState();
1267
1268 const bool enable = it->second->IsDisconnected();
1269
1270 EnableConnection(it->second, enable);
1271 ConnectSlot(it->first, enable ? it->second->GetEndpoint() : tcp::endpoint());
1272
1273 return T::GetCurrentState();
1274 }
1275
1276 int StartConnection()
1277 {
1278 vector<tcp::endpoint> addr(40);
1279
1280 for (BoardList::iterator i=fBoards.begin(); i!=fBoards.end(); i++)
1281 addr[i->first] = i->second->GetEndpoint();
1282
1283 StartThread(addr);
1284 EnableAll(true);
1285
1286 return T::GetCurrentState();
1287 }
1288
1289 int StopConnection()
1290 {
1291 Exit();
1292 EnableAll(false);
1293 return T::GetCurrentState();
1294 }
1295
1296 int AbortConnection()
1297 {
1298 Abort();
1299 EnableAll(false);
1300 return T::GetCurrentState();
1301 }
1302
1303 int Reset(bool soft)
1304 {
1305 ResetThread(soft);
1306 return T::GetCurrentState();
1307 }
1308
1309 vector<uint8_t> fStatus1;
1310 vector<uint8_t> fStatus2;
1311 vector<uint8_t> fStatusC;
1312 bool fStatusT;
1313
1314 int Execute()
1315 {
1316 // Dispatch (execute) at most one handler from the queue. In contrary
1317 // to run_one(), it doesn't wait until a handler is available
1318 // which can be dispatched, so poll_one() might return with 0
1319 // handlers dispatched. The handlers are always dispatched/executed
1320 // synchronously, i.e. within the call to poll_one()
1321 poll_one();
1322
1323 // ===== Evaluate connection status =====
1324
1325 uint16_t nclosed1 = 0;
1326 uint16_t nconnecting1 = 0;
1327 uint16_t nconnecting2 = 0;
1328 uint16_t nconnected1 = 0;
1329 uint16_t nconnected2 = 0;
1330 uint16_t nconfigured = 0;
1331
1332 vector<uint8_t> stat1(40);
1333 vector<uint8_t> stat2(40);
1334 vector<bool> statC(40);
1335
1336 int cnt = 0; // counter for enabled board
1337
1338 const bool runs = IsThreadRunning();
1339
1340 for (int idx=0; idx<40; idx++)
1341 {
1342 // ----- Command socket -----
1343 const BoardList::const_iterator &slot = fBoards.find(idx);
1344 if (slot!=fBoards.end())
1345 {
1346 const ConnectionFAD *c = slot->second;
1347 if (c->IsDisconnected())
1348 {
1349 stat1[idx] = 0;
1350 nclosed1++;
1351
1352 //DisconnectSlot(idx);
1353 }
1354 if (c->IsConnecting())
1355 {
1356 stat1[idx] = 1;
1357 nconnecting1++;
1358 }
1359 if (c->IsConnected())
1360 {
1361 stat1[idx] = 2;
1362 nconnected1++;
1363
1364 if (c->IsConfigured())
1365 {
1366 statC[idx] = 1;
1367 nconfigured++;
1368 }
1369 }
1370
1371 cnt++;
1372 }
1373
1374 // ----- Event builder -----
1375
1376 if (!runs)
1377 continue;
1378
1379 stat2[idx] = GetNumConnected(idx);
1380
1381 if (IsConnecting(idx))
1382 {
1383 nconnecting2++;
1384 stat2[idx]++;
1385 }
1386
1387 if (IsConnected(idx))
1388 {
1389 stat2[idx]++;
1390 nconnected2++;
1391 }
1392 }
1393
1394 // ===== Send connection status via dim =====
1395
1396 if (fStatus1!=stat1 || fStatus2!=stat2 || fStatusT!=IsThreadRunning())
1397 {
1398 fStatus1 = stat1;
1399 fStatus2 = stat2;
1400 fStatusT = runs;
1401 UpdateConnectionStatus(stat1, stat2, IsThreadRunning());
1402 }
1403
1404 // ===== Return connection status =====
1405
1406 // fadctrl: Always connecting if not disabled
1407 // event builder:
1408 if (nconnecting1==0 && nconnected1>0 && nconnected2==nconnected1)
1409 {
1410 if (T::GetCurrentState()==FAD::kConfigured && IsRunStarted())
1411 return FAD::kConnected;
1412
1413 if (nconfigured!=nconnected1)
1414 {
1415
1416 if (T::GetCurrentState()==FAD::kConfiguring ||
1417 T::GetCurrentState()==FAD::kConfigured)
1418 // Stay in Configured until at least one new
1419 // event has been received
1420 return T::GetCurrentState();
1421
1422 return FAD::kConnected;
1423 }
1424
1425 if (T::GetCurrentState()==FAD::kConfiguring)
1426 {
1427 for (BoardList::iterator it=fBoards.begin(); it!=fBoards.end(); it++)
1428 {
1429 //const Configuration &conf = fTargetConfig->second;
1430
1431 ConnectionFAD &fad = *it->second;
1432
1433 fad.Cmd(FAD::kCmdResetEventCounter);
1434 fad.Cmd(FAD::kCmdSocket, false);
1435 fad.Cmd(FAD::kCmdTriggerLine, true);
1436
1437 // FIXME: How do we find out when the FADs
1438 // successfully enabled the trigger lines?
1439 }
1440 return FAD::kConfigured;
1441 }
1442
1443 return FAD::kConnected;
1444 }
1445
1446 if (nconnecting1>0 || nconnecting2>0 || nconnected1!=nconnected2)
1447 return FAD::kConnecting;
1448
1449 // nconnected1 == nconnected2 == 0
1450 return IsThreadRunning() ? FAD::kDisconnected : FAD::kOffline;
1451 }
1452
1453 void AddEndpoint(const tcp::endpoint &addr)
1454 {
1455 int i=0;
1456 while (i<40)
1457 {
1458 if (fBoards.find(i)==fBoards.end())
1459 break;
1460 i++;
1461 }
1462
1463 if (i==40)
1464 {
1465 T::Warn("Not more than 40 slots allowed.");
1466 return;
1467 }
1468
1469 ConnectionFAD *fad = new ConnectionFAD(*this, *this, i);
1470
1471 fad->SetEndpoint(addr);
1472 fad->SetVerbose(fIsVerbose);
1473 fad->SetHexOutput(fIsHexOutput);
1474 fad->SetDataOutput(fIsDataOutput);
1475 fad->SetDebugTx(fDebugTx);
1476
1477 fBoards[i] = fad;
1478 }
1479
1480
1481 DimDescribedService fDimConnection;
1482
1483 void UpdateConnectionStatus(const vector<uint8_t> &stat1, const vector<uint8_t> &stat2, bool thread)
1484 {
1485 vector<uint8_t> stat(41);
1486
1487 for (int i=0; i<40; i++)
1488 stat[i] = stat1[i]|(stat2[i]<<3);
1489
1490 stat[40] = thread;
1491
1492 fDimConnection.setData(stat.data(), 41);
1493 fDimConnection.updateService();
1494 }
1495
1496public:
1497 StateMachineFAD(ostream &out=cout) :
1498 T(out, "FAD_CONTROL"), EventBuilderWrapper(*static_cast<MessageImp*>(this)), ba::io_service::work(static_cast<ba::io_service&>(*this)),
1499 fStatus1(40), fStatus2(40), fStatusC(40), fStatusT(false),
1500 fDimConnection("FAD_CONTROL/CONNECTIONS", "C:40;C:1", "")
1501 {
1502 // ba::io_service::work is a kind of keep_alive for the loop.
1503 // It prevents the io_service to go to stopped state, which
1504 // would prevent any consecutive calls to run()
1505 // or poll() to do nothing. reset() could also revoke to the
1506 // previous state but this might introduce some overhead of
1507 // deletion and creation of threads and more.
1508
1509 // State names
1510 T::AddStateName(FAD::kOffline, "Disengaged",
1511 "All enabled FAD boards are disconnected and the event-builer thread is not running.");
1512
1513 T::AddStateName(FAD::kDisconnected, "Disconnected",
1514 "All enabled FAD boards are disconnected, but the event-builder thread is running.");
1515
1516 T::AddStateName(FAD::kConnecting, "Connecting",
1517 "Only some enabled FAD boards are connected.");
1518
1519 T::AddStateName(FAD::kConnected, "Connected",
1520 "All enabled FAD boards are connected..");
1521
1522 T::AddStateName(FAD::kConfiguring, "Configuring",
1523 ".");
1524
1525 T::AddStateName(FAD::kConfigured, "Configured",
1526 "The last header received through the command socket fits the requested configureation and has EventCounter==0.");
1527
1528 // FAD Commands
1529 T::AddEvent("SEND_CMD", "I:1")
1530 (boost::bind(&StateMachineFAD::SendCmd, this, _1))
1531 ("Send a command to the FADs. Values between 0 and 0xffff are allowed."
1532 "|command[uint16]:Command to be transmittted.");
1533 T::AddEvent("SEND_DATA", "I:2")
1534 (boost::bind(&StateMachineFAD::SendCmdData, this, _1))
1535 ("Send a command with data to the FADs. Values between 0 and 0xffff are allowed."
1536 "|command[uint16]:Command to be transmittted."
1537 "|data[uint16]:Data to be sent with the command.");
1538
1539 T::AddEvent("ENABLE_SRCLK", "B:1")
1540 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdSrclk))
1541 ("Set SRCLK");
1542 T::AddEvent("ENABLE_BUSY", "B:1")
1543 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdBusy))
1544 ("Set BUSY");
1545 T::AddEvent("ENABLE_SCLK", "B:1")
1546 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdSclk))
1547 ("Set SCLK");
1548 T::AddEvent("ENABLE_DRS", "B:1")
1549 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdDrsEnable))
1550 ("Switch Domino wave");
1551 T::AddEvent("ENABLE_DWRITE", "B:1")
1552 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdDwrite))
1553 ("Set Dwrite (possibly high / always low)");
1554 T::AddEvent("ENABLE_CONTINOUS_TRIGGER", "B:1")
1555 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdContTrigger))
1556 ("Enable continous (internal) trigger.");
1557 T::AddEvent("ENABLE_TRIGGER_LINE", "B:1")
1558 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdTriggerLine))
1559 ("Incoming triggers can be accepted/will not be accepted");
1560 T::AddEvent("ENABLE_COMMAND_SOCKET_MODE", "B:1")
1561 (boost::bind(&StateMachineFAD::CmdEnable, this, _1, FAD::kCmdSocket))
1562 ("Set debug mode (yes: dump events through command socket, no=dump events through other sockets)");
1563
1564 T::AddEvent("SET_TRIGGER_RATE", "I:1")
1565 (boost::bind(&StateMachineFAD::SetTriggerRate, this, _1))
1566 ("Enable continous trigger");
1567 T::AddEvent("SEND_SINGLE_TRIGGER")
1568 (boost::bind(&StateMachineFAD::Trigger, this, 1))
1569 ("Issue software triggers");
1570 T::AddEvent("SEND_N_TRIGGERS", "I")
1571 (boost::bind(&StateMachineFAD::SendTriggers, this, _1))
1572 ("Issue software triggers");
1573 T::AddEvent("START_RUN", "")
1574 (boost::bind(&StateMachineFAD::StartRun, this, _1, true))
1575 ("Set FAD DAQ mode. when started, no configurations must be send.");
1576 T::AddEvent("STOP_RUN")
1577 (boost::bind(&StateMachineFAD::StartRun, this, _1, false))
1578 ("");
1579 T::AddEvent("PHASE_SHIFT", "S:1")
1580 (boost::bind(&StateMachineFAD::PhaseShift, this, _1))
1581 ("Adjust ADC phase (in 'steps')");
1582
1583 T::AddEvent("RESET_EVENT_COUNTER")
1584 (boost::bind(&StateMachineFAD::Cmd, this, FAD::kCmdResetEventCounter))
1585 ("");
1586
1587 T::AddEvent("SET_RUN_NUMBER", "X:1")
1588 (boost::bind(&StateMachineFAD::SetRunNumber, this, _1))
1589 ("");
1590
1591 T::AddEvent("SET_MAX_MEMORY", "S:1")
1592 (boost::bind(&StateMachineFAD::SetMaxMemoryBuffer, this, _1))
1593 ("Set maximum memory buffer size allowed to be consumed by the EventBuilder to buffer events."
1594 "|memory[short]:Buffer size in Mega-bytes.");
1595
1596 T::AddEvent("SET_REGISTER", "I:2")
1597 (boost::bind(&StateMachineFAD::SetRegister, this, _1))
1598 ("set register to value"
1599 "|addr[short]:Address of register"
1600 "|val[short]:Value to be set");
1601
1602 // FIXME: Maybe add a mask which channels should be set?
1603 T::AddEvent("SET_REGION_OF_INTEREST", "I:2")
1604 (boost::bind(&StateMachineFAD::SetRoi, this, _1))
1605 ("Set region-of-interest to value"
1606 "|addr[short]:Address of register"
1607 "|val[short]:Value to be set");
1608
1609 // FIXME: Maybe add a mask which channels should be set?
1610 T::AddEvent("SET_DAC_VALUE", "I:2")
1611 (boost::bind(&StateMachineFAD::SetDac, this, _1))
1612 ("Set DAC numbers in range to value"
1613 "|addr[short]:Address of register (-1 for all)"
1614 "|val[short]:Value to be set");
1615
1616 T::AddEvent("CONFIGURE", "C", FAD::kConnected, FAD::kConfigured)
1617 (boost::bind(&StateMachineFAD::StartConfigure, this, _1))
1618 ("");
1619
1620 T::AddEvent("RESET_CONFIGURE", FAD::kConfiguring, FAD::kConfigured)
1621 (boost::bind(&StateMachineFAD::ResetConfig, this))
1622 ("");
1623
1624 // Verbosity commands
1625 T::AddEvent("SET_VERBOSE", "B:1")
1626 (boost::bind(&StateMachineFAD::SetVerbosity, this, _1))
1627 ("Set verbosity state"
1628 "|verbosity[bool]:disable or enable verbosity for received data (yes/no), except dynamic data");
1629
1630 T::AddEvent("SET_HEX_OUTPUT", "B:1")
1631 (boost::bind(&StateMachineFAD::SetHexOutput, this, _1))
1632 ("Enable or disable hex output for received data"
1633 "|hexout[bool]:disable or enable hex output for received data (yes/no)");
1634
1635 T::AddEvent("SET_DATA_OUTPUT", "B:1")
1636 (boost::bind(&StateMachineFAD::SetDataOutput, this, _1))
1637 ("");
1638
1639 T::AddEvent("SET_DEBUG_TX", "B:1")
1640 (boost::bind(&StateMachineFAD::SetDebugTx, this, _1))
1641 ("Enable or disable the output of messages in case of successfull data transmission to the boards."
1642 "|debug[bool]:disable or enable debug output for transmitted data (yes/no)");
1643
1644 T::AddEvent("SET_DEBUG_EVENT_BUILDER_OUT", "B:1")
1645 (boost::bind(&StateMachineFAD::SetDebugEb, this, _1))
1646 ("");
1647
1648 T::AddEvent("PRINT_EVENT", "S:1")
1649 (boost::bind(&StateMachineFAD::PrintEvent, this, _1))
1650 ("Print (last) event"
1651 "|board[short]:slot from which the event should be printed (-1 for all)");
1652
1653 T::AddEvent("DUMP_STREAM", "B:1")
1654 (boost::bind(&StateMachineFAD::SetDumpStream, this, _1))
1655 ("For debugging purpose: the binary data stream read from the sockets 0-7 can be dumped to files."
1656 "|switch[bool]:Enable (yes) or disable (no)");
1657
1658 T::AddEvent("DUMP_RECV", "B:1")
1659 (boost::bind(&StateMachineFAD::SetDumpRecv, this, _1))
1660 ("For debugging purpose: the times when data has been receives are dumped to a file."
1661 "|switch[bool]:Enable (yes) or disable (no)");
1662
1663 T::AddEvent("BLOCK_TRANSMISSION", "S:1;B:1")
1664 (boost::bind(&StateMachineFAD::SetBlockTransmission, this, _1))
1665 ("Blocks the transmission of commands to the given slot. Use with care! For debugging pupose only!"
1666 "|slot[short]:Slot to which the command transmission should be blocked (0-39)"
1667 "|enable[bool]:Whether the command transmission should be blockes (yes) or allowed (no)");
1668
1669 T::AddEvent("BLOCK_TRANSMISSION_RANGE", "S:2;B:1")
1670 (boost::bind(&StateMachineFAD::SetBlockTransmissionRange, this, _1))
1671 ("Blocks the transmission of commands to the given range of slots. Use with care! For debugging pupose only!"
1672 "|first[short]:First slot to which the command transmission should be blocked (0-39)"
1673 "|last[short]:Last slot to which the command transmission should be blocked (0-39)"
1674 "|enable[bool]:Whether the command transmission should be blockes (yes) or allowed (no)");
1675
1676 T::AddEvent("IGNORE_EVENTS", "S:1;B:1")
1677 (boost::bind(&StateMachineFAD::SetIgnoreSlot, this, _1))
1678 ("Instructs the event-builder to ignore events from the given slot but still read the data from the socket."
1679 "|slot[short]:Slot from which the data should be ignored when building events"
1680 "|enable[bool]:Whether the event builder should ignore data from this slot (yes) or allowed (no)");
1681
1682 T::AddEvent("IGNORE_EVENTS_RANGE", "S:2;B:1")
1683 (boost::bind(&StateMachineFAD::SetIgnoreSlots, this, _1))
1684 ("Instructs the event-builder to ignore events from the given slot but still read the data from the socket."
1685 "|first[short]:First slot from which the data should be ignored when building events"
1686 "|last[short]:Last slot from which the data should be ignored when building events"
1687 "|enable[bool]:Whether the event builder should ignore data from this slot (yes) or allowed (no)");
1688
1689 T::AddEvent("CLOSE_OPEN_FILES", FAD::kConnecting, FAD::kConnected)
1690 (boost::bind(&StateMachineFAD::CloseOpenFiles, this))
1691 ("Close all run files opened by the EventBuilder.");
1692
1693 T::AddEvent("TEST", "S:1")
1694 (boost::bind(&StateMachineFAD::Test, this, _1))
1695 ("");
1696
1697
1698
1699 // Conenction commands
1700 T::AddEvent("START", FAD::kOffline)
1701 (boost::bind(&StateMachineFAD::StartConnection, this))
1702 ("Start EventBuilder thread and connect all valid slots.");
1703
1704 T::AddEvent("STOP", FAD::kDisconnected, FAD::kConnecting, FAD::kConnected)
1705 (boost::bind(&StateMachineFAD::StopConnection, this))
1706 ("Stop EventBuilder thread (still write buffered events) and disconnect all slots.");
1707
1708 T::AddEvent("ABORT", FAD::kDisconnected, FAD::kConnecting, FAD::kConnected)
1709 (boost::bind(&StateMachineFAD::AbortConnection, this))
1710 ("Immediately abort EventBuilder thread and disconnect all slots.");
1711
1712 T::AddEvent("SOFT_RESET", FAD::kConnected)
1713 (boost::bind(&StateMachineFAD::Reset, this, true))
1714 ("Wait for buffers to drain, close all files and reinitialize event builder thread.");
1715
1716 T::AddEvent("HARD_RESET", FAD::kConnected)
1717 (boost::bind(&StateMachineFAD::Reset, this, false))
1718 ("Free all buffers, close all files and reinitialize event builder thread.");
1719
1720 T::AddEvent("CONNECT", "S:1", FAD::kDisconnected, FAD::kConnecting, FAD::kConnected)
1721 (boost::bind(&StateMachineFAD::EnableSlot, this, _1, true))
1722 ("Connect a disconnected slot.");
1723
1724 T::AddEvent("DISCONNECT", "S:1", FAD::kConnecting, FAD::kConnected)
1725 (boost::bind(&StateMachineFAD::EnableSlot, this, _1, false))
1726 ("Disconnect a connected slot.");
1727
1728 T::AddEvent("TOGGLE", "S:1", FAD::kDisconnected, FAD::kConnecting, FAD::kConnected)
1729 (boost::bind(&StateMachineFAD::ToggleSlot, this, _1))
1730 ("");
1731
1732 T::AddEvent("SET_FILE_FORMAT", "S:1")
1733 (boost::bind(&StateMachineFAD::SetFileFormat, this, _1))
1734 ("");
1735
1736
1737 T::AddEvent("ADD_ADDRESS", "C", FAD::kOffline)
1738 (boost::bind(&StateMachineFAD::AddAddress, this, _1))
1739 ("Add the address of a DRS4 board to the first free slot"
1740 "|IP[string]:address in the format <address:port>");
1741 T::AddEvent("REMOVE_SLOT", "S:1", FAD::kOffline)
1742 (boost::bind(&StateMachineFAD::RemoveSlot, this, _1))
1743 ("Remove the Iaddress in slot n. For a list see LIST"
1744 "|slot[short]:Remove the address in slot n from the list");
1745 T::AddEvent("LIST_SLOTS")
1746 (boost::bind(&StateMachineFAD::ListSlots, this))
1747 ("Print a list of all available board addressesa and whether they are enabled");
1748 }
1749
1750 ~StateMachineFAD()
1751 {
1752 for (BoardList::const_iterator i=fBoards.begin(); i!=fBoards.end(); i++)
1753 delete i->second;
1754 fBoards.clear();
1755 }
1756
1757 tcp::endpoint GetEndpoint(const string &base)
1758 {
1759 const size_t p0 = base.find_first_of(':');
1760 const size_t p1 = base.find_last_of(':');
1761
1762 if (p0==string::npos || p0!=p1)
1763 {
1764 T::Out() << kRed << "GetEndpoint - Wrong format ('host:port' expected)" << endl;
1765 return tcp::endpoint();
1766 }
1767
1768 tcp::resolver resolver(get_io_service());
1769
1770 boost::system::error_code ec;
1771
1772 const tcp::resolver::query query(base.substr(0, p0), base.substr(p0+1));
1773 const tcp::resolver::iterator iterator = resolver.resolve(query, ec);
1774
1775 if (ec)
1776 {
1777 T::Out() << kRed << "GetEndpoint - Couldn't resolve endpoint '" << base << "': " << ec.message();
1778 return tcp::endpoint();
1779 }
1780
1781 return *iterator;
1782 }
1783
1784 typedef map<string, FAD::Configuration> Configs;
1785 Configs fConfigs;
1786 Configs::const_iterator fTargetConfig;
1787
1788
1789 template<class V>
1790 bool CheckConfigVal(const Configuration &conf, V max, const string &name, const string &sub)
1791 {
1792 if (!conf.HasDef(name, sub))
1793 {
1794 T::Error("Neither "+name+"default nor "+name+sub+" found.");
1795 return false;
1796 }
1797
1798 const V val = conf.GetDef<V>(name, sub);
1799
1800 if (val<=max)
1801 return true;
1802
1803 ostringstream str;
1804 str << name << sub << "=" << val << " exceeds allowed maximum of " << max << "!";
1805 T::Error(str);
1806
1807 return false;
1808 }
1809
1810 int EvalConfiguration(const Configuration &conf)
1811 {
1812 // ---------- General setup ---------
1813 fIsVerbose = !conf.Get<bool>("quiet");
1814 fIsHexOutput = conf.Get<bool>("hex-out");
1815 fIsDataOutput = conf.Get<bool>("data-out");
1816 fDebugTx = conf.Get<bool>("debug-tx");
1817
1818 // ---------- Setup event builder ---------
1819 SetMaxMemory(conf.Get<unsigned int>("max-mem"));
1820
1821 // ---------- Setup run types ---------
1822 const vector<string> types = conf.Vec<string>("run-type");
1823 if (types.size()==0)
1824 T::Warn("No run-types defined.");
1825 else
1826 T::Message("Defining run-types");
1827 for (vector<string>::const_iterator it=types.begin();
1828 it!=types.end(); it++)
1829 {
1830 T::Message(" -> "+ *it);
1831
1832 if (fConfigs.count(*it)>0)
1833 {
1834 T::Error("Run-type "+*it+" defined twice.");
1835 return 1;
1836 }
1837
1838 FAD::Configuration target;
1839
1840 if (!CheckConfigVal<bool>(conf, true, "enable-drs.", *it) ||
1841 !CheckConfigVal<bool>(conf, true, "enable-dwrite.", *it) ||
1842 !CheckConfigVal<bool>(conf, true, "enable-continous-trigger.", *it))
1843 return 2;
1844
1845 target.fDenable = conf.GetDef<bool>("enable-drs.", *it);
1846 target.fDwrite = conf.GetDef<bool>("enable-dwrite.", *it);
1847 target.fContinousTrigger = conf.GetDef<bool>("enable-continous-trigger.", *it);
1848
1849 target.fTriggerRate = 0;
1850 //if (target.fContinousTrigger)
1851 {
1852 if (!CheckConfigVal<uint16_t>(conf, 0xffff, "trigger-rate.", *it))
1853 return 3;
1854
1855 target.fTriggerRate = conf.GetDef<uint16_t>("trigger-rate.", *it);
1856 }
1857
1858 for (int i=0; i<FAD::kNumChannelsPerChip; i++)
1859 {
1860 ostringstream str;
1861 str << "roi-ch" << i << '.';
1862
1863 if (!CheckConfigVal<uint16_t>(conf, FAD::kMaxRoiValue, "roi.", *it) &&
1864 !CheckConfigVal<uint16_t>(conf, FAD::kMaxRoiValue, str.str(), *it))
1865 return 4;
1866
1867 target.fRoi[i] = conf.HasDef(str.str(), *it) ?
1868 conf.GetDef<uint16_t>(str.str(), *it) :
1869 conf.GetDef<uint16_t>("roi.", *it);
1870 }
1871
1872 for (int i=0; i<FAD::kNumDac; i++)
1873 {
1874 ostringstream str;
1875 str << "dac-" << i << '.';
1876
1877 if (!CheckConfigVal<uint16_t>(conf, FAD::kMaxDacValue, "dac.", *it) &&
1878 !CheckConfigVal<uint16_t>(conf, FAD::kMaxDacValue, str.str(), *it))
1879 return 5;
1880
1881 target.fDac[i] = conf.HasDef(str.str(), *it) ?
1882 conf.GetDef<uint16_t>(str.str(), *it) :
1883 conf.GetDef<uint16_t>("dac.", *it);
1884 }
1885
1886 fConfigs[*it] = target;
1887 }
1888
1889 // FIXME: Add a check about unsused configurations
1890
1891 // ---------- Setup board addresses for fake-fad ---------
1892
1893 if (conf.Has("debug-addr"))
1894 {
1895 const string addr = conf.Get<string>("debug-addr");
1896 const int num = conf.Get<unsigned int>("debug-num");
1897
1898 const tcp::endpoint endpoint = GetEndpoint(addr);
1899 if (endpoint==tcp::endpoint())
1900 return 1;
1901
1902 for (int i=0; i<num; i++)
1903 AddEndpoint(tcp::endpoint(endpoint.address(), endpoint.port()+8*i));
1904
1905 StartConnection();
1906 return -1;
1907 }
1908
1909 // ---------- Setup board addresses for the real camera ---------
1910
1911 if (conf.Has("base-addr"))
1912 {
1913 string base = conf.Get<string>("base-addr");
1914
1915 if (base=="def" || base =="default")
1916 base = "10.0.128.128:31919";
1917
1918 const tcp::endpoint endpoint = GetEndpoint(base);
1919 if (endpoint==tcp::endpoint())
1920 return 10;
1921
1922 const ba::ip::address_v4::bytes_type ip = endpoint.address().to_v4().to_bytes();
1923
1924 if (ip[2]>250 || ip[3]>244)
1925 {
1926 T::Out() << kRed << "EvalConfiguration - IP address given by --base-addr out-of-range." << endl;
1927 return 11;
1928 }
1929
1930 for (int crate=0; crate<4; crate++)
1931 for (int board=0; board<10; board++)
1932 {
1933 ba::ip::address_v4::bytes_type target = endpoint.address().to_v4().to_bytes();
1934 target[2] += crate;
1935 target[3] += board;
1936
1937 AddEndpoint(tcp::endpoint(ba::ip::address_v4(target), endpoint.port()));
1938 }
1939
1940 StartConnection();
1941 return -1;
1942
1943 }
1944
1945 // ---------- Setup board addresses one by one ---------
1946
1947 if (conf.Has("addr"))
1948 {
1949 const vector<string> addrs = conf.Get<vector<string>>("addr");
1950 for (vector<string>::const_iterator i=addrs.begin(); i<addrs.end(); i++)
1951 {
1952 const tcp::endpoint endpoint = GetEndpoint(*i);
1953 if (endpoint==tcp::endpoint())
1954 return 12;
1955
1956 AddEndpoint(endpoint);
1957 }
1958
1959 StartConnection();
1960 return -1;
1961 }
1962
1963 return -1;
1964 }
1965
1966};
1967
1968// ------------------------------------------------------------------------
1969
1970#include "Main.h"
1971
1972/*
1973void RunThread(StateMachineImp *io_service)
1974{
1975 // This is necessary so that the StateMachien Thread can signal the
1976 // Readline to exit
1977 io_service->Run();
1978 Readline::Stop();
1979}
1980*/
1981/*
1982template<class S>
1983int RunDim(Configuration &conf)
1984{
1985 WindowLog wout;
1986
1987 ReadlineColor::PrintBootMsg(wout, conf.GetName(), false);
1988
1989 if (conf.Has("log"))
1990 if (!wout.OpenLogFile(conf.Get<string>("log")))
1991 wout << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl;
1992
1993 // Start io_service.Run to use the StateMachineImp::Run() loop
1994 // Start io_service.run to only use the commandHandler command detaching
1995 StateMachineFAD<S> io_service(wout);
1996 if (!io_service.EvalConfiguration(conf))
1997 return -1;
1998
1999 io_service.Run();
2000
2001 return 0;
2002}
2003*/
2004
2005template<class T, class S>
2006int RunShell(Configuration &conf)
2007{
2008 return Main<T, StateMachineFAD<S>>(conf);
2009/*
2010 static T shell(conf.GetName().c_str(), conf.Get<int>("console")!=1);
2011
2012 WindowLog &win = shell.GetStreamIn();
2013 WindowLog &wout = shell.GetStreamOut();
2014
2015 if (conf.Has("log"))
2016 if (!wout.OpenLogFile(conf.Get<string>("log")))
2017 win << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl;
2018
2019 StateMachineFAD<S> io_service(wout);
2020 if (!io_service.EvalConfiguration(conf))
2021 return -1;
2022
2023 shell.SetReceiver(io_service);
2024
2025 boost::thread t(boost::bind(RunThread, &io_service));
2026 //boost::thread t(boost::bind(&StateMachineFAD<S>::Run, &io_service));
2027
2028 if (conf.Has("cmd"))
2029 {
2030 const vector<string> v = conf.Get<vector<string>>("cmd");
2031 for (vector<string>::const_iterator it=v.begin(); it!=v.end(); it++)
2032 shell.ProcessLine(*it);
2033 }
2034
2035 if (conf.Has("exec"))
2036 {
2037 const vector<string> v = conf.Get<vector<string>>("exec");
2038 for (vector<string>::const_iterator it=v.begin(); it!=v.end(); it++)
2039 shell.Execute(*it);
2040 }
2041
2042 if (conf.Get<bool>("quit"))
2043 shell.Stop();
2044
2045 shell.Run(); // Run the shell
2046 io_service.Stop(); // Signal Loop-thread to stop
2047
2048 // Wait until the StateMachine has finished its thread
2049 // before returning and destroying the dim objects which might
2050 // still be in use.
2051 t.join();
2052
2053 return 0;
2054 */
2055}
2056
2057void SetupConfiguration(Configuration &conf)
2058{
2059 const string n = conf.GetName()+".log";
2060
2061 po::options_description config("Program options");
2062 config.add_options()
2063 ("dns", var<string>("localhost"), "Dim nameserver host name (Overwites DIM_DNS_NODE environment variable)")
2064 ("log,l", var<string>(n), "Write log-file")
2065// ("no-dim,d", po_switch(), "Disable dim services")
2066 ("console,c", var<int>(), "Use console (0=shell, 1=simple buffered, X=simple unbuffered)")
2067 ("cmd", vars<string>(), "Execute one or more commands at startup")
2068 ("exec,e", vars<string>(), "Execute one or more scrips at startup")
2069 ("quit", po_switch(), "Quit after startup");
2070 ;
2071
2072 po::options_description control("FAD control options");
2073 control.add_options()
2074 ("quiet,q", po_bool(), "Disable printing contents of all received messages in clear text.")
2075 ("hex-out", po_bool(), "Enable printing contents of all printed messages also as hex data.")
2076 ("data-out", po_bool(), "Enable printing received event data.")
2077 ("debug-tx", po_bool(), "Enable debugging of ethernet transmission.")
2078 ;
2079
2080 po::options_description connect("FAD connection options");
2081 connect.add_options()
2082 ("addr", vars<string>(), "Network address of FAD")
2083 ("base-addr", var<string>(), "Base address of all FAD")
2084 ("debug-num,n", var<unsigned int>(40), "Sets the number of fake boards to be connected locally")
2085 ("debug-addr", var<string>(), "")
2086 ;
2087
2088 po::options_description builder("Event builder options");
2089 builder.add_options()
2090 ("max-mem,m", var<unsigned int>(100), "Maximum memory the event builder thread is allowed to consume for its event buffer")
2091 ;
2092
2093
2094 po::options_description runtype("Run type configuration");
2095 runtype.add_options()
2096 ("run-type", vars<string>(), "")
2097 ("enable-dwrite.*", var<bool>(), "")
2098 ("enable-drs.*", var<bool>(), "")
2099 ("enable-continous-trigger.*", var<bool>(), "")
2100 ("trigger-rate.*", var<uint16_t>(), "")
2101 ("dac.*", var<uint16_t>(), "")
2102 ("dac-0.*", var<uint16_t>(), "")
2103 ("dac-1.*", var<uint16_t>(), "")
2104 ("dac-2.*", var<uint16_t>(), "")
2105 ("dac-3.*", var<uint16_t>(), "")
2106 ("dac-4.*", var<uint16_t>(), "")
2107 ("dac-5.*", var<uint16_t>(), "")
2108 ("dac-6.*", var<uint16_t>(), "")
2109 ("dac-7.*", var<uint16_t>(), "")
2110 ("roi.*", var<uint16_t>(), "")
2111 ("roi-ch0.*", var<uint16_t>(), "")
2112 ("roi-ch1.*", var<uint16_t>(), "")
2113 ("roi-ch2.*", var<uint16_t>(), "")
2114 ("roi-ch3.*", var<uint16_t>(), "")
2115 ("roi-ch4.*", var<uint16_t>(), "")
2116 ("roi-ch5.*", var<uint16_t>(), "")
2117 ("roi-ch6.*", var<uint16_t>(), "")
2118 ("roi-ch7.*", var<uint16_t>(), "")
2119 ("roi-ch8.*", var<uint16_t>(), "")
2120 ;
2121
2122 conf.AddEnv("dns", "DIM_DNS_NODE");
2123
2124 conf.AddOptions(config);
2125 conf.AddOptions(control);
2126 conf.AddOptions(connect);
2127 conf.AddOptions(builder);
2128 conf.AddOptions(runtype);
2129}
2130
2131void PrintUsage()
2132{
2133 cout <<
2134 "The fadctrl controls the FAD boards.\n"
2135 "\n"
2136 "The default is that the program is started without user intercation. "
2137 "All actions are supposed to arrive as DimCommands. Using the -c "
2138 "option, a local shell can be initialized. With h or help a short "
2139 "help message about the usuage can be brought to the screen.\n"
2140 "\n"
2141 "Usage: fadctrl [-c type] [OPTIONS]\n"
2142 " or: fadctrl [OPTIONS]\n";
2143 cout << endl;
2144}
2145
2146void PrintHelp()
2147{
2148 /* Additional help text which is printed after the configuration
2149 options goes here */
2150}
2151
2152int main(int argc, const char* argv[])
2153{
2154 Configuration conf(argv[0]);
2155 conf.SetPrintUsage(PrintUsage);
2156 SetupConfiguration(conf);
2157
2158 po::variables_map vm;
2159 try
2160 {
2161 vm = conf.Parse(argc, argv);
2162 }
2163#if BOOST_VERSION > 104000
2164 catch (po::multiple_occurrences &e)
2165 {
2166 cerr << "Program options invalid due to: " << e.what() << " of '" << e.get_option_name() << "'." << endl;
2167 return -1;
2168 }
2169#endif
2170 catch (exception& e)
2171 {
2172 cerr << "Program options invalid due to: " << e.what() << endl;
2173 return -1;
2174 }
2175
2176 if (conf.HasVersion() || conf.HasPrint())
2177 return -1;
2178
2179 if (conf.HasHelp())
2180 {
2181 PrintHelp();
2182 return -1;
2183 }
2184
2185 Dim::Setup(conf.Get<string>("dns"));
2186
2187// try
2188 {
2189 // No console access at all
2190 if (!conf.Has("console"))
2191 {
2192// if (conf.Get<bool>("no-dim"))
2193// return RunShell<LocalStream, StateMachine>(conf);
2194// else
2195 return RunShell<LocalStream, StateMachineDim>(conf);
2196 }
2197 // Cosole access w/ and w/o Dim
2198/* if (conf.Get<bool>("no-dim"))
2199 {
2200 if (conf.Get<int>("console")==0)
2201 return RunShell<LocalShell, StateMachine>(conf);
2202 else
2203 return RunShell<LocalConsole, StateMachine>(conf);
2204 }
2205 else
2206*/ {
2207 if (conf.Get<int>("console")==0)
2208 return RunShell<LocalShell, StateMachineDim>(conf);
2209 else
2210 return RunShell<LocalConsole, StateMachineDim>(conf);
2211 }
2212 }
2213/* catch (std::exception& e)
2214 {
2215 cerr << "Exception: " << e.what() << endl;
2216 return -1;
2217 }*/
2218
2219 return 0;
2220}
Note: See TracBrowser for help on using the repository browser.