source: trunk/FACT++/src/fpgaftmctrl.cc@ 20115

Last change on this file since 20115 was 20071, checked in by tbretz, 4 years ago
Allow for different names in fact and famous.
File size: 54.8 KB
Line 
1/* ToDo:
2 * 1) Delay TriggerDataTimer
3 * 2)
4 *
5 *
6 *
7 *
8 *
9 */
10
11#include <boost/array.hpp>
12
13#include <string>
14#include <queue>
15
16#include "FACT.h"
17#include "Dim.h"
18#include "Event.h"
19#include "StateMachineDim.h"
20#include "StateMachineAsio.h"
21#include "Connection.h"
22#include "LocalControl.h"
23#include "Configuration.h"
24#include "Console.h"
25
26#include "tools.h"
27
28#include "HeadersFPGAFTM.h"
29
30namespace ba = boost::asio;
31namespace bs = boost::system;
32namespace dummy = ba::placeholders;
33
34using namespace std;
35
36class ConnectionFPGAFTM : public Connection
37{
38public:
39 static bool fIsFACT;
40
41private:
42 bool fIsVerbose;
43 bool fDebugRx;
44
45 uint32_t fInterval;
46
47 boost::asio::deadline_timer fRxTimeout;
48 boost::asio::deadline_timer fDataTimer;
49
50 vector<uint8_t> fBuffer;
51
52 bool fIsInitializing;
53
54 FPGAFTM::Config fConf;
55 FPGAFTM::Data fData;
56
57 virtual void UpdateConfiguration(const FPGAFTM::Config &)
58 {
59 }
60
61 virtual void UpdateData(uint8_t, const FPGAFTM::Data &)
62 {
63 }
64
65 virtual void UpdateTrigger(uint8_t, const uint64_t &)
66 {
67 }
68
69 queue<FPGAFTM::BusData> fQueue;
70
71 void HandleReadTimeout(const bs::error_code &error)
72 {
73 if (error==ba::error::basic_errors::operation_aborted)
74 return;
75
76 if (error)
77 {
78 ostringstream str;
79 str << "Read timeout: " << error.message() << " (" << error << ")";
80 Error(str);
81
82 PostClose(false);
83 return;
84
85 }
86
87 if (!is_open())
88 {
89 // For example: Here we could schedule a new accept if we
90 // would not want to allow two connections at the same time.
91 return;
92 }
93
94 // Check whether the deadline has passed. We compare the deadline
95 // against the current time since a new asynchronous operation
96 // may have moved the deadline before this actor had a chance
97 // to run.
98 //if (fRxTimeout.expires_at() > ba::deadline_timer::traits_type::now())
99 // return;
100
101 Error("Timeout ("+to_simple_string(fRxTimeout.expires_from_now())+") reading data.");
102 PostClose(false);
103 }
104
105
106 void HandleDataTimer(const bs::error_code &error)
107 {
108 if (error==ba::error::basic_errors::operation_aborted)
109 return;
110
111 if (error)
112 {
113 ostringstream str;
114 str << "Data timer: " << error.message() << " (" << error << ")";
115 Error(str);
116
117 PostClose(false);
118 return;
119
120 }
121
122 if (!is_open())
123 return;
124
125 SendWrite(FPGAFTM::kOnTime);
126 SendRead(FPGAFTM::kRS485Data);
127 SendRead(FPGAFTM::kClockMeasure);
128 SendRead(FPGAFTM::kTimerMeasure);
129 SendRead(FPGAFTM::kADC1);
130
131 TriggerDataTimer();
132 }
133
134
135 void HandleReceivedData(const boost::system::error_code& err, size_t bytes_received, int)
136 {
137 // Do not schedule a new read if the connection failed.
138 if (err)
139 {
140 // 107: Transport endpoint is not connected (bs::error_code(107, bs::system_category))
141 // 125: Operation canceled
142 if (err && err!=ba::error::eof && // Connection closed by remote host
143 err!=ba::error::basic_errors::not_connected && // Connection closed by remote host
144 err!=ba::error::basic_errors::operation_aborted) // Connection closed by us
145 {
146 ostringstream str;
147 str << "Reading from " << URL() << ": " << err.message() << " (" << err << ")";// << endl;
148 Error(str);
149 }
150 PostClose(err!=ba::error::basic_errors::operation_aborted);
151 return;
152 }
153
154 if (bytes_received!=16)
155 {
156 Error(Tools::Form("Number of received bytes (%d) does not match 16", bytes_received));
157 PostClose(false);
158 return;
159 }
160
161 // Keep time of (async) data reception
162 const Time time;
163 bool _ignore = false; //Ignore temperature read errors
164
165 FPGAFTM::BusData &data = *reinterpret_cast<FPGAFTM::BusData*>(fBuffer.data());
166
167 // Print raw message in verbose mode
168 if (fDebugRx)
169 Out() << "RX|" << data << endl;
170
171 // Some sanity checks
172 if (data.fStartBits!=0xffff || data.fStopBits!=0xffff)
173 {
174 Error(Tools::Form("Frame bytes mismatch (%04x|%04x)",
175 data.fStartBits, data.fStopBits));
176 PostClose(false);
177 return;
178 }
179
180 if (!data.isCrcValid())
181 {
182 Error(Tools::Form("Checksum mismatch (Received: %d, Expected: %d)", data.fCrc, data.calcCrc()));
183 PostClose(false);
184 return;
185 }
186
187 if (data.fReadWrite==FPGAFTM::kCmdError)
188 {
189 ostringstream msg;
190 msg << "FPGA returned an error: ";
191 switch (data.fData)
192 {
193 case FPGAFTM::kErrFrameStart: msg << "Start bytes wrong"; break;
194 case FPGAFTM::kErrFrameStop: msg << "Stop bytes wrong"; break;
195 case FPGAFTM::kErrFrameCrc: msg << "Checksum error"; break;
196 case FPGAFTM::kErrUnknownCmd: msg << "Command unknown"; break;
197 case FPGAFTM::kErrForbiddenCmd: msg << "Command not allowed"; break;
198 case FPGAFTM::kErrTempReadCmd: msg << "Temperature read failed"; _ignore = true; break;
199 case FPGAFTM::kErrTempReadBusy: msg << "Temperature read busy"; _ignore = true; break;
200
201 default: msg << "Unknwon error"; break;
202 }
203 msg << Tools::Form(" [%04x]", data.fData);
204
205 if (!_ignore)
206 { Error(msg);
207 PostClose(false);
208 return;
209 }
210
211 Warn(msg);
212 }
213
214 if (fQueue.empty() && data.fReadWrite!=FPGAFTM::kCmdADM)
215 {
216 Error(Tools::Form("Unexpected answer [%02x|%04x] received.", data.fReadWrite, data.fCommand));
217 PostClose(false);
218 return;
219 }
220
221 if (!fQueue.empty() && data.fReadWrite!=FPGAFTM::kCmdADM && fQueue.front().id() != data.id() && !_ignore)
222 {
223 Error(Tools::Form("Command mismatch (Received: %06x, Expected: %06x)", data.id(), fQueue.front().id()));
224 PostClose(false);
225 return;
226 }
227
228 // Requested Message received -> cancel timeout
229 if (!fQueue.empty() && data.fReadWrite!=FPGAFTM::kCmdADM)
230 fRxTimeout.cancel();
231
232 switch (data.fCommand)
233 {
234 case FPGAFTM::kRegProductId:
235 fConf.fProductId = data.fData;
236 UpdateConfiguration(fConf);
237 Info(Tools::Form("Product ID = 0x%x", data.fData));
238 // FIXME: Check for validity
239 break;
240
241 case FPGAFTM::kRegFirmwareId:
242 fConf.fFirmwareId = data.fData;
243 UpdateConfiguration(fConf);
244 Info(Tools::Form("Firmware = 0x%x", data.fData));
245 // FIXME: Check for validity
246 break;
247
248 case FPGAFTM::kClockEnable:
249 fConf.fClockState = data.fCommand>>8;
250 UpdateConfiguration(fConf);
251 Info("Clock enabled.");
252 break;
253
254 case FPGAFTM::kClockDisable:
255 fConf.fClockState = data.fCommand>>8;
256 UpdateConfiguration(fConf);
257 Info("Clock disabled.");
258 break;
259
260 case FPGAFTM::kClockShutdown:
261 fConf.fClockState = data.fCommand>>8;
262 UpdateConfiguration(fConf);
263 Info("Clock shut down.");
264 break;
265
266 case FPGAFTM::kTimerEnable:
267 fConf.fTimerState = data.fCommand>>8;
268 UpdateConfiguration(fConf);
269 Info("TIM timer enabled.");
270 break;
271
272 case FPGAFTM::kTimerDisable:
273 fConf.fTimerState = data.fCommand>>8;
274 UpdateConfiguration(fConf);
275 Info("TIM timer disabled.");
276 break;
277
278 case FPGAFTM::kTimerShutdown:
279 fConf.fTimerState = data.fCommand>>8;
280 UpdateConfiguration(fConf);
281 Info("TIM timer shut down.");
282 break;
283
284 case FPGAFTM::kClockFrequency:
285 {
286 const uint16_t dac = (data.fData>>2) &0x3ff;
287 const uint16_t oct = (data.fData>>12)&0xf;
288
289 const double freq = pow(2, oct)*2078/(2-dac/1024.)/1000;
290
291 fConf.fClockFrequency64 = data.fData;
292 fConf.fClockFrequencyD = freq;
293
294 UpdateConfiguration(fConf);
295
296 Info(Tools::Form("Clock frequency = %.2f kHz [dac=%d; oct=%d]", freq, dac, oct));
297 }
298 break;
299
300 case FPGAFTM::kTimerFrequency:
301 {
302 const uint16_t dac = (data.fData>>2) &0x3ff;
303 const uint16_t oct = (data.fData>>12)&0xf;
304
305 const double freq = pow(2, oct)*2078/(2-dac/1024.)/1000;
306
307 fConf.fTimerFrequency64 = data.fData;
308 fConf.fTimerFrequencyD = freq;
309
310 UpdateConfiguration(fConf);
311
312 Info(Tools::Form("Timer frequency = %.2f kHz [dac=%d; oct=%d]", freq, dac, oct));
313 }
314 break;
315
316 case FPGAFTM::kTriggerInternal:
317 fConf.fTriggerState = data.fCommand>>8;
318 UpdateConfiguration(fConf);
319 Info("Internal trigger turned on ["+to_string(fConf.fTriggerState)+"]");
320 break;
321
322 case FPGAFTM::kTriggerExternal:
323 fConf.fTriggerState = data.fCommand>>8;
324 UpdateConfiguration(fConf);
325 Info("External trigger turned on ["+to_string(fConf.fTriggerState)+"]");
326 break;
327/*
328 case FPGAFTM::kTriggerRandom:
329 fConf.fTriggerState = data.fCommand>>8;
330 UpdateConfiguration(fConf);
331 Info("Random trigger turned on ["+to_string(fConf.fTriggerState)+"]");
332 break;
333*/
334 case FPGAFTM::kTriggerShutdown:
335 fConf.fTriggerState = data.fCommand>>8;
336 UpdateConfiguration(fConf);
337 Info("Trigger turned off ["+to_string(fConf.fTriggerState)+"]");
338 break;
339
340 case FPGAFTM::kTriggerSourceMask:
341 fConf.fTriggerSourceMask = data.fData;
342 UpdateConfiguration(fConf);
343 Info(Tools::Form("Trigger source mask set [%x]", data.fData));
344 break;
345
346 case FPGAFTM::kTriggerOutSourceMask:
347 fConf.fTriggerOutSourceMask = data.fData;
348 UpdateConfiguration(fConf);
349 Info(Tools::Form("Trigger-out source mask set [%x]", data.fData));
350 break;
351/*
352 case FPGAFTM::kTriggerOutputMask:
353 fConf.fTriggerOutputMask = data.fData;
354 UpdateConfiguration(fConf);
355 Info(Tools::Form("Trigger output mask set [%x]", data.fData));
356 break;
357*/
358 case FPGAFTM::kTriggerHoldOff:
359 fConf.fTriggerHoldOff24 = data.fData&0xffffff;
360 UpdateConfiguration(fConf);
361 Info(Tools::Form("Trigger hold off = %d us", fConf.fTriggerHoldOff24));
362 break;
363
364/*
365 case FPGAFTM::kTriggerRS485On:
366 fConf.fRS485OnOff = data.fCommand>>8;
367 UpdateConfiguration(fConf);
368 Info("RS485 communication turned on.");
369 break;
370
371 case FPGAFTM::kTriggerRS485Off:
372 fConf.fRS485OnOff = data.fCommand>>8;
373 UpdateConfiguration(fConf);
374 Info("RS485 communication turned off.");
375 break;
376*/
377 case FPGAFTM::kTriggerPeriod:
378 {
379 const double freq = 1e6/data.fData; // old: 2*4150.
380
381 fConf.fTriggerPeriod32 = data.fData;
382
383 UpdateConfiguration(fConf);
384
385 Info(Tools::Form("Trigger period = %.2f Hz (%d)", freq, data.fData));
386 break;
387 }
388
389 case FPGAFTM::kTriggerDspDelay:
390 fConf.fTriggerDspDelay = data.fData;
391 UpdateConfiguration(fConf);
392 Info(Tools::Form("Trigger dsp delay = %.1f ns (%d)", data.fData*2.5, data.fData));
393 break;
394
395 case FPGAFTM::kTriggerExtDelay:
396 fConf.fTriggerExtDelay = data.fData;
397 UpdateConfiguration(fConf);
398 Info(Tools::Form("Trigger ext delay = %.1f ns (%d)", data.fData*2.5, data.fData));
399 break;
400
401 case FPGAFTM::kTriggerOutDelay:
402 fConf.fTriggerOutDelay = data.fData;
403 UpdateConfiguration(fConf);
404 Info(Tools::Form("Trigger out delay = %.1f ns (%d)", data.fData*2.5, data.fData));
405 break;
406 case FPGAFTM::kTriggerInhibitState:
407 // Looks like the current state of the line rather than the state is returned
408 fConf.fTriggerInhibitState = data.fData;
409 UpdateConfiguration(fConf);
410 Info(Tools::Form("Trigger inhibit state = %d ", data.fData));
411 break;
412
413 case FPGAFTM::kTriggerInhibitEnable:
414 //fConf.fTriggerInhibitState = data.fData;
415 //UpdateConfiguration(fConf);
416 // The value returned is always 0
417 Info(Tools::Form("INH_HACK! Trigger inhibit state = %d ", data.fData));
418 break;
419
420 case FPGAFTM::kTriggerInhibitTime:
421 fConf.fTriggerInhibitTime = data.fData;
422 UpdateConfiguration(fConf);
423 Info(Tools::Form("Trigger inhibit time = %.1f ns (%d)", data.fData*5.0, data.fData));
424 break;
425 case FPGAFTM::kFadResetLo:
426 case FPGAFTM::kFadResetHi:
427 Info("FAD reset signal="+to_string(data.fCommand));
428 break;
429
430 case FPGAFTM::kSingleTrigger:
431 Info("Single trigger.");
432 break;
433
434 case FPGAFTM::kOnTime:
435 {
436 const uint32_t total = data.fData>>32; // 10ns
437 const uint32_t dead = data.fData; // 10ns
438
439 fData.fRunTime = total;
440 fData.fDeadTime = dead;
441
442 UpdateData(0, fData);
443
444 if (fIsVerbose || fIsInitializing)
445 Info(Tools::Form("Dead time counter: Total=%.2fus Veto=%.2fus (%.1f%%)", total*0.01, dead*0.01, 100.*dead/total));
446 //fDimConf.set(PSU::kBitADM, data[0]);
447 //UpdateConfig(time, data.id(), fDimConf);
448 }
449 break;
450
451 case FPGAFTM::kRS485Data:
452 fData.fTriggerCounter = data.fData;
453 UpdateData(1, fData);
454 if (fIsVerbose || fIsInitializing)
455 Info(Tools::Form("RS485 data = %016lx", data.fData));
456 break;
457
458 case FPGAFTM::kClockMeasure:
459 fData.fClockFrequency = data.fData;
460 UpdateData(2, fData);
461 if (fIsVerbose || fIsInitializing)
462 Info(Tools::Form("Measured clock frequency = %d Hz", data.fData));
463 break;
464
465 case FPGAFTM::kTimerMeasure:
466 fData.fTimerFrequency = data.fData;
467 UpdateData(3, fData);
468 if (fIsVerbose || fIsInitializing)
469 Info(Tools::Form("Measured timer frequency = %d Hz", data.fData));
470 break;
471
472 case FPGAFTM::kADC1:
473 fData.SetADC1(data.fData);
474 UpdateData(4, fData);
475 if (fIsVerbose || fIsInitializing)
476 Info(Tools::Form("ADC1 = %.1f degC (%04x)", fData.fTemp1, fData.fADC1));
477 break;
478
479 default:
480 if(!_ignore)
481 {
482 Error(Tools::Form("Unknown command byte received (%d)", data.fCommand));
483 PostClose(false);
484 return;
485 }
486 else
487 {
488 break;
489 }
490 }
491
492 // Start reading of next package
493 AsyncRead(ba::buffer(fBuffer));
494
495 // If this was an automatic package no further handling should be done
496 if (data.fReadWrite==FPGAFTM::kCmdADM)
497 return;
498
499 // Remove the request for which we just processed the answer from
500 // the queue. This could have a check for an empty queue, but an
501 // empty queue here should never happen!
502 fQueue.pop();
503
504 // If this is the answer to the last sent initialization request
505 // Initialization is done
506 if (fQueue.empty() && fIsInitializing)
507 {
508 PrintConfig();
509 fIsInitializing = false;
510 StartDataTimer();
511 return;
512 }
513
514 // send next request if queue not empty
515 PostCommandFromQueue();
516 }
517
518 void PostCommandFromQueue()
519 {
520 if (fQueue.empty())
521 return;
522
523 const FPGAFTM::BusData &dat = fQueue.front();
524
525 PostMessage(&dat, sizeof(dat));
526 if (GetDebugTx())
527 Out() << "TX|" << dat << endl;
528
529 AsyncWait(fRxTimeout, 1000, &Connection::HandleReadTimeout);
530 }
531
532public:
533 void SendCommand(uint8_t rw, uint16_t cmd, uint64_t d0=0)
534 {
535 fQueue.emplace(rw, cmd, d0);
536 if (fQueue.size()==1)
537 PostCommandFromQueue();
538 }
539
540 void SendWrite(uint16_t cmd, uint64_t val=0)
541 {
542 SendCommand(FPGAFTM::kCmdWrite, cmd, val);
543 }
544
545 void SendRead(uint16_t cmd, uint64_t val=0)
546 {
547 SendCommand(FPGAFTM::kCmdRead, cmd, val);
548 }
549
550 // This is called when a connection was established
551 void ConnectionEstablished()
552 {
553 Info("Connection established to "+URL()+"...");
554
555 fQueue = queue<FPGAFTM::BusData>();
556
557 SendRead(FPGAFTM::kRegProductId);
558 SendRead(FPGAFTM::kRegFirmwareId);
559// SendRead(FPGAFTM::kRegError);
560
561 SendRead(FPGAFTM::kClockFrequency);
562 SendRead(FPGAFTM::kClockMeasure);
563
564 SendWrite(FPGAFTM::kClockEnable);
565// SendRead(FPGAFTM::kClockFrequency);
566
567// SendRead(FPGAFTM::kTimerState);
568 SendRead(FPGAFTM::kTimerFrequency);
569// SendRead(FPGAFTM::kTimerMeasure);
570
571 // The default is to report 'enabled' but no frequency is shown
572 SendRead(FPGAFTM::kTimerShutdown);
573
574 SendWrite(FPGAFTM::kTriggerSourceMask);
575 SendWrite(FPGAFTM::kTriggerOutSourceMask);
576 //SendWrite(FPGAFTM::kTriggerOutputMask);
577 SendWrite(FPGAFTM::kTriggerHoldOff);
578 SendWrite(FPGAFTM::kTriggerDspDelay);
579 SendWrite(FPGAFTM::kTriggerExtDelay);
580 SendWrite(FPGAFTM::kTriggerOutDelay);
581 SendWrite(FPGAFTM::kTriggerShutdown);
582 SendRead(FPGAFTM::kTriggerPeriod);
583
584 fIsInitializing = true;
585 AsyncRead(ba::buffer(fBuffer));
586
587 }
588
589public:
590 ConnectionFPGAFTM(ba::io_service& ioservice, MessageImp &imp) : Connection(ioservice, imp()),
591 fIsVerbose(true), fDebugRx(false),
592 fRxTimeout(ioservice), fDataTimer(ioservice),
593 fBuffer(16), fIsInitializing(false)
594 {
595 SetLogStream(&imp);
596 }
597
598 void SetVerbose(bool b)
599 {
600 fIsVerbose = b;
601 }
602
603 void SetDebugRx(bool b)
604 {
605 fDebugRx = b;
606 Connection::SetVerbose(b);
607 }
608
609 void SetDebugTx(bool b)
610 {
611 Connection::SetDebugTx(b);
612 }
613
614 int GetState() const
615 {
616 if (!IsConnected())
617 return FPGAFTM::State::kDisconnected;
618
619 if (fIsInitializing)
620 return FPGAFTM::State::kConnected;
621
622 return FPGAFTM::State::kValid;
623 }
624
625 size_t GetQueueSize() const
626 {
627 return fQueue.size();
628 }
629
630 uint8_t GetTriggerState() const
631 {
632 return fConf.fTriggerState;
633 }
634
635 uint8_t IsTriggerOn() const
636 {
637 return fConf.fTriggerState!=FPGAFTM::kShutdown;
638 }
639
640 int PrintConfig()
641 {
642 Out() << fConf;
643 return StateMachineImp::kSM_KeepState;
644 }
645
646 int PrintDynamicData()
647 {
648 Out() << fData;
649 return StateMachineImp::kSM_KeepState;
650 }
651
652 void TriggerDataTimer()
653 {
654 if (fInterval==0)
655 return;
656
657 fDataTimer.expires_at(fDataTimer.expires_at()+boost::posix_time::milliseconds(fInterval));
658 fDataTimer.async_wait(boost::bind(&ConnectionFPGAFTM::HandleDataTimer, this, dummy::error));
659 }
660
661 void StartDataTimer()
662 {
663 fDataTimer.cancel();
664 if (fInterval>0 && IsConnected() && !fIsInitializing)
665 {
666 SendWrite(FPGAFTM::kOnTime);
667 fDataTimer.expires_at(Time()+boost::posix_time::milliseconds(fInterval));
668 fDataTimer.async_wait(boost::bind(&ConnectionFPGAFTM::HandleDataTimer, this, dummy::error));
669 }
670 }
671
672 void SetInterval(uint32_t i=0)
673 {
674 fInterval = i;
675 StartDataTimer();
676 }
677};
678
679bool ConnectionFPGAFTM::fIsFACT = true;
680
681// ------------------------------------------------------------------------
682
683#include "DimDescriptionService.h"
684
685class ConnectionDimFPGAFTM : public ConnectionFPGAFTM
686{
687private:
688 DimDescribedService fDimConfig;
689 DimDescribedService fDimData;
690
691public:
692 ConnectionDimFPGAFTM(ba::io_service& ioservice, MessageImp &imp) :
693 ConnectionFPGAFTM(ioservice, imp),
694 fDimConfig(fIsFACT?"FPGAFTM_CONTROL/CONFIGURATION":"FTM_CONTROL/CONFIGURATION",
695 "X:1;X:1;C:1;X:1;D:1;C:1;X:1;D:1;C:1;C:1;C:1;S:1;S:1;S:1;I:1;I:1;C:1;S:1",
696 "|firmware[uint64]:Firmware ID"
697 "|product[uint64]:Product ID"
698 "|clk_state[uint8]:Clock state"
699 "|clk_freq_raw[uint64]:Clock frequency (raw)"
700 "|clk_freq[Hz]:Clock frequency"
701 "|tim_state[uint8]:Timer state"
702 "|tim_freq_raw[uint64]:Timer frequency (raw)"
703 "|tim_freq[Hz]:Timer frequency"
704 "|trg_mode[uint8]:Trigger Mode"
705 "|trg_mask[uint8]:Trigger Source-Mask"
706 "|trg_out_mask[uint8]:Trigger Out Source-Mask"
707 "|trg_delay_dsp[2.5ns]:Trigger Delay DSP"
708 "|trg_delay_ext[2.5ns]:Trigger Delay EXT"
709 "|trg_delay_out[2.5ns]:Trigger Delay OUT"
710 "|trg_period[uint32]:Trigger Period"
711 "|trg_hold_off[uint24]:Trigger Hold Off"
712 "|trg_inhibit_state[uint8]:"
713 "|trg_inhibit_time[5ns]:"),
714 fDimData(fIsFACT?"FPGAFTM_CONTROL/DATA":"FTM_CONTROL/DATA", "I:1;I:1;I:1;I:1;I:1;S:1;F:1",
715 "|run_time[10ns]:Absolute Run Time"
716 "|dead_time[10ns]:Measured Dead Time"
717 "|trg_counter[uint32]:Trigger counter"
718 "|clk_freq[Hz]:Clock frequency measured"
719 "|tim_freq[Hz]:Timer frequency measured"
720 "|adc[uint10]:ADC value (raw)"
721 "|temp[degC]:Temperature corresponding to ADC value")
722 {
723 }
724
725 void UpdateConfiguration(const FPGAFTM::Config &conf)
726 {
727 //fDim.setQuality(status.GetVal());
728 fDimConfig.setData(conf);
729 fDimConfig.Update();
730 }
731
732 void UpdateData(uint8_t qos, const FPGAFTM::Data &data)
733 {
734 fDimData.setQuality(qos);
735 fDimData.setData(data);
736 fDimData.Update();
737 }
738};
739
740// ------------------------------------------------------------------------
741
742template <class T, class S>
743class StateMachineFPGAFTM : public StateMachineAsio<T>
744{
745private:
746 S fFTM;
747 Time fLastCommand;
748
749 bool CheckEventSize(size_t has, const char *name, size_t size)
750 {
751 if (has==size)
752 return true;
753
754 ostringstream msg;
755 msg << name << " - Received event has " << has << " bytes, but expected " << size << ".";
756 T::Fatal(msg);
757 return false;
758 }
759
760 int SetVerbosity(const EventImp &evt)
761 {
762 if (!CheckEventSize(evt.GetSize(), "SetVerbosity", 1))
763 return T::kSM_FatalError;
764
765 fFTM.SetVerbose(evt.GetBool());
766
767 return T::GetCurrentState();
768 }
769
770 int SetDebugRx(const EventImp &evt)
771 {
772 if (!CheckEventSize(evt.GetSize(), "SetDebugRx", 1))
773 return T::kSM_FatalError;
774
775 fFTM.SetDebugRx(evt.GetBool());
776
777 return T::GetCurrentState();
778 }
779
780 int SetDebugTx(const EventImp &evt)
781 {
782 if (!CheckEventSize(evt.GetSize(), "SetDebugTx", 1))
783 return T::kSM_FatalError;
784
785 fFTM.SetDebugTx(evt.GetBool());
786
787 return T::GetCurrentState();
788 }
789
790 int Disconnect()
791 {
792 // Close all connections
793 fFTM.PostClose(false);
794
795 /*
796 // Now wait until all connection have been closed and
797 // all pending handlers have been processed
798 poll();
799 */
800
801 return T::GetCurrentState();
802 }
803
804 int Reconnect(const EventImp &evt)
805 {
806 // Close all connections to supress the warning in SetEndpoint
807 fFTM.PostClose(false);
808
809 // Now wait until all connection have been closed and
810 // all pending handlers have been processed
811 ba::io_service::poll();
812
813 if (evt.GetBool())
814 fFTM.SetEndpoint(evt.GetString());
815
816 // Now we can reopen the connection
817 fFTM.PostClose(true);
818
819 return T::GetCurrentState();
820 }
821
822 uint16_t fTriggerMode; // Kommand to be sent to turn the trigger on
823
824 int Configure(const EventImp &evt)
825 {
826 const string name = evt.GetText();
827
828 auto it = fRunTypes.find(name);
829 if (it==fRunTypes.end())
830 {
831 T::Info("Configure - Run-type '"+name+"' not found... trying 'default'.");
832
833 it = fRunTypes.find("default");
834 if (it==fRunTypes.end())
835 {
836 T::Error("Configure - Run-type 'default' not found.");
837 return T::GetCurrentState();
838 }
839 }
840
841 Dim::SendCommand("FTU_CONTROL/ENABLE_PRESCALING", uint8_t(0));
842
843 fFTM.SendWrite(FPGAFTM::kTriggerShutdown);
844 //fFTM.SendWrite(FPGAFTM::kTriggerRS485On);
845 fFTM.SendWrite(FPGAFTM::kTriggerPeriod, it->second.fTriggerPeriod);
846 fFTM.SendWrite(FPGAFTM::kTriggerSourceMask, it->second.fTriggerSourceMask);
847 fFTM.SendWrite(FPGAFTM::kTriggerOutSourceMask, it->second.fTriggerOutSourceMask);
848 fFTM.SendWrite(FPGAFTM::kTriggerDspDelay, it->second.fTriggerDspDelay);
849 fFTM.SendWrite(FPGAFTM::kTriggerExtDelay, it->second.fTriggerExtDelay);
850 fFTM.SendWrite(FPGAFTM::kTriggerOutDelay, it->second.fTriggerOutDelay);
851 fFTM.SendWrite(FPGAFTM::kTriggerHoldOff, it->second.fTriggerHoldOff);
852 //fFTM.SendWrite(FPGAFTM::kRS485Data);
853
854 fTriggerMode = FPGAFTM::kTriggerShutdown;
855 if (it->second.fTriggerType=="internal")
856 fTriggerMode = FPGAFTM::kTriggerInternal;
857 if (it->second.fTriggerType=="external")
858 fTriggerMode = FPGAFTM::kTriggerExternal;
859 //if (it->second.fTriggerType=="random")
860 // fTriggerMode = FPGAFTM::kTriggerRandom;
861
862 return FPGAFTM::State::kConfiguring;
863 }
864
865 int ResetConfig()
866 {
867 return fFTM.GetState();
868 }
869
870 int StartTrigger()
871 {
872 fFTM.StartDataTimer();
873 fFTM.SendWrite(fTriggerMode);
874 return T::GetCurrentState();//FPGAFTM::State::kTriggerOn;
875 }
876
877 int ReadRegister(uint16_t cmd)
878 {
879 fFTM.SendRead(cmd);
880
881 return T::GetCurrentState();
882 }
883
884 int WriteRegister(uint16_t cmd)
885 {
886 fFTM.SendWrite(cmd);
887
888 return T::GetCurrentState();
889 }
890
891 int ReadReg(const EventImp &evt)
892 {
893 if (!CheckEventSize(evt.GetSize(), "Read", 2))
894 return T::kSM_FatalError;
895
896 fFTM.SendRead(evt.GetUShort());
897
898 return T::GetCurrentState();
899 }
900
901 int WriteReg(const EventImp &evt)
902 {
903 if (!CheckEventSize(evt.GetSize(), "Write", 10))
904 return T::kSM_FatalError;
905
906 fFTM.SendWrite(evt.GetUShort(), evt.Get<uint64_t>(2));
907
908 return T::GetCurrentState();
909 }
910
911 int WriteRegister64(const EventImp &evt, uint16_t cmd)
912 {
913 if (!CheckEventSize(evt.GetSize(), "WriteRegister64", 8))
914 return T::kSM_FatalError;
915
916 fFTM.SendWrite(cmd, evt.Get<uint64_t>());
917
918 return T::GetCurrentState();
919 }
920
921 int ShutdownTrigger(const EventImp &evt)
922 {
923 if (!CheckEventSize(evt.GetSize(), "ShutdownTrigger", 1))
924 return T::kSM_FatalError;
925
926 fFTM.SendWrite(FPGAFTM::kTriggerShutdown, evt.GetBool());
927
928 return T::GetCurrentState();
929 }
930
931 int SetFADReset(const EventImp &evt)
932 {
933 if (!CheckEventSize(evt.GetSize(), "SetFADReset", 1))
934 return T::kSM_FatalError;
935
936 fFTM.SendWrite(evt.GetBool() ? FPGAFTM::kFadResetHi : FPGAFTM::kFadResetLo);
937
938 return T::GetCurrentState();
939 }
940
941 int SendFADReset(const EventImp &evt)
942 {
943 if (!CheckEventSize(evt.GetSize(), "SendFADReset", 0))
944 return T::kSM_FatalError;
945
946 fFTM.SendWrite(FPGAFTM::kFadResetHi);
947 fFTM.SendWrite(FPGAFTM::kFadResetLo);
948
949 return T::GetCurrentState();
950 }
951
952 int SetClockFrequency(const EventImp &evt)
953 {
954 if (!CheckEventSize(evt.GetSize(), "SetClockFrequency", 4))
955 return T::kSM_FatalError;
956
957 const uint16_t m = evt.Get<uint16_t>(0);
958 const uint16_t e = evt.Get<uint16_t>(2);
959
960 if (m>0x3ff)
961 {
962 T::Warn("Clock frequency matinsse exceeds allowed range (10 bit)... ignored.");
963 return T::GetCurrentState();
964 }
965
966 if (e>0xf)
967 {
968 T::Warn("Clock frequency exponent exceeds allowed range (4 bit)... ignored.");
969 return T::GetCurrentState();
970 }
971
972 fFTM.SendWrite(FPGAFTM::kClockFrequency, (e<<12)|(m<<2));
973
974 return T::GetCurrentState();
975 }
976
977 int SetTimerFrequency(const EventImp &evt)
978 {
979 if (!CheckEventSize(evt.GetSize(), "SetTimerFrequency", 4))
980 return T::kSM_FatalError;
981
982 const uint16_t m = evt.Get<uint16_t>(0);
983 const uint16_t e = evt.Get<uint16_t>(2);
984
985 if (m>0x3ff)
986 {
987 T::Warn("Timer frequency matinsse exceeds allowed range (10 bit)... ignored.");
988 return T::GetCurrentState();
989 }
990
991 if (e>0xf)
992 {
993 T::Warn("Timer frequency exponent exceeds allowed range (4 bit)... ignored.");
994 return T::GetCurrentState();
995 }
996
997 fFTM.SendWrite(FPGAFTM::kTimerFrequency, (e<<12)|(m<<2));
998
999 return T::GetCurrentState();
1000 }
1001
1002 int SetTriggerPeriod(const EventImp &evt)
1003 {
1004 if (!CheckEventSize(evt.GetSize(), "SetTriggerPeriod", 8))
1005 return T::kSM_FatalError;
1006
1007 if (evt.GetXtra()<0 || evt.GetXtra()>0xffffffff)
1008 {
1009 T::Warn("Trigger period out of range (32bit)... ignored.");
1010 return T::GetCurrentState();
1011 }
1012
1013 fFTM.SendWrite(FPGAFTM::kTriggerPeriod, evt.GetUInt());
1014
1015 return T::GetCurrentState();
1016 }
1017
1018 int SetTriggerHoldOff(const EventImp &evt)
1019 {
1020 if (!CheckEventSize(evt.GetSize(), "SetTriggerHoldOff", 4))
1021 return T::kSM_FatalError;
1022
1023 if (evt.GetInt()<0 || evt.GetInt()>0xffffff)
1024 {
1025 T::Warn("Trigger hold off out of range (24bit)... ignored.");
1026 return T::GetCurrentState();
1027 }
1028
1029 fFTM.SendWrite(FPGAFTM::kTriggerHoldOff, evt.GetUInt());
1030
1031 return T::GetCurrentState();
1032 }
1033/*
1034 int SetRS485Mode(const EventImp &evt)
1035 {
1036 if (!CheckEventSize(evt.GetSize(), "SetRS485Mode", 8))
1037 return T::kSM_FatalError;
1038
1039 const uint8_t *ptr = evt.Ptr<uint8_t>();
1040
1041 uint64_t data = 0;
1042 data |= uint64_t(ptr[0])<<40; // baud (word2)
1043 data |= uint64_t(ptr[1])<<32; // baud (word2)
1044 data |= uint64_t(ptr[2])<<24; // baud (word3)
1045 data |= uint64_t(ptr[3])<<16; // baud (word3)
1046 data |= uint64_t(ptr[4]&1)<<(40+15); // PEN
1047 data |= uint64_t(ptr[5]&1)<<(40+14); // PAR
1048 data |= uint64_t(ptr[6]&1)<<(40+13); // SPB
1049 data |= uint64_t(ptr[7]&1)<<(40+11); // MSB
1050
1051 fFTM.SendWrite(FPGAFTM::kRS485Mode, data);
1052
1053 return T::GetCurrentState();
1054 }
1055*/
1056 int SetInterval(const EventImp &evt)
1057 {
1058 if (!CheckEventSize(evt.GetSize(), "SetInterval", 8))
1059 return T::kSM_FatalError;
1060
1061 if (evt.GetUXtra()>0xffffffff)
1062 {
1063 T::Warn("Interval out of allowed range [32 bit]... ignored.");
1064 return T::GetCurrentState();
1065 }
1066
1067 fFTM.SetInterval(evt.GetUXtra());
1068
1069 return T::GetCurrentState();
1070 }
1071
1072 int Execute()
1073 {
1074 if (fFTM.GetState()<FPGAFTM::State::kValid)
1075 return fFTM.GetState();
1076
1077 switch (T::GetCurrentState())
1078 {
1079 case FPGAFTM::State::kConfiguring:
1080 return fFTM.GetQueueSize()==0 ? FPGAFTM::State::kConfigured : FPGAFTM::State::kConfiguring;
1081
1082 case FPGAFTM::State::kConfigured:
1083 return fFTM.IsTriggerOn() ? FPGAFTM::State::kTriggerOn : FPGAFTM::State::kConfigured;
1084
1085 case FPGAFTM::State::kTriggerOn:
1086 return fFTM.IsTriggerOn() ? FPGAFTM::State::kTriggerOn : FPGAFTM::State::kValid;
1087 }
1088
1089 return fFTM.GetState();
1090 }
1091
1092public:
1093 StateMachineFPGAFTM(ostream &out=cout) :
1094 StateMachineAsio<T>(out, ConnectionFPGAFTM::fIsFACT?"FPGAFTM_CONTROL":"FTM_CONTROL"),
1095 fFTM(*this, *this)
1096 {
1097 // State names
1098 T::AddStateName(FPGAFTM::State::kDisconnected, "Disconnected",
1099 "No ethernet connection established");
1100
1101 T::AddStateName(FPGAFTM::State::kConnected, "Connected",
1102 "Connection established, requesting configuration");
1103
1104 T::AddStateName(FPGAFTM::State::kValid, "Valid",
1105 "Connection established, valid configuration received");
1106
1107 T::AddStateName(FPGAFTM::State::kConfiguring, "Configuring",
1108 "Configuring FTM for data taking");
1109
1110 T::AddStateName(FPGAFTM::State::kConfigured, "Configured",
1111 "Ready for data taking, ready to enable trigger");
1112
1113 T::AddStateName(FPGAFTM::State::kTriggerOn, "TriggerOn",
1114 "Trigger enabled");
1115
1116
1117 // Verbosity commands
1118 T::AddEvent("SET_VERBOSE", "B:1")
1119 (bind(&StateMachineFPGAFTM::SetVerbosity, this, placeholders::_1))
1120 ("Set verbosity state"
1121 "|verbosity[bool]:disable or enable verbosity for interpreted data (yes/no)");
1122
1123 T::AddEvent("SET_DEBUG_RX", "B:1")
1124 (bind(&StateMachineFPGAFTM::SetDebugRx, this, placeholders::_1))
1125 ("Set debux-rx state"
1126 "|debug[bool]:dump received message to console (yes/no)");
1127
1128 T::AddEvent("SET_DEBUG_TX", "B:1")
1129 (bind(&StateMachineFPGAFTM::SetDebugTx, this, placeholders::_1))
1130 ("Set debux-tx state"
1131 "|debug[bool]:dump outgoing message to console (yes/no)");
1132
1133 T::AddEvent("READ", "S:1", FPGAFTM::State::kValid)
1134 (bind(&StateMachineFPGAFTM::ReadReg, this, placeholders::_1))
1135 ("Read a register"
1136 "|id[uint16]:Register ID");
1137
1138 T::AddEvent("WRITE", "S:1;X:1", FPGAFTM::State::kValid)
1139 (bind(&StateMachineFPGAFTM::WriteReg, this, placeholders::_1))
1140 ("Write a register"
1141 "|id[uint16]:Register ID"
1142 "|val[uint64]:Data value");
1143
1144 // Device control
1145 T::AddEvent("READ_PRODUCT_ID", FPGAFTM::State::kValid)
1146 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kRegProductId))
1147 ("Read product identification");
1148
1149 T::AddEvent("READ_FIRMWARE_ID", FPGAFTM::State::kValid)
1150 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kRegFirmwareId))
1151 ("Read firmware version");
1152
1153 T::AddEvent("READ_CLOCK_STATE", FPGAFTM::State::kValid)
1154 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kClockState))
1155 ("Read clock state");
1156
1157 T::AddEvent("READ_TIMER_STATE", FPGAFTM::State::kValid)
1158 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kTimerState))
1159 ("Read timer state");
1160
1161 T::AddEvent("READ_CLOCK_FREQUENCY", FPGAFTM::State::kValid)
1162 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kClockFrequency))
1163 ("Read comment clock frequency");
1164
1165 T::AddEvent("READ_CLOCK_MEASURE", FPGAFTM::State::kValid)
1166 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kClockMeasure))
1167 ("Read measured clock frequency");
1168
1169 T::AddEvent("READ_TIMER_FREQUENCY", FPGAFTM::State::kValid)
1170 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kTimerFrequency))
1171 ("Read comment timer frequency");
1172
1173 T::AddEvent("READ_TIMER_MEASURE", FPGAFTM::State::kValid)
1174 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kTimerMeasure))
1175 ("Read measured timer frequency");
1176
1177 //T::AddEvent("READ_TRIGGER_MODE", FPGAFTM::State::kValid)
1178 // (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kTriggerState))
1179 // ("Read trigger mode");
1180
1181 T::AddEvent("READ_TRIGGER_PERIOD", FPGAFTM::State::kValid)
1182 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kTriggerPeriod))
1183 ("Read trigger period");
1184/*
1185 T::AddEvent("READ_CONFIGURATION", FPGAFTM::State::kValid)
1186 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kConfiguration))
1187 ("Read some configuration bits");
1188*/
1189 T::AddEvent("SET_FAD_RESET", "B:1", FPGAFTM::State::kValid)
1190 (bind(&StateMachineFPGAFTM::SetFADReset, this, placeholders::_1))
1191 ("Set the FAD reset line to the provided logic signal"
1192 "|hilo[bool]:Set hi or lo state");
1193
1194 T::AddEvent("FAD_RESET", FPGAFTM::State::kValid)
1195 (bind(&StateMachineFPGAFTM::SendFADReset, this, placeholders::_1))
1196 ("Emit both, an up and down of the FAD reset line");
1197
1198 T::AddEvent("READ_ADC1", FPGAFTM::State::kValid)
1199 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kADC1))
1200 ("Read ADC1 (Temp1)");
1201/*
1202 T::AddEvent("READ_ADC2", FPGAFTM::State::kValid)
1203 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kADC2))
1204 ("Read ADC2 (Temp2)");
1205
1206 T::AddEvent("READ_TEMPERATURES", FPGAFTM::State::kValid)
1207 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kADCs))
1208 ("Read both temperatures (ADCs)");
1209
1210
1211 T::AddEvent("READ_FAD_RESET_CYCLES", FPGAFTM::State::kValid)
1212 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kFadResetCycles))
1213 ("Read number of cycles of FAD reset");
1214
1215 T::AddEvent("READ_FAD_RESET_ACTIVE_HI", FPGAFTM::State::kValid)
1216 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kFadResetActiveHi))
1217 ("Set when FAD reset is active hi");
1218*/
1219
1220
1221 T::AddEvent("SET_CLOCK_FREQUENCY", "S:1;S:1", FPGAFTM::State::kValid)
1222 (bind(&StateMachineFPGAFTM::SetClockFrequency, this, placeholders::_1))
1223 ("Set clock frequency 2^oct*2078Hz/(2-dac/1024)"
1224 "|dac[uint16]:Value DAC (10 bit)"
1225 "|oct[uint16]:Value OCT (4 bit)");
1226
1227 T::AddEvent("SET_TIMER_FREQUENCY", "S:1;S:1", FPGAFTM::State::kValid)
1228 (bind(&StateMachineFPGAFTM::SetTimerFrequency, this, placeholders::_1))
1229 ("Set timer (TIM) frequency 2^oct*2078Hz/(2-dac/1024)"
1230 "|dac[uint16]:Value DAC (10 bit)"
1231 "|oct[uint16]:Value OCT (4 bit)");
1232
1233 T::AddEvent("SET_TRIGGER_PERIOD", "X:1", FPGAFTM::State::kValid)
1234 (bind(&StateMachineFPGAFTM::SetTriggerPeriod, this, placeholders::_1))
1235 ("Set trigger period"
1236 "|period[us]:Trigger frequency (32 bit)");
1237
1238 T::AddEvent("SET_TRIGGER_HOLDOFF", "I:1", FPGAFTM::State::kValid)
1239 (bind(&StateMachineFPGAFTM::SetTriggerHoldOff, this, placeholders::_1))
1240 ("Set trigger hold off period"
1241 "|period[us]:Trigger hold off (24 bit)");
1242
1243
1244
1245 T::AddEvent("ENABLE_CLOCK", FPGAFTM::State::kValid)
1246 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kClockEnable))
1247 ("Enable clock");
1248
1249 T::AddEvent("DISABLE_CLOCK", FPGAFTM::State::kValid)
1250 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kClockDisable))
1251 ("Disable clock");
1252
1253 T::AddEvent("SHUTDOWN_CLOCK", FPGAFTM::State::kValid)
1254 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kClockShutdown))
1255 ("Shutdown clock");
1256
1257
1258 T::AddEvent("ENABLE_TIMER", FPGAFTM::State::kValid)
1259 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kTimerEnable))
1260 ("Enable timer");
1261
1262 T::AddEvent("DISABLE_TIMER", FPGAFTM::State::kValid)
1263 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kTimerDisable))
1264 ("Disable timer");
1265
1266 T::AddEvent("SHUTDOWN_TIMER", FPGAFTM::State::kValid)
1267 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kTimerShutdown))
1268 ("Shutdown timer");
1269
1270
1271 T::AddEvent("ENABLE_INTERNAL_TRIGGER", FPGAFTM::State::kValid)
1272 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kTriggerInternal))
1273 ("Enable internal trigger");
1274
1275 T::AddEvent("ENABLE_EXTERNAL_TRIGGER", FPGAFTM::State::kValid)
1276 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kTriggerExternal))
1277 ("Enable external trigger");
1278/*
1279 T::AddEvent("ENABLE_RANDOM_TRIGGER", FPGAFTM::State::kValid)
1280 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kTriggerRandom))
1281 ("Enable random trigger");
1282*/
1283 T::AddEvent("SHUTDOWN_TRIGGER", "B:1", FPGAFTM::State::kValid)
1284 (bind(&StateMachineFPGAFTM::ShutdownTrigger, this, placeholders::_1))
1285 ("Shutdown trigger"
1286 "|hilo[bool]:Set hi or lo state after shutdown");
1287
1288 T::AddEvent("SET_TRIGGER_SOURCE_MASK", "X:1", FPGAFTM::State::kValid)
1289 (bind(&StateMachineFPGAFTM::WriteRegister64, this, placeholders::_1, FPGAFTM::kTriggerSourceMask))
1290 ("Trigger Source Mask (128=SINGLE, 64=BUTTON, 32=FIXRATE, 16=DSP_IN_delay, 8=EXT_IN_delay, 4=DSP_IN, 2=EXT_IN, 1=NOT_USED)"
1291 "|mask[uint8]:");
1292
1293 T::AddEvent("SET_TRIGGER_OUT_SOURCE_MASK", "X:1", FPGAFTM::State::kValid)
1294 (bind(&StateMachineFPGAFTM::WriteRegister64, this, placeholders::_1, FPGAFTM::kTriggerOutSourceMask))
1295 ("Trigger-out Source Mask (128=SINGLE, 64=BUTTON, 32=FIXRATE, 16=DSP_IN_delay, 8=EXT_IN_delay, 4=DSP_IN, 2=EXT_IN, 1=NOT_USED)"
1296 "|mask[uint8]:");
1297
1298 T::AddEvent("SET_TRIGGER_DSP_DELAY", "X:1", FPGAFTM::State::kValid)
1299 (bind(&StateMachineFPGAFTM::WriteRegister64, this, placeholders::_1, FPGAFTM::kTriggerDspDelay))
1300 ("Trigger DSP Delay"
1301 "|delay[2.5ns]:");
1302
1303 T::AddEvent("SET_TRIGGER_EXT_DELAY", "X:1", FPGAFTM::State::kValid)
1304 (bind(&StateMachineFPGAFTM::WriteRegister64, this, placeholders::_1, FPGAFTM::kTriggerExtDelay))
1305 ("Trigger Ext Delay"
1306 "|delay[2.5ns]:");
1307
1308 T::AddEvent("SET_TRIGGER_OUT_DELAY", "X:1", FPGAFTM::State::kValid)
1309 (bind(&StateMachineFPGAFTM::WriteRegister64, this, placeholders::_1, FPGAFTM::kTriggerOutDelay))
1310 ("Trigger Out Delay"
1311 "|delay[2.5ns]:");
1312/*
1313 T::AddEvent("SET_TRIGGER_OUTPUT_MASK", "X:1", FPGAFTM::State::kValid)
1314 (bind(&StateMachineFPGAFTM::WriteRegister64, this, placeholders::_1, FPGAFTM::kTriggerOutputMask))
1315 ("Trigger Output Mask"
1316 "|mask[uint8]:");
1317*/
1318
1319/*
1320 T::AddEvent("SET_RS485_MODE", "S:2;B:4", FPGAFTM::State::kValid)
1321 (bind(&StateMachineFPGAFTM::SetRS485Mode, this, placeholders::_1))
1322 ("Set the RS485 mode"
1323 "|BAUD0[uint16]:Baud rate (word 2)"
1324 "|BAUD1[uint16]:Baud rate (word 3)"
1325 "|PEN[bool]:Parity enabled (0: disabled, 1: enabled)"
1326 "|PAR[bool]:Parity even (0: odd, 1: even)"
1327 "|SPB[bool]:Stop bits (0: one, 1: two)"
1328 "|MSB[bool]:Most Significant Bit First (MSB) (0: LSB, 1: MSB)");
1329
1330
1331 T::AddEvent("ENABLE_RS485", FPGAFTM::State::kValid)
1332 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kTriggerRS485On))
1333 ("Enable RS485 communication.");
1334
1335 T::AddEvent("DISABLE_RS485", FPGAFTM::State::kValid)
1336 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kTriggerRS485Off))
1337 ("Disable RS485 communication.");
1338*/
1339
1340
1341 T::AddEvent("READ_RS485_DATA", FPGAFTM::State::kValid)
1342 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kRS485Data))
1343 ("Read RS485 data");
1344
1345 T::AddEvent("SET_RS485_DATA", "X:1", FPGAFTM::State::kValid)
1346 (bind(&StateMachineFPGAFTM::WriteRegister64, this, placeholders::_1, FPGAFTM::kRS485Data))
1347 ("Set RS485 data");
1348
1349
1350/*
1351 T::AddEvent("SET_FAD_RESET_CYCLES", "X:1", FPGAFTM::State::kValid)
1352 (bind(&StateMachineFPGAFTM::WriteRegister64, this, placeholders::_1, FPGAFTM::kFadResetCycles))
1353 ("Set number of Cycles of FAD reset"
1354 "|cycles[uint16]:Number of cycles (min: 10, 16 bit)");
1355
1356
1357 T::AddEvent("SET_FAD_RESET_ACTIVE_HI", "X:1", FPGAFTM::State::kValid)
1358 (bind(&StateMachineFPGAFTM::WriteRegister64, this, placeholders::_1, FPGAFTM::kFadResetActiveHi))
1359 ("Set whether FAD reset is active hi"
1360 "|hi[bool]:Active hi");
1361*/
1362
1363
1364 T::AddEvent("SINGLE_TRIGGER", FPGAFTM::State::kValid)
1365 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kSingleTrigger))
1366 ("Issue single trigger");
1367
1368
1369
1370 T::AddEvent("ERROR", FPGAFTM::State::kValid)
1371 (bind(&StateMachineFPGAFTM::WriteRegister, this, 0x9999))
1372 ("Send an errorneous command (debugging purpose)");
1373
1374
1375
1376 T::AddEvent("PRINT_CONFIGURATION")
1377 (bind(&S::PrintConfig, &fFTM))
1378 ("Print the current configuration as available in memory");
1379 T::AddEvent("PRINT_DYNAMIC_DATA")
1380 (bind(&S::PrintDynamicData, &fFTM))
1381 ("Print the current dynamic data as available in memory");
1382
1383
1384 // A new configure will first stop the FTM this means
1385 // we can allow it in idle _and_ taking data
1386 T::AddEvent("CONFIGURE", "C", FPGAFTM::State::kValid, FPGAFTM::State::kTriggerOn)
1387 (bind(&StateMachineFPGAFTM::Configure, this, placeholders::_1))
1388 ("Configure a new run");
1389
1390 T::AddEvent("RESET_CONFIGURE", FPGAFTM::State::kConfiguring, FPGAFTM::State::kConfigured)
1391 (bind(&StateMachineFPGAFTM::ResetConfig, this))
1392 ("Reset states during a configuration or in case of configuration error");
1393
1394 T::AddEvent("START_TRIGGER", FPGAFTM::State::kConfigured)
1395 (bind(&StateMachineFPGAFTM::StartTrigger, this))
1396 ("Start trigger as configured by CONFIGURE");
1397
1398 T::AddEvent("STOP_TRIGGER", FPGAFTM::State::kTriggerOn)
1399 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kTriggerShutdown))
1400 ("Disable all triggers");
1401
1402 T::AddEvent("READ_TRIGGER_INHIBIT_STATE", FPGAFTM::State::kValid)
1403 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kTriggerInhibitState))
1404 ("Read trigger inhibit state");
1405
1406 T::AddEvent("READ_TRIGGER_INHIBIT_TIME", FPGAFTM::State::kValid)
1407 (bind(&StateMachineFPGAFTM::ReadRegister, this, FPGAFTM::kTriggerInhibitTime))
1408 ("Read trigger inhibit time");
1409
1410 T::AddEvent("SET_TRIGGER_INHIBIT_ON", FPGAFTM::State::kValid)
1411 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kTriggerInhibitEnable))
1412 ("Set BUSY (active low)");
1413
1414 T::AddEvent("SET_TRIGGER_INHIBIT_OFF", FPGAFTM::State::kValid)
1415 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kTriggerInhibitDisable))
1416 ("Free BUSY (high impedance)");
1417
1418 T::AddEvent("SET_TRIGGER_INHIBIT_TIME", "X:1", FPGAFTM::State::kValid)
1419 (bind(&StateMachineFPGAFTM::WriteRegister64, this, placeholders::_1, FPGAFTM::kTriggerInhibitTime))
1420 ("Trigger inhibit time"
1421 "|time[5.0ns]:");
1422
1423
1424 T::AddEvent("SOFT_RESET", FPGAFTM::State::kValid)
1425 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kSoftReset))
1426 ("Soft reset FPGA");
1427
1428 T::AddEvent("HARD_RESET", FPGAFTM::State::kValid)
1429 (bind(&StateMachineFPGAFTM::WriteRegister, this, FPGAFTM::kHardReset))
1430 ("Hard reset FPGA");
1431
1432 T::AddEvent("SET_INTERVAL", "X:1", FPGAFTM::State::kValid)
1433 (bind(&StateMachineFPGAFTM::SetInterval, this, placeholders::_1))
1434 ("Set temperature request interval"
1435 "|dt[uint32]:Interval in ms (0=off)");
1436
1437
1438
1439 // Conenction commands
1440 T::AddEvent("DISCONNECT", FPGAFTM::State::kConnected, FPGAFTM::State::kValid)
1441 (bind(&StateMachineFPGAFTM::Disconnect, this))
1442 ("Disconnect from ethernet");
1443
1444 T::AddEvent("RECONNECT", "O", FPGAFTM::State::kDisconnected, FPGAFTM::State::kConnected, FPGAFTM::State::kValid)
1445 (bind(&StateMachineFPGAFTM::Reconnect, this, placeholders::_1))
1446 ("(Re)connect ethernet connection, a new address can be given"
1447 "|[host][string]:new ethernet address in the form <host:port>");
1448 }
1449
1450 map<string, FPGAFTM::RunType> fRunTypes;
1451
1452 template<typename _t>
1453 bool GetConfig(Configuration &conf, const string &name, const string &sub, _t &rc)
1454 {
1455 if (conf.HasDef(name, sub))
1456 {
1457 rc = conf.GetDef<_t>(name, sub);
1458 return true;
1459 }
1460
1461 T::Error("Neither "+name+"default nor "+name+sub+" found.");
1462 return false;
1463 }
1464
1465 int EvalOptions(Configuration &conf)
1466 {
1467 fFTM.SetVerbose(!conf.Get<bool>("quiet"));
1468 fFTM.SetDebugTx(conf.Get<bool>("debug-tx"));
1469 fFTM.SetDebugRx(conf.Get<bool>("debug-rx"));
1470 fFTM.SetEndpoint(conf.Get<string>("addr"));
1471 fFTM.SetInterval(conf.Get<uint32_t>("interval"));
1472
1473 // ---------- Setup run types ---------
1474 const vector<string> types = conf.Vec<string>("run-type");
1475 if (types.empty())
1476 T::Warn("No run-types defined.");
1477 else
1478 T::Message("Defining run-types");
1479
1480 for (auto it=types.begin(); it!=types.end(); it++)
1481 {
1482 T::Message(" -> "+ *it);
1483
1484 if (fRunTypes.count(*it)>0)
1485 {
1486 T::Error("Run-type "+*it+" defined twice.");
1487 return 1;
1488 }
1489
1490 FPGAFTM::RunType &c = fRunTypes[*it];
1491 if (!GetConfig(conf, "trigger-period.", *it, c.fTriggerPeriod) ||
1492 !GetConfig(conf, "trigger-type.", *it, c.fTriggerType) ||
1493 !GetConfig(conf, "trigger-mask.", *it, c.fTriggerSourceMask) ||
1494 !GetConfig(conf, "trigger-out-mask.", *it, c.fTriggerOutSourceMask) ||
1495 !GetConfig(conf, "trigger-delay-dsp.", *it, c.fTriggerDspDelay) ||
1496 !GetConfig(conf, "trigger-delay-ext.", *it, c.fTriggerExtDelay) ||
1497 !GetConfig(conf, "trigger-delay-out.", *it, c.fTriggerOutDelay) ||
1498 !GetConfig(conf, "trigger-hold-off.", *it, c.fTriggerHoldOff)
1499 )
1500 return 2;
1501 }
1502
1503 // -----------------------------------
1504
1505 fFTM.StartConnect();
1506
1507 return -1;
1508 }
1509};
1510
1511// ------------------------------------------------------------------------
1512
1513#include "Main.h"
1514
1515
1516template<class T, class S, class R>
1517int RunShell(Configuration &conf)
1518{
1519#if BOOST_VERSION < 104600
1520 const string fname = boost::filesystem::path(conf.GetName()).filename();
1521#else
1522 const string fname = boost::filesystem::path(conf.GetName()).filename().string();
1523#endif
1524
1525 ConnectionFPGAFTM::fIsFACT = fname!="ftmctrl";
1526 return Main::execute<T, StateMachineFPGAFTM<S, R>>(conf);
1527}
1528
1529void SetupConfiguration(Configuration &conf)
1530{
1531 po::options_description control("Interlock control");
1532 control.add_options()
1533 ("no-dim,d", po_switch(), "Disable dim services")
1534 ("addr,a", var<string>(""), "Network address of the lid controling Arduino including port")
1535 ("quiet,q", po_bool(true), "Disable printing contents of all received messages (except dynamic data) in clear text.")
1536 ("debug-tx", po_bool(), "Enable debugging of ethernet transmission.")
1537 ("debug-rx", po_bool(), "Enable debugging for received data.")
1538 ("interval", var<uint32_t>(1000), "Interval in which dynamic data is requested [ms]")
1539 ;
1540
1541 po::options_description runtype("Run type configuration");
1542 runtype.add_options()
1543 ("run-type", vars<string>(), "Name of run-types (replace the * in the following configuration by the case-sensitive names defined here)")
1544 ("trigger-type.*", var<string>(), "Calibration type ('internal', 'external', 'off')")
1545 ("trigger-period.*", var<uint32_t>(), "Target rate for calibration by rate")
1546 ("trigger-mask.*", var<uint16_t>(), "Trigger mask")
1547 ("trigger-out-mask.*", var<uint16_t>(), "Trigger mask")
1548 ("trigger-delay-dsp.*", var<uint16_t>(), "")
1549 ("trigger-delay-ext.*", var<uint16_t>(), "")
1550 ("trigger-delay-out.*", var<uint16_t>(), "")
1551 ("trigger-hold-off.*", var<uint32_t>(), "")
1552 ;
1553
1554 conf.AddOptions(control);
1555 conf.AddOptions(runtype);
1556}
1557
1558/*
1559 Extract usage clause(s) [if any] for SYNOPSIS.
1560 Translators: "Usage" and "or" here are patterns (regular expressions) which
1561 are used to match the usage synopsis in program output. An example from cp
1562 (GNU coreutils) which contains both strings:
1563 Usage: cp [OPTION]... [-T] SOURCE DEST
1564 or: cp [OPTION]... SOURCE... DIRECTORY
1565 or: cp [OPTION]... -t DIRECTORY SOURCE...
1566 */
1567void PrintUsage()
1568{
1569 cout <<
1570 "The ftmctrl is a hardware interface to the FPGAFTM board built for FAMOUS"
1571 "\n"
1572 "The default is that the program is started with user intercation. "
1573 "All actions are supposed to arrive as DimCommands. Using the -c "
1574 "option, a local shell can be initialized. With h or help a short "
1575 "help message about the usuage can be brought to the screen.\n"
1576 "\n"
1577 "Usage: ftmctrl [-c type] [OPTIONS]\n"
1578 " or: ftmctrl [OPTIONS]\n";
1579 cout << endl;
1580}
1581
1582void PrintHelp()
1583{
1584 Main::PrintHelp<StateMachineFPGAFTM<StateMachine, ConnectionFPGAFTM>>();
1585
1586 /* Additional help text which is printed after the configuration
1587 options goes here */
1588
1589 /*
1590 cout << "bla bla bla" << endl << endl;
1591 cout << endl;
1592 cout << "Environment:" << endl;
1593 cout << "environment" << endl;
1594 cout << endl;
1595 cout << "Examples:" << endl;
1596 cout << "test exam" << endl;
1597 cout << endl;
1598 cout << "Files:" << endl;
1599 cout << "files" << endl;
1600 cout << endl;
1601 */
1602}
1603
1604int main(int argc, const char* argv[])
1605{
1606 Configuration conf(argv[0]);
1607 conf.SetPrintUsage(PrintUsage);
1608 Main::SetupConfiguration(conf);
1609 SetupConfiguration(conf);
1610
1611 if (!conf.DoParse(argc, argv, PrintHelp))
1612 return 127;
1613
1614 // No console access at all
1615 if (!conf.Has("console"))
1616 {
1617 if (conf.Get<bool>("no-dim"))
1618 return RunShell<LocalStream, StateMachine, ConnectionFPGAFTM>(conf);
1619 else
1620 return RunShell<LocalStream, StateMachineDim, ConnectionDimFPGAFTM>(conf);
1621 }
1622 // Cosole access w/ and w/o Dim
1623 if (conf.Get<bool>("no-dim"))
1624 {
1625 if (conf.Get<int>("console")==0)
1626 return RunShell<LocalShell, StateMachine, ConnectionFPGAFTM>(conf);
1627 else
1628 return RunShell<LocalConsole, StateMachine, ConnectionFPGAFTM>(conf);
1629 }
1630 else
1631 {
1632 if (conf.Get<int>("console")==0)
1633 return RunShell<LocalShell, StateMachineDim, ConnectionDimFPGAFTM>(conf);
1634 else
1635 return RunShell<LocalConsole, StateMachineDim, ConnectionDimFPGAFTM>(conf);
1636 }
1637
1638 return 0;
1639}
Note: See TracBrowser for help on using the repository browser.