source: trunk/FACT++/src/HeadersFTM.h@ 16778

Last change on this file since 16778 was 16771, checked in by tbretz, 12 years ago
When compiling a new static buffer to be sent to the FTM, not the last received buffer has to be used but the last sent buffer, this is because a new configuration might be in the queue already, but we have not yet received the answer. To avoid race conditions, the sent buffer is now filled at connection time and used to update the configuration; also a new state was introduced to signal (for debugging mainly) whether the last sent and the last received static data are different (this does not include the thresholds); for convenience in the ratecontrol: added a SET_ALL_THRESHOLDS
File size: 26.7 KB
Line 
1#ifndef FACT_HeadersFTM
2#define FACT_HeadersFTM
3
4#include <ostream>
5
6// For debugging
7#include <iostream>
8
9#include "ByteOrder.h"
10
11// ====================================================================
12
13
14namespace FTM
15{
16 enum States
17 {
18 kFtmUndefined = 0,
19
20 // FTM internal states
21 kFtmIdle = 1, ///< Trigger output disabled, configuration possible
22 kFtmConfig = 2, ///< FTM and FTUs are being reconfigured
23 kFtmRunning = 3, ///< Trigger output enabled, configuration ignored
24 kFtmCalib = 4,
25
26 kFtmStates = 0x0ff,
27 kFtmLocked = 0x100,
28
29 };
30
31 // idle: not locked: 0x2711
32 // running: not locked: 0x2713
33
34 namespace State
35 {
36 enum StateMachine
37 {
38 kDisconnected = 1,
39 kConnected,
40 kIdle,
41 kValid,
42 kTriggerOn,
43 kConfiguring1,
44 kConfiguring2,
45 kConfigured,
46
47 kConfigError1 = 0x101,
48 kConfigError2 = 0x102,
49 //kConfigError3 = 0x103,
50 };
51 }
52
53 /// Command codes for FTM communication
54 enum Commands
55 {
56 // First word
57 kCmdRead = 0x0001, ///< Request data
58 kCmdWrite = 0x0002, ///< Send data
59 kCmdStartRun = 0x0004, ///< Enable the trigger output
60 kCmdStopRun = 0x0008, ///< Disable the trigger output
61 kCmdPing = 0x0010, ///< Ping all FTUs (get FTU list)
62 kCmdCrateReset = 0x0020, ///< Reboot (no power cycle) all FTUs and FADs of one crate
63 kCmdDisableReports = 0x0040, ///< Disable transmission of rate-reports (dynamic data)
64 kCmdConfigFTU = 0x0080, ///< Configure single FTU board
65 kCmdToggleLed = 0xc000,
66
67 // second word for read and write
68 kCmdStaticData = 0x0001, ///< Specifies that static (configuration) data is read/written
69 kCmdDynamicData = 0x0002, ///< Specifies that dynamic data is read/written
70 kCmdRegister = 0x0004, ///< Specifies that a register is read/written
71
72 // second word for StartRun
73 kStartRun = 0x0001, ///< ...until kCmdStopRun
74 kTakeNevents = 0x0002, ///< ...fixed number of events
75
76 // second word for kCmdCrateReset
77 kResetCrate0 = 0x0001,
78 kResetCrate1 = 0x0002,
79 kResetCrate2 = 0x0004,
80 kResetCrate3 = 0x0008,
81 };
82
83
84 /// Types sent in the header of the following data
85 enum Types
86 {
87 kHeader = 0, ///< Local extension to identify a header in fCounter
88 kStaticData = 1, ///< Static (configuration) data
89 kDynamicData = 2, ///< Dynamic data (rates)
90 kFtuList = 3, ///< FTU list (answer of ping)
91 kErrorList = 4, ///< Error list (error when FTU communication failed)
92 kRegister = 5, ///< A requested register value
93 };
94
95 // --------------------------------------------------------------------
96
97 enum Delimiter
98 {
99 kDelimiterStart = 0xfb01, ///< Start delimiter send before each header
100 kDelimiterEnd = 0x04fe ///< End delimiter send after each data block
101 };
102
103 struct Header
104 {
105 uint16_t fDelimiter; ///< Start delimiter
106 uint16_t fType; ///< Type of the data to be received after the header
107 uint16_t fDataSize; ///< Size in words to be received after the header (incl end delim.)
108 uint16_t fState; ///< State of the FTM central state machine
109 uint64_t fBoardId; ///< FPGA device DNA (unique chip id)
110 uint16_t fFirmwareId; ///< Version number
111 uint32_t fTriggerCounter; ///< FTM internal counter of all trigger decision independant of trigger-line enable/disable (reset: start/stop run)
112 uint64_t fTimeStamp; ///< Internal counter (micro-seconds, reset: start/stop run)
113
114 Header() { init(*this); }
115
116 std::vector<uint16_t> HtoN() const
117 {
118 Header h(*this);
119
120 Reverse(&h.fBoardId);
121 Reverse(&h.fTriggerCounter);
122 Reverse(&h.fTimeStamp);
123
124 return htoncpy(h);
125 }
126 void operator=(const std::vector<uint16_t> &vec)
127 {
128 ntohcpy(vec, *this);
129
130 Reverse(&fBoardId);
131 Reverse(&fTriggerCounter);
132 Reverse(&fTimeStamp);
133 }
134
135 void clear() { reset(*this); }
136 void print(std::ostream &out) const;
137
138 } __attribute__((__packed__));
139
140 struct DimPassport
141 {
142 uint64_t fBoardId;
143 uint16_t fFirmwareId;
144
145 DimPassport(const Header &h) :
146 fBoardId(h.fBoardId),
147 fFirmwareId(h.fFirmwareId)
148 {
149 }
150 } __attribute__((__packed__));
151
152 /*
153 struct DimTriggerCounter
154 {
155 uint64_t fTimeStamp;
156 uint32_t fTriggerCounter;
157
158 DimTriggerCounter(const Header &h) :
159 fTimeStamp(h.fTimeStamp),
160 fTriggerCounter(h.fTriggerCounter)
161 {
162 }
163 } __attribute__((__packed__));
164 */
165
166 struct StaticDataBoard
167 {
168 uint16_t fEnable[4]; /// enable of 4x9 pixels coded as 4x9bits
169 uint16_t fDAC[5]; /// 0-3 (A-D) Threshold of patches, 4 (H) Threshold for N out of 4 (12 bit each)
170 uint16_t fPrescaling; /// Internal readout time of FTUs for trigger counter
171
172 StaticDataBoard() { init(*this); }
173
174 void print(std::ostream &out) const;
175
176 } __attribute__((__packed__));
177
178 struct StaticData
179 {
180 enum Limits
181 {
182 kMaxMultiplicity = 40, ///< Minimum required trigger multiplicity
183 kMaxWindow = 0xf, ///< (4ns * x + 8ns) At least N (multiplicity) rising edges (trigger signal) within this window
184 kMaxDeadTime = 0xffff, ///< (4ns * x + 8ns)
185 kMaxDelayTimeMarker = 0x3ff, ///< (4ns * x + 8ns)
186 kMaxDelayTrigger = 0x3ff, ///< (4ns * x + 8ns)
187 kMaxTriggerInterval = 0x3ff, ///<
188 kMaxIntensity = 0x7f,
189 kMaxSequence = 0x1f,
190 kMaxDAC = 0xfff,
191 kMaxAddr = 0xfff,
192 kMaxPatchIdx = 159,
193 kMaxPixelIdx = 1439,
194 kMaskSettings = 0xf,
195 kMaskLEDs = 0xf,
196 };
197
198 enum GeneralSettings
199 {
200 kTrigger = 0x80, ///< Physics trigger decision (PhysicTrigger)
201 kPedestal = 0x40, ///< Pedestal trigger (artifical)
202 kLPint = 0x20, ///< Enable artificial trigger after light pulse (LP2)
203 kLPext = 0x10, ///< Enable trigger decision after light pulse (CalibrationTrigger, LP1)
204 kExt2 = 0x08, ///< External trigger signal 2
205 kExt1 = 0x04, ///< External trigger signal 1
206 kVeto = 0x02, ///< Veto trigger decision / artifical triggers
207 kClockConditioner = 0x01, ///< Select clock conditioner frequency (1) / time marker (0) as output
208 };
209
210 enum LightPulserEnable
211 {
212 kGroup1 = 0x40,
213 kGroup2 = 0x80,
214 };
215
216 uint16_t fGeneralSettings; /// Enable for different trigger types / select for TIM/ClockConditioner output (only 8 bit used)
217 uint16_t fStatusLEDs; /// only 8 bit used
218 uint16_t fTriggerInterval; /// [ms] Interval between two artificial triggers (no matter which type) minimum 1ms, 10 bit
219 uint16_t fTriggerSequence; /// Ratio between trigger types send as artificial trigger (in this order) 3x5bit
220 uint8_t fIntensityLPext; /// Intensity of LEDs (0-127)
221 uint8_t fEnableLPext; /// Enable for LED group 1/2 (LightPulserEnable)
222 uint8_t fIntensityLPint; /// Intensity of LEDs (0-127)
223 uint8_t fEnableLPint; /// Enable for LED group 1/2 (LightPulserEnable)
224 uint32_t fDummy0;
225 uint16_t fMultiplicityPhysics; /// Required trigger multiplicity for physcis triggers (0-40)
226 uint16_t fMultiplicityCalib; /// Required trigger multiplicity calibration (LPext) triggers (0-40)
227 uint16_t fDelayTrigger; /// (4ns * x + 8ns) FTM internal programmable delay between trigger decision and output
228 uint16_t fDelayTimeMarker; /// (4ns * x + 8ns) FTM internal programmable delay between trigger descision and time marker output
229 uint16_t fDeadTime; /// (4ns * x + 8ns) FTM internal programmable dead time after trigger decision
230 uint32_t fClockConditioner[8]; /// R0, R1, R8, R9, R11, R13, R14, R15
231 uint16_t fWindowPhysics; /// (4ns * x + 8ns) At least N (multiplicity) rising edges (trigger signal) within this window
232 uint16_t fWindowCalib; /// (4ns * x + 8ns) At least N (multiplicity) rising edges (trigger signal) within this window
233 uint16_t fDummy1;
234
235 StaticDataBoard fBoard[4][10]; // 4 crates * 10 boards (Crate0/FTU0 == readout time of FTUs)
236
237 uint16_t fActiveFTU[4]; // 4 crates * 10 bits (FTU enable)
238
239 StaticData() { init(*this); }
240 StaticData(const std::vector<uint16_t> &vec)
241 {
242 ntohcpy(vec, *this);
243
244 for (int i=0; i<8; i++)
245 Reverse(fClockConditioner+i);
246 }
247
248 std::vector<uint16_t> HtoN() const
249 {
250 StaticData d(*this);
251 for (int i=0; i<8; i++)
252 Reverse(d.fClockConditioner+i);
253
254 return htoncpy(d);
255 }
256
257 bool operator==(StaticData d) const
258 {
259 for (int i=0; i<4; i++)
260 for (int j=0; j<10; j++)
261 memcpy(d.fBoard[i][j].fDAC, fBoard[i][j].fDAC, sizeof(uint16_t)*5);
262 return memcmp(this, &d, sizeof(StaticData))==0;
263 }
264
265 bool valid() const { static StaticData empty; return memcmp(this, &empty, sizeof(FTM::StaticData))!=0; }
266
267 void clear() { reset(*this); }
268 void print(std::ostream &out) const;
269
270 StaticDataBoard &operator[](int i) { return fBoard[i/10][i%10]; }
271 const StaticDataBoard &operator[](int i) const { return fBoard[i/10][i%10]; }
272
273 void EnableFTU(int i) { fActiveFTU[i/10] |= (1<<(i%10)); }
274 void DisableFTU(int i) { fActiveFTU[i/10] &= ~(1<<(i%10)); }
275
276 void EnableAllFTU() { for (int i=0; i<4; i++) fActiveFTU[i] = 0x3ff; }
277 void DisableAllFTU() { for (int i=0; i<4; i++) fActiveFTU[i] = 0; }
278
279 void EnableLPint(LightPulserEnable group, bool enable)
280 {
281 if (enable)
282 fEnableLPint |= group;
283 else
284 fEnableLPint &= ~group;
285 }
286
287 void EnableLPext(LightPulserEnable group, bool enable)
288 {
289 if (enable)
290 fEnableLPext |= group;
291 else
292 fEnableLPext &= ~group;
293 }
294
295 void ToggleFTU(int i) { fActiveFTU[i/10] ^= (1<<(i%10)); }
296
297 void Enable(GeneralSettings type, bool enable)
298 {
299 if (enable)
300 fGeneralSettings |= uint16_t(type);
301 else
302 fGeneralSettings &= ~uint16_t(type);
303 }
304
305 bool IsEnabled(GeneralSettings type) const { return fGeneralSettings&uint16_t(type); }
306
307 uint16_t *EnablePixel(int idx, bool enable)
308 {
309 const int pixel = idx%9;
310 const int patch = (idx/9)%4;
311 const int board = (idx/9)/4;
312
313 uint16_t &pix = fBoard[board/10][board%10].fEnable[patch];
314
315 if (enable)
316 pix |= (1<<pixel);
317 else
318 pix &= ~(1<<pixel);
319
320 return &pix;
321 }
322
323 void EnablePatch(int idx, bool enable)
324 {
325 const int patch = idx%4;
326 const int board = idx/4;
327
328 fBoard[board/10][board%10].fEnable[patch] = enable ? 0x1ff : 0;
329 }
330
331 void EnableAllPixel()
332 {
333 for (int c=0; c<4; c++)
334 for (int b=0; b<10; b++)
335 for (int p=0; p<4; p++)
336 fBoard[c][b].fEnable[p] = 0x1ff;
337 }
338
339 bool Enabled(uint16_t idx) const
340 {
341 const int pixel = idx%9;
342 const int patch = (idx/9)%4;
343 const int board = (idx/9)/4;
344
345 return (fBoard[board/10][board%10].fEnable[patch]>>pixel)&1;
346 }
347
348 uint8_t GetSequencePed() const { return (fTriggerSequence>>10)&0x1f; }
349 uint8_t GetSequenceLPint() const { return (fTriggerSequence>> 5)&0x1f; }
350 uint8_t GetSequenceLPext() const { return (fTriggerSequence) &0x1f; }
351
352 void SetSequence(uint8_t ped, uint8_t lpint, uint8_t lpext)
353 {
354 fTriggerSequence = ((ped&0x1f)<<10)|((lpint&0x1f)<<5)|(lpext&0x1f);
355
356 Enable(kPedestal, ped >0);
357 Enable(kLPext, lpext>0);
358 Enable(kLPint, lpint>0);
359 }
360
361 void SetClockRegister(const uint64_t reg[])
362 {
363 for (int i=0; i<8; i++)
364 fClockConditioner[i] = reg[i];
365 }
366
367 void SetPrescaling(uint16_t val)
368 {
369 for (int c=0; c<4; c++)
370 for (int b=0; b<10; b++)
371 fBoard[c][b].fPrescaling = val;
372 }
373
374 } __attribute__((__packed__));
375
376 // DimStructures must be a multiple of two... I don't know why
377 struct DimStaticData
378 {
379 uint64_t fTimeStamp;
380 //8
381 uint16_t fGeneralSettings; // only 8 bit used
382 uint16_t fStatusLEDs; // only 8 bit used
383 uint64_t fActiveFTU; // 40 bits in row
384 //20
385 uint16_t fTriggerInterval; // only 10 bit used
386 //22
387 uint16_t fTriggerSeqLPint; // only 5bits used
388 uint16_t fTriggerSeqLPext; // only 5bits used
389 uint16_t fTriggerSeqPed; // only 5bits used
390 // 28
391 uint8_t fEnableLPint; /// Enable for LED group 1/2 (LightPulserEnable)
392 uint8_t fEnableLPext; /// Enable for LED group 1/2 (LightPulserEnable)
393 uint8_t fIntensityLPint; /// Intensity of LEDs (0-127)
394 uint8_t fIntensityLPext; /// Intensity of LEDs (0-127)
395 //32
396 uint16_t fMultiplicityPhysics; // 0-40
397 uint16_t fMultiplicityCalib; // 0-40
398 //36
399 uint16_t fWindowPhysics;
400 uint16_t fWindowCalib;
401 //40
402 uint16_t fDelayTrigger;
403 uint16_t fDelayTimeMarker;
404 uint32_t fDeadTime;
405 //48
406 uint32_t fClockConditioner[8];
407 //64
408 uint16_t fEnable[90]; // 160*9bit = 180byte
409 uint16_t fThreshold[160];
410 uint16_t fMultiplicity[40]; // N out of 4
411 uint16_t fPrescaling[40];
412 // 640+64 = 704
413
414 bool HasTrigger() const { return fGeneralSettings & StaticData::kTrigger; }
415 bool HasPedestal() const { return fGeneralSettings & StaticData::kPedestal; }
416 bool HasLPext() const { return fGeneralSettings & StaticData::kLPext; }
417 bool HasLPint() const { return fGeneralSettings & StaticData::kLPint; }
418 bool HasExt2() const { return fGeneralSettings & StaticData::kExt2; }
419 bool HasExt1() const { return fGeneralSettings & StaticData::kExt1; }
420 bool HasVeto() const { return fGeneralSettings & StaticData::kVeto; }
421 bool HasClockConditioner() const { return fGeneralSettings & StaticData::kClockConditioner; }
422
423 bool HasLPextG1() const { return fEnableLPext&StaticData::kGroup1; }
424 bool HasLPextG2() const { return fEnableLPext&StaticData::kGroup2; }
425 bool HasLPintG1() const { return fEnableLPint&StaticData::kGroup1; }
426 bool HasLPintG2() const { return fEnableLPint&StaticData::kGroup2; }
427
428 bool IsActive(int i) const { return fActiveFTU&(uint64_t(1)<<i); }
429 bool IsEnabled(int i) const { return fEnable[i/16]&(1<<(i%16)); }
430
431 DimStaticData() { memset(this, 0, sizeof(DimStaticData)); }
432
433 DimStaticData(const Header &h, const StaticData &d) :
434 fTimeStamp(h.fTimeStamp),
435 fGeneralSettings(d.fGeneralSettings),
436 fStatusLEDs(d.fStatusLEDs),
437 fActiveFTU( uint64_t(d.fActiveFTU[0]) |
438 (uint64_t(d.fActiveFTU[1])<<10) |
439 (uint64_t(d.fActiveFTU[2])<<20) |
440 (uint64_t(d.fActiveFTU[3])<<30)),
441 fTriggerInterval(d.fTriggerInterval),
442 fTriggerSeqLPint((d.fTriggerSequence>>5)&0x1f),
443 fTriggerSeqLPext((d.fTriggerSequence)&0x1f),
444 fTriggerSeqPed((d.fTriggerSequence>>10)&0x1f),
445 fEnableLPint(d.fEnableLPint),
446 fEnableLPext(d.fEnableLPext),
447 fIntensityLPint(d.fIntensityLPint),
448 fIntensityLPext(d.fIntensityLPext),
449 fMultiplicityPhysics(d.fMultiplicityPhysics),
450 fMultiplicityCalib(d.fMultiplicityCalib),
451 fWindowPhysics(d.fWindowPhysics*4+8),
452 fWindowCalib(d.fWindowCalib*4+8),
453 fDelayTrigger(d.fDelayTrigger*4+8),
454 fDelayTimeMarker(d.fDelayTimeMarker*4+8),
455 fDeadTime(uint32_t(d.fDeadTime)*4+8)
456 {
457 memcpy(fClockConditioner, d.fClockConditioner, sizeof(uint32_t)*8);
458
459 uint16_t src[160];
460 for (int i=0; i<40; i++)
461 {
462 for (int j=0; j<4; j++)
463 {
464 src[i*4+j] = d[i].fEnable[j];
465 fThreshold[i*4+j] = d[i].fDAC[j];
466 }
467
468 fMultiplicity[i] = d[i].fDAC[4];
469 fPrescaling[i] = d[i].fPrescaling+1;
470 }
471 bitcpy(fEnable, 90, src, 160, 9);
472 }
473
474 } __attribute__((__packed__));
475
476
477 struct DynamicDataBoard
478 {
479 uint32_t fRatePatch[4]; // Patch 0,1,2,3
480 uint32_t fRateTotal; // Sum
481
482 uint16_t fOverflow; // Patches: bits 0-3, total 4
483 uint16_t fCrcError;
484
485 void print(std::ostream &out) const;
486
487 void reverse()
488 {
489 for (int i=0; i<4; i++)
490 Reverse(fRatePatch+i);
491
492 Reverse(&fRateTotal);
493 }
494
495 uint32_t &operator[](int i) { return fRatePatch[i]; }
496
497 } __attribute__((__packed__));
498
499
500 struct DynamicData
501 {
502 uint64_t fOnTimeCounter;
503 uint16_t fTempSensor[4]; // U45, U46, U48, U49
504
505 DynamicDataBoard fBoard[4][10]; // 4 crates * 10 boards
506
507 DynamicData() { init(*this); }
508
509 std::vector<uint16_t> HtoN() const
510 {
511 DynamicData d(*this);
512
513 Reverse(&d.fOnTimeCounter);
514
515 for (int c=0; c<4; c++)
516 for (int b=0; b<10; b++)
517 d.fBoard[c][b].reverse();
518
519 return htoncpy(d);
520 }
521
522 void operator=(const std::vector<uint16_t> &vec)
523 {
524 ntohcpy(vec, *this);
525
526 Reverse(&fOnTimeCounter);
527
528 for (int c=0; c<4; c++)
529 for (int b=0; b<10; b++)
530 fBoard[c][b].reverse();
531 }
532
533 void clear() { reset(*this); }
534 void print(std::ostream &out) const;
535
536 DynamicDataBoard &operator[](int i) { return fBoard[i/10][i%10]; }
537 const DynamicDataBoard &operator[](int i) const { return fBoard[i/10][i%10]; }
538
539 } __attribute__((__packed__));
540
541
542 struct DimDynamicData
543 {
544 uint64_t fTimeStamp;
545
546 uint64_t fOnTimeCounter;
547 float fTempSensor[4];
548
549 uint32_t fRatePatch[160];
550
551 uint32_t fRateBoard[40];
552 uint16_t fRateOverflow[40];
553
554 uint16_t fPrescaling[40];
555
556 uint16_t fCrcError[40];
557
558 uint16_t fState;
559
560 DimDynamicData(const Header &h, const DynamicData &d, const StaticData &s) :
561 fTimeStamp(h.fTimeStamp),
562 fOnTimeCounter(d.fOnTimeCounter),
563 fState(h.fState)
564 {
565 for (int i=0; i<4; i++)
566 fTempSensor[i] = d.fTempSensor[i];
567
568 for (int i=0; i<40; i++)
569 {
570 fRateBoard[i] = d[i].fRateTotal;
571 fRateOverflow[i] = d[i].fOverflow;
572 fCrcError[i] = d[i].fCrcError;
573 for (int j=0; j<4; j++)
574 fRatePatch[i*4+j] = d[i].fRatePatch[j];
575
576 fPrescaling[i] = s[i].fPrescaling+1;
577 }
578 }
579
580 } __attribute__((__packed__));
581
582 struct DimTriggerRates
583 {
584 uint64_t fTimeStamp;
585 uint64_t fOnTimeCounter;
586 uint32_t fTriggerCounter;
587 float fTriggerRate;
588 float fBoardRate[40];
589 float fPatchRate[160];
590
591 float fElapsedTime;
592 float fOnTime;
593
594 DimTriggerRates() { memset(this, 0, sizeof(DimTriggerRates)); }
595
596 DimTriggerRates(const Header &h, const DynamicData &d, const StaticData &s, float rate, float et, float ot) :
597 fTimeStamp(h.fTimeStamp), fOnTimeCounter(d.fOnTimeCounter),
598 fTriggerCounter(h.fTriggerCounter), fTriggerRate(rate),
599 fElapsedTime(et), fOnTime(ot)
600 {
601 for (int i=0; i<40; i++)
602 {
603 if ((d[i].fOverflow>>4)&1)
604 fBoardRate[i] = float(UINT32_MAX+1)*2/(s[i].fPrescaling+1);
605 else
606 fBoardRate[i] = float(d[i].fRateTotal)*2/(s[i].fPrescaling+1);
607
608 // FIXME: Include fCrcError in calculation
609 //fRateOverflow[i] = d[i].fOverflow;
610 for (int j=0; j<4; j++)
611 if ((d[i].fOverflow>>j)&1)
612 fPatchRate[i*4+j] = float(UINT32_MAX+1)*2/(s[i].fPrescaling+1);
613 else
614 fPatchRate[i*4+j] = float(d[i].fRatePatch[j])*2/(s[i].fPrescaling+1);
615 }
616 }
617
618 } __attribute__((__packed__));
619
620
621 struct FtuResponse
622 {
623 uint16_t fPingAddr; // Number of Pings and addr (pings= see error)
624 uint64_t fDNA;
625 uint16_t fErrorCounter; //
626
627 void reverse() { Reverse(&fDNA); }
628
629 void print(std::ostream &out) const;
630
631 } __attribute__((__packed__));
632
633 struct FtuList
634 {
635 uint16_t fNumBoards; /// Total number of boards responded
636 uint16_t fNumBoardsCrate[4]; /// Num of board responded in crate 0-3
637 uint16_t fActiveFTU[4]; /// List of active FTU boards in crate 0-3
638
639 FtuResponse fFTU[4][10];
640
641 FtuList() { init(*this); }
642
643 std::vector<uint16_t> HtoN() const
644 {
645 FtuList d(*this);
646
647 for (int c=0; c<4; c++)
648 for (int b=0; b<10; b++)
649 d.fFTU[c][b].reverse();
650
651 return htoncpy(d);
652 }
653
654 void operator=(const std::vector<uint16_t> &vec)
655 {
656 ntohcpy(vec, *this);
657
658 for (int c=0; c<4; c++)
659 for (int b=0; b<10; b++)
660 fFTU[c][b].reverse();
661 }
662
663 void clear() { reset(*this); }
664 void print(std::ostream &out) const;
665
666 FtuResponse &operator[](int i) { return fFTU[i/10][i%10]; }
667 const FtuResponse &operator[](int i) const { return fFTU[i/10][i%10]; }
668
669 } __attribute__((__packed__));
670
671 struct DimFtuList
672 {
673 uint64_t fTimeStamp;
674 uint64_t fActiveFTU;
675
676 uint16_t fNumBoards; /// Number of boards answered in total
677 uint8_t fNumBoardsCrate[4]; /// Number of boards answered per crate
678
679 uint64_t fDNA[40]; /// DNA of FTU board
680 uint8_t fAddr[40]; /// Address of FTU board
681 uint8_t fPing[40]; /// Number of pings until response (same as in Error)
682
683 DimFtuList(const Header &h, const FtuList &d) :
684 fTimeStamp(h.fTimeStamp),
685 fActiveFTU( uint64_t(d.fActiveFTU[0]) |
686 (uint64_t(d.fActiveFTU[1])<<10) |
687 (uint64_t(d.fActiveFTU[2])<<20) |
688 (uint64_t(d.fActiveFTU[3])<<30)),
689 fNumBoards(d.fNumBoards)
690 {
691 for (int i=0; i<4; i++)
692 fNumBoardsCrate[i] = d.fNumBoardsCrate[i];
693
694 for (int i=0; i<40; i++)
695 {
696 fDNA[i] = d[i].fDNA;
697 fAddr[i] = d[i].fPingAddr&0x3f;
698 fPing[i] = (d[i].fPingAddr>>8)&0x3;
699 }
700 }
701
702 bool IsActive(int i) const { return fActiveFTU&(uint64_t(1)<<i); }
703
704 } __attribute__((__packed__));
705
706
707 struct Error
708 {
709 uint16_t fNumCalls; // 0=error, >1 needed repetition but successfull
710
711 uint16_t fDelimiter;
712 uint16_t fDestAddress;
713 uint16_t fSrcAddress;
714 uint16_t fFirmwareId;
715 uint16_t fCommand;
716 uint16_t fData[21];
717 uint16_t fCrcErrorCounter;
718 uint16_t fCrcCheckSum;
719
720 Error() { init(*this); }
721
722 std::vector<uint16_t> HtoN() const
723 {
724 return htoncpy(*this);
725 }
726
727 void operator=(const std::vector<uint16_t> &vec) { ntohcpy(vec, *this); }
728
729 void clear() { reset(*this); }
730
731 uint16_t &operator[](int idx) { return fData[idx]; }
732 const uint16_t &operator[](int idx) const { return fData[idx]; }
733
734 void print(std::ostream &out) const;
735
736 } __attribute__((__packed__));
737
738 struct DimError
739 {
740 uint64_t fTimeStamp;
741 Error fError;
742
743 DimError(const Header &h, const Error &e) :
744 fTimeStamp(h.fTimeStamp),
745 fError(e)
746 {
747 fError.fDestAddress = (e.fDestAddress&0x3)*10 + ((e.fDestAddress>>2)&0xf);
748 fError.fSrcAddress = (e.fSrcAddress &0x3)*10 + ((e.fSrcAddress >>2)&0xf);
749 }
750
751 } __attribute__((__packed__));
752
753 /*
754 struct Command
755 {
756 uint16_t fStartDelimiter;
757 uint16_t fCommand;
758 uint16_t fParam[3];
759
760 Command() { init(*this); }
761
762 void HtoN() { hton(*this); }
763 void NtoH() { ntoh(*this); }
764
765 void operator=(const std::vector<uint16_t> &vec) { ntohcpy(vec, *this); }
766
767 void clear() { reset(*this); }
768
769
770 } __attribute__((__packed__));
771 */
772
773 // --------------------------------------------------------------------
774
775 inline std::ostream &operator<<(std::ostream &out, const FtuResponse &h)
776 {
777 h.print(out);
778 return out;
779 }
780
781 inline std::ostream &operator<<(std::ostream &out, const Header &h)
782 {
783 h.print(out);
784 return out;
785 }
786
787
788 inline std::ostream &operator<<(std::ostream &out, const FtuList &h)
789 {
790 h.print(out);
791 return out;
792 }
793
794 inline std::ostream &operator<<(std::ostream &out, const DynamicDataBoard &h)
795 {
796 h.print(out);
797 return out;
798 }
799
800 inline std::ostream &operator<<(std::ostream &out, const DynamicData &h)
801 {
802 h.print(out);
803 return out;
804 }
805
806 inline std::ostream &operator<<(std::ostream &out, const StaticDataBoard &h)
807 {
808 h.print(out);
809 return out;
810 }
811
812 inline std::ostream &operator<<(std::ostream &out, const StaticData &h)
813 {
814 h.print(out);
815 return out;
816 }
817
818 inline std::ostream &operator<<(std::ostream &out, const Error &h)
819 {
820 h.print(out);
821 return out;
822 }
823};
824
825#endif
Note: See TracBrowser for help on using the repository browser.