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 |
|
---|
30 | namespace ba = boost::asio;
|
---|
31 | namespace bs = boost::system;
|
---|
32 | namespace dummy = ba::placeholders;
|
---|
33 |
|
---|
34 | using namespace std;
|
---|
35 |
|
---|
36 | class ConnectionFPGAFTM : public Connection
|
---|
37 | {
|
---|
38 | public:
|
---|
39 | static bool fIsFACT;
|
---|
40 |
|
---|
41 | private:
|
---|
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 |
|
---|
532 | public:
|
---|
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 |
|
---|
589 | public:
|
---|
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 |
|
---|
679 | bool ConnectionFPGAFTM::fIsFACT = true;
|
---|
680 |
|
---|
681 | // ------------------------------------------------------------------------
|
---|
682 |
|
---|
683 | #include "DimDescriptionService.h"
|
---|
684 |
|
---|
685 | class ConnectionDimFPGAFTM : public ConnectionFPGAFTM
|
---|
686 | {
|
---|
687 | private:
|
---|
688 | DimDescribedService fDimConfig;
|
---|
689 | DimDescribedService fDimData;
|
---|
690 |
|
---|
691 | public:
|
---|
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 |
|
---|
742 | template <class T, class S>
|
---|
743 | class StateMachineFPGAFTM : public StateMachineAsio<T>
|
---|
744 | {
|
---|
745 | private:
|
---|
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 |
|
---|
1092 | public:
|
---|
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 |
|
---|
1516 | template<class T, class S, class R>
|
---|
1517 | int 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 |
|
---|
1529 | void 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 | */
|
---|
1567 | void 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 |
|
---|
1582 | void 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 |
|
---|
1604 | int 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 | }
|
---|