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

Last change on this file since 11264 was 11176, checked in by tbretz, 13 years ago
Added output of frequency calculated from the clock conditioner values.
File size: 21.5 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
13namespace FTM
14{
15 enum States
16 {
17 // State Machine states
18 kDisconnected = 1,
19 kConnected,
20 kIdle,
21 kTakingData,
22
23 // FTM internal states
24 kFtmIdle = 1, ///< Trigger output disabled, configuration possible
25 kFtmConfig = 2, ///< FTM and FTUs are being reconfigured
26 kFtmRunning = 3, ///< Trigger output enabled, configuration ignored
27 kFtmCalib = 4,
28 };
29
30 /// Command codes for FTM communication
31 enum Commands
32 {
33 // First word
34 kCmdRead = 0x0001, ///< Request data
35 kCmdWrite = 0x0002, ///< Send data
36 kCmdStartRun = 0x0004, ///< Enable the trigger output
37 kCmdStopRun = 0x0008, ///< Disable the trigger output
38 kCmdPing = 0x0010, ///< Ping all FTUs (get FTU list)
39 kCmdCrateReset = 0x0020, ///< Reboot (no power cycle) all FTUs and FADs of one crate
40 kCmdDisableReports = 0x0040, ///< Disable transmission of rate-reports (dynamic data)
41 kCmdToggleLed = 0xc000,
42
43 // second word for read and write
44 kCmdStaticData = 0x0001, ///< Specifies that static (configuration) data is read/written
45 kCmdDynamicData = 0x0002, ///< Specifies that dynamic data is read/written
46 kCmdRegister = 0x0004, ///< Specifies that a register is read/written
47
48 // second word for StartRun
49 kStartRun = 0x0001, ///< ...until kCmdStopRun
50 kTakeNevents = 0x0002, ///< ...fixed number of events
51
52 // second word for kCmdCrateReset
53 kResetCrate0 = 0x0001,
54 kResetCrate1 = 0x0002,
55 kResetCrate2 = 0x0004,
56 kResetCrate3 = 0x0008,
57 };
58
59
60 /// Types sent in the header of the following data
61 enum Types
62 {
63 kHeader = 0, ///< Local extension to identify a header in fCounter
64 kStaticData = 1, ///< Static (configuration) data
65 kDynamicData = 2, ///< Dynamic data (rates)
66 kFtuList = 3, ///< FTU list (answer of ping)
67 kErrorList = 4, ///< Error list (error when FTU communication failed)
68 kRegister = 5, ///< A requested register value
69 };
70
71 // --------------------------------------------------------------------
72
73 enum Delimiter
74 {
75 kDelimiterStart = 0xfb01, ///< Start delimiter send before each header
76 kDelimiterEnd = 0x04fe ///< End delimiter send after each data block
77 };
78
79 struct Header
80 {
81 uint16_t fDelimiter; ///< Start delimiter
82 uint16_t fType; ///< Type of the data to be received after the header
83 uint16_t fDataSize; ///< Size in words to be received after the header (incl end delim.)
84 uint16_t fState; ///< State of the FTM central state machine
85 uint64_t fBoardId; ///< FPGA device DNA (unique chip id)
86 uint16_t fFirmwareId; ///< Version number
87 uint32_t fTriggerCounter; ///< FTM internal counter of all trigger decision independant of trigger-line enable/disable (reset: start/stop run)
88 uint64_t fTimeStamp; ///< Internal counter (micro-seconds, reset: start/stop run)
89
90 Header() { init(*this); }
91
92 std::vector<uint16_t> HtoN() const
93 {
94 Header h(*this);
95
96 Reverse(&h.fBoardId);
97 Reverse(&h.fTriggerCounter);
98 Reverse(&h.fTimeStamp);
99
100 return htoncpy(h);
101 }
102 void operator=(const std::vector<uint16_t> &vec)
103 {
104 ntohcpy(vec, *this);
105
106 Reverse(&fBoardId);
107 Reverse(&fTriggerCounter);
108 Reverse(&fTimeStamp);
109 }
110
111 void clear() { reset(*this); }
112 void print(std::ostream &out) const;
113
114 } __attribute__((__packed__));
115
116 struct DimPassport
117 {
118 uint64_t fBoardId;
119 uint16_t fFirmwareId;
120
121 DimPassport(const Header &h) :
122 fBoardId(h.fBoardId),
123 fFirmwareId(h.fFirmwareId)
124 {
125 }
126 } __attribute__((__packed__));
127
128 struct DimTriggerCounter
129 {
130 uint64_t fTimeStamp;
131 uint32_t fTriggerCounter;
132
133 DimTriggerCounter(const Header &h) :
134 fTimeStamp(h.fTimeStamp),
135 fTriggerCounter(h.fTriggerCounter)
136 {
137 }
138 } __attribute__((__packed__));
139
140
141 struct StaticDataBoard
142 {
143 uint16_t fEnable[4]; /// enable of 4x9 pixels coded as 4x9bits
144 uint16_t fDAC[5]; /// 0-3 (A-D) Threshold of patches, 4 (H) Threshold for N out of 4 (12 bit each)
145 uint16_t fPrescaling; /// Internal readout time of FTUs for trigger counter
146
147 StaticDataBoard() { init(*this); }
148
149 void print(std::ostream &out) const;
150
151 } __attribute__((__packed__));
152
153 struct StaticData
154 {
155 enum Limits
156 {
157 kMaxMultiplicity = 40, ///< Minimum required trigger multiplicity
158 kMaxWindow = 0xf, ///< (4ns * x + 8ns) At least N (multiplicity) rising edges (trigger signal) within this window
159 kMaxDeadTime = 0xffff, ///< (4ns * x + 8ns)
160 kMaxDelayTimeMarker = 0x3ff, ///< (4ns * x + 8ns)
161 kMaxDelayTrigger = 0x3ff, ///< (4ns * x + 8ns)
162 kMaxTriggerInterval = 0x3ff, ///<
163 kMaxSequence = 0x1f,
164 kMaxDAC = 0xfff,
165 kMaxAddr = 0xfff,
166 kMaxPatchIdx = 159,
167 kMaxPixelIdx = 1439,
168 kMaskSettings = 0xf,
169 kMaskLEDs = 0xf,
170 };
171
172 enum GeneralSettings
173 {
174 kTrigger = 0x80, ///< Physics trigger decision (PhysicTrigger)
175 kPedestal = 0x40, ///< Pedestal trigger (artifical)
176 kLPint = 0x20, ///< Enable artificial trigger after light pulse (LP2)
177 kLPext = 0x10, ///< Enable trigger decision after light pulse (CalibrationTrigger, LP1)
178 kExt2 = 0x08, ///< External trigger signal 2
179 kExt1 = 0x04, ///< External trigger signal 1
180 kVeto = 0x02, ///< Veto trigger decision / artifical triggers
181 kClockConditioner = 0x01, ///< Select clock conditioner frequency (1) / time marker (0) as output
182 };
183
184 uint16_t fGeneralSettings; // Enable for different trigger types / select for TIM/ClockConditioner output (only 8 bit used)
185 uint16_t fStatusLEDs; // only 8 bit used
186 uint16_t fTriggerInterval; // [ms] Interval between two artificial triggers (no matter which type) minimum 1ms, 10 bit
187 uint16_t fTriggerSequence; // Ratio between trigger types send as artificial trigger (in this order) 3x5bit
188 uint64_t fDummy0;
189 uint16_t fMultiplicityPhysics; /// Required trigger multiplicity for physcis triggers (0-40)
190 uint16_t fMultiplicityCalib; /// Required trigger multiplicity calibration (LPext) triggers (0-40)
191 uint16_t fDelayTrigger; /// (4ns * x + 8ns) FTM internal programmable delay between trigger decision and output
192 uint16_t fDelayTimeMarker; /// (4ns * x + 8ns) FTM internal programmable delay between trigger descision and time marker output
193 uint16_t fDeadTime; /// (4ns * x + 8ns) FTM internal programmable dead time after trigger decision
194 uint32_t fClockConditioner[8]; /// R0, R1, R8, R9, R11, R13, R14, R15
195 uint16_t fWindowPhysics; /// (4ns * x + 8ns) At least N (multiplicity) rising edges (trigger signal) within this window
196 uint16_t fWindowCalib; /// (4ns * x + 8ns) At least N (multiplicity) rising edges (trigger signal) within this window
197 uint16_t fDummy1;
198
199 StaticDataBoard fBoard[4][10]; // 4 crates * 10 boards (Crate0/FTU0 == readout time of FTUs)
200
201 uint16_t fActiveFTU[4]; // 4 crates * 10 bits (FTU enable)
202
203 StaticData() { init(*this); }
204
205 std::vector<uint16_t> HtoN() const
206 {
207 StaticData d(*this);
208 for (int i=0; i<8; i++)
209 Reverse(d.fClockConditioner+i);
210
211 return htoncpy(d);
212 }
213
214 void operator=(const std::vector<uint16_t> &vec)
215 {
216 ntohcpy(vec, *this);
217
218 for (int i=0; i<8; i++)
219 Reverse(fClockConditioner+i);
220 }
221
222 void clear() { reset(*this); }
223 void print(std::ostream &out) const;
224
225 StaticDataBoard &operator[](int i) { return fBoard[i/10][i%10]; }
226 const StaticDataBoard &operator[](int i) const { return fBoard[i/10][i%10]; }
227
228 void EnableFTU(int i) { fActiveFTU[i/10] |= (1<<(i%10)); }
229 void DisableFTU(int i) { fActiveFTU[i/10] &= ~(1<<(i%10)); }
230
231 void EnableAllFTU() { for (int i=0; i<4; i++) fActiveFTU[i] = 0x3ff; }
232 void DisableAllFTU() { for (int i=0; i<4; i++) fActiveFTU[i] = 0; }
233
234 void ToggleFTU(int i) { fActiveFTU[i/10] ^= (1<<(i%10)); }
235
236 void Enable(GeneralSettings type, bool enable)
237 {
238 if (enable)
239 fGeneralSettings |= uint16_t(type);
240 else
241 fGeneralSettings &= ~uint16_t(type); }
242
243 bool IsEnabled(GeneralSettings type) const { return fGeneralSettings&uint16_t(type); }
244
245 void EnablePixel(int idx, bool enable)
246 {
247 const int pixel = idx%9;
248 const int patch = (idx/9)%4;
249 const int board = (idx/9)/4;
250
251 uint16_t &pix = fBoard[board/10][board%10].fEnable[patch];
252
253 if (enable)
254 pix |= (1<<pixel);
255 else
256 pix &= ~(1<<pixel);
257 }
258
259 bool Enabled(uint16_t idx) const
260 {
261 const int pixel = idx%9;
262 const int patch = (idx/9)%4;
263 const int board = (idx/9)/4;
264
265 return (fBoard[board/10][board%10].fEnable[patch]>>pixel)&1;
266 }
267
268 uint8_t GetSequencePed() const { return (fTriggerSequence>>10)&0x1f; }
269 uint8_t GetSequenceLPint() const { return (fTriggerSequence>> 5)&0x1f; }
270 uint8_t GetSequenceLPext() const { return (fTriggerSequence) &0x1f; }
271
272 } __attribute__((__packed__));
273
274 // DimStructures must be a multiple of two... I don't know why
275 struct DimStaticData
276 {
277 uint64_t fTimeStamp;
278 //8
279 uint16_t fGeneralSettings; // only 8 bit used
280 uint16_t fStatusLEDs; // only 8 bit used
281 uint64_t fActiveFTU; // 40 bits in row
282 //20
283 uint16_t fTriggerInterval; // only 10 bit used
284 //22
285 uint16_t fTriggerSeqLPint; // only 5bits used
286 uint16_t fTriggerSeqLPext; // only 5bits used
287 uint16_t fTriggerSeqPed; // only 5bits used
288 //28
289 uint16_t fMultiplicityPhysics; // 0-40
290 uint16_t fMultiplicityCalib; // 0-40
291 //32
292 uint16_t fWindowPhysics;
293 uint16_t fWindowCalib;
294 //36
295 uint16_t fDelayTrigger;
296 uint16_t fDelayTimeMarker;
297 uint32_t fDeadTime;
298 //44
299 uint32_t fClockConditioner[8];
300 //60
301 uint16_t fEnable[90]; // 160*9bit = 180byte
302 uint16_t fThreshold[160];
303 uint16_t fMultiplicity[40]; // N out of 4
304 uint16_t fPrescaling[40];
305 // 640+60 = 700
306
307 bool HasTrigger() const { return fGeneralSettings & StaticData::kTrigger; }
308 bool HasPedestal() const { return fGeneralSettings & StaticData::kPedestal; }
309 bool HasLPext() const { return fGeneralSettings & StaticData::kLPext; }
310 bool HasLPint() const { return fGeneralSettings & StaticData::kLPint; }
311 bool HasExt2() const { return fGeneralSettings & StaticData::kExt2; }
312 bool HasExt1() const { return fGeneralSettings & StaticData::kExt1; }
313 bool HasVeto() const { return fGeneralSettings & StaticData::kVeto; }
314 bool HasClockConditioner() const { return fGeneralSettings & StaticData::kClockConditioner; }
315
316 bool IsActive(int i) const { return fActiveFTU&(uint64_t(1)<<i); }
317 bool IsEnabled(int i) const { return fEnable[i/16]&(1<<(i%16)); }
318
319 DimStaticData() { memset(this, 0, sizeof(DimStaticData)); }
320
321 DimStaticData(const Header &h, const StaticData &d) :
322 fTimeStamp(h.fTimeStamp),
323 fGeneralSettings(d.fGeneralSettings),
324 fStatusLEDs(d.fStatusLEDs),
325 fActiveFTU( uint64_t(d.fActiveFTU[0]) |
326 (uint64_t(d.fActiveFTU[1])<<10) |
327 (uint64_t(d.fActiveFTU[2])<<20) |
328 (uint64_t(d.fActiveFTU[3])<<30)),
329 fTriggerInterval(d.fTriggerInterval),
330 fTriggerSeqLPint((d.fTriggerSequence>>5)&0x1f),
331 fTriggerSeqLPext((d.fTriggerSequence)&0x1f),
332 fTriggerSeqPed((d.fTriggerSequence>>10)&0x1f),
333 fMultiplicityPhysics(d.fMultiplicityPhysics),
334 fMultiplicityCalib(d.fMultiplicityCalib),
335 fWindowPhysics(d.fWindowPhysics*4+8),
336 fWindowCalib(d.fWindowCalib*4+8),
337 fDelayTrigger(d.fDelayTrigger*4+8),
338 fDelayTimeMarker(d.fDelayTimeMarker*4+8),
339 fDeadTime(uint32_t(d.fDeadTime)*4+8)
340 {
341 memcpy(fClockConditioner, d.fClockConditioner, sizeof(uint32_t)*8);
342
343 uint16_t src[160];
344 for (int i=0; i<40; i++)
345 {
346 for (int j=0; j<4; j++)
347 {
348 src[i*4+j] = d[i].fEnable[j];
349 fThreshold[i*4+j] = d[i].fDAC[j];
350 }
351
352 fMultiplicity[i] = d[i].fDAC[4];
353 fPrescaling[i] = d[i].fPrescaling+1;
354 }
355 bitcpy(fEnable, 90, src, 160, 9);
356 }
357
358 } __attribute__((__packed__));
359
360
361 struct DynamicDataBoard
362 {
363 uint32_t fRatePatch[4]; // Patch 0,1,2,3
364 uint32_t fRateTotal; // Sum
365
366 uint16_t fOverflow; // Patches: bits 0-3, total 4
367 uint16_t fCrcError;
368
369 void print(std::ostream &out) const;
370
371 void reverse()
372 {
373 for (int i=0; i<4; i++)
374 Reverse(fRatePatch+i);
375
376 Reverse(&fRateTotal);
377 }
378
379 uint32_t &operator[](int i) { return fRatePatch[i]; }
380
381 } __attribute__((__packed__));
382
383
384 struct DynamicData
385 {
386 uint64_t fOnTimeCounter;
387 uint16_t fTempSensor[4]; // U45, U46, U48, U49
388
389 DynamicDataBoard fBoard[4][10]; // 4 crates * 10 boards
390
391 DynamicData() { init(*this); }
392
393 std::vector<uint16_t> HtoN() const
394 {
395 DynamicData d(*this);
396
397 Reverse(&d.fOnTimeCounter);
398
399 for (int c=0; c<4; c++)
400 for (int b=0; b<10; b++)
401 d.fBoard[c][b].reverse();
402
403 return htoncpy(d);
404 }
405
406 void operator=(const std::vector<uint16_t> &vec)
407 {
408 ntohcpy(vec, *this);
409
410 Reverse(&fOnTimeCounter);
411
412 for (int c=0; c<4; c++)
413 for (int b=0; b<10; b++)
414 fBoard[c][b].reverse();
415 }
416
417 void clear() { reset(*this); }
418 void print(std::ostream &out) const;
419
420 DynamicDataBoard &operator[](int i) { return fBoard[i/10][i%10]; }
421 const DynamicDataBoard &operator[](int i) const { return fBoard[i/10][i%10]; }
422
423 } __attribute__((__packed__));
424
425
426 struct DimDynamicData
427 {
428 uint64_t fTimeStamp;
429
430 uint64_t fOnTimeCounter;
431 float fTempSensor[4];
432
433 uint32_t fRatePatch[160];
434
435 uint32_t fRateBoard[40];
436 uint16_t fRateOverflow[40];
437
438 uint16_t fCrcError[40];
439
440 DimDynamicData(const Header &h, const DynamicData &d) :
441 fTimeStamp(h.fTimeStamp),
442 fOnTimeCounter(d.fOnTimeCounter)
443 {
444 for (int i=0; i<4; i++)
445 fTempSensor[i] = d.fTempSensor[i];
446
447 for (int i=0; i<40; i++)
448 {
449 fRateBoard[i] = d[i].fRateTotal;
450 fRateOverflow[i] = d[i].fOverflow;
451 fCrcError[i] = d[i].fCrcError;
452 for (int j=0; j<4; j++)
453 fRatePatch[i*4+j] = d[i].fRatePatch[j];
454 }
455 }
456
457 } __attribute__((__packed__));
458
459
460 struct FtuResponse
461 {
462 uint16_t fPingAddr; // Number of Pings and addr (pings= see error)
463 uint64_t fDNA;
464 uint16_t fErrorCounter; //
465
466 void reverse() { Reverse(&fDNA); }
467
468 void print(std::ostream &out) const;
469
470 } __attribute__((__packed__));
471
472 struct FtuList
473 {
474 uint16_t fNumBoards; /// Total number of boards responded
475 uint16_t fNumBoardsCrate[4]; /// Num of board responded in crate 0-3
476 uint16_t fActiveFTU[4]; /// List of active FTU boards in crate 0-3
477
478 FtuResponse fFTU[4][10];
479
480 FtuList() { init(*this); }
481
482 std::vector<uint16_t> HtoN() const
483 {
484 FtuList d(*this);
485
486 for (int c=0; c<4; c++)
487 for (int b=0; b<10; b++)
488 d.fFTU[c][b].reverse();
489
490 return htoncpy(d);
491 }
492
493 void operator=(const std::vector<uint16_t> &vec)
494 {
495 ntohcpy(vec, *this);
496
497 for (int c=0; c<4; c++)
498 for (int b=0; b<10; b++)
499 fFTU[c][b].reverse();
500 }
501
502 void clear() { reset(*this); }
503 void print(std::ostream &out) const;
504
505 FtuResponse &operator[](int i) { return fFTU[i/10][i%10]; }
506 const FtuResponse &operator[](int i) const { return fFTU[i/10][i%10]; }
507
508 } __attribute__((__packed__));
509
510 struct DimFtuList
511 {
512 uint64_t fTimeStamp;
513 uint64_t fActiveFTU;
514
515 uint16_t fNumBoards; /// Number of boards answered in total
516 uint8_t fNumBoardsCrate[4]; /// Number of boards answered per crate
517
518 uint64_t fDNA[40]; /// DNA of FTU board
519 uint8_t fAddr[40]; /// Address of FTU board
520 uint8_t fPing[40]; /// Number of pings until response (same as in Error)
521
522 DimFtuList(const Header &h, const FtuList &d) :
523 fTimeStamp(h.fTimeStamp),
524 fActiveFTU( uint64_t(d.fActiveFTU[0]) |
525 (uint64_t(d.fActiveFTU[1])<<10) |
526 (uint64_t(d.fActiveFTU[2])<<20) |
527 (uint64_t(d.fActiveFTU[3])<<30)),
528 fNumBoards(d.fNumBoards)
529 {
530 for (int i=0; i<4; i++)
531 fNumBoardsCrate[i] = d.fNumBoardsCrate[i];
532
533 for (int i=0; i<40; i++)
534 {
535 fDNA[i] = d[i].fDNA;
536 fAddr[i] = d[i].fPingAddr&0x3f;
537 fPing[i] = (d[i].fPingAddr>>8)&0x3;
538 }
539 }
540
541 bool IsActive(int i) const { return fActiveFTU&(uint64_t(1)<<i); }
542
543 } __attribute__((__packed__));
544
545
546 struct Error
547 {
548 uint16_t fNumCalls; // 0=error, >1 needed repetition but successfull
549
550 uint16_t fDelimiter;
551 uint16_t fDestAddress;
552 uint16_t fSrcAddress;
553 uint16_t fFirmwareId;
554 uint16_t fCommand;
555 uint16_t fData[21];
556 uint16_t fCrcErrorCounter;
557 uint16_t fCrcCheckSum;
558
559 Error() { init(*this); }
560
561 std::vector<uint16_t> HtoN() const
562 {
563 return htoncpy(*this);
564 }
565
566 void operator=(const std::vector<uint16_t> &vec) { ntohcpy(vec, *this); }
567
568 void clear() { reset(*this); }
569
570 uint16_t &operator[](int idx) { return fData[idx]; }
571 const uint16_t &operator[](int idx) const { return fData[idx]; }
572
573 void print(std::ostream &out) const;
574
575 } __attribute__((__packed__));
576
577 struct DimError
578 {
579 uint64_t fTimeStamp;
580 Error fError;
581
582 DimError(const Header &h, const Error &e) :
583 fTimeStamp(h.fTimeStamp),
584 fError(e)
585 {
586 fError.fDestAddress = (e.fDestAddress&0x3)*10 + ((e.fDestAddress>>2)&0xf);
587 fError.fSrcAddress = (e.fSrcAddress &0x3)*10 + ((e.fSrcAddress >>2)&0xf);
588 }
589
590 } __attribute__((__packed__));
591
592 /*
593 struct Command
594 {
595 uint16_t fStartDelimiter;
596 uint16_t fCommand;
597 uint16_t fParam[3];
598
599 Command() { init(*this); }
600
601 void HtoN() { hton(*this); }
602 void NtoH() { ntoh(*this); }
603
604 void operator=(const std::vector<uint16_t> &vec) { ntohcpy(vec, *this); }
605
606 void clear() { reset(*this); }
607
608
609 } __attribute__((__packed__));
610 */
611
612 // --------------------------------------------------------------------
613
614 inline std::ostream &operator<<(std::ostream &out, const FtuResponse &h)
615 {
616 h.print(out);
617 return out;
618 }
619
620 inline std::ostream &operator<<(std::ostream &out, const Header &h)
621 {
622 h.print(out);
623 return out;
624 }
625
626
627 inline std::ostream &operator<<(std::ostream &out, const FtuList &h)
628 {
629 h.print(out);
630 return out;
631 }
632
633 inline std::ostream &operator<<(std::ostream &out, const DynamicDataBoard &h)
634 {
635 h.print(out);
636 return out;
637 }
638
639 inline std::ostream &operator<<(std::ostream &out, const DynamicData &h)
640 {
641 h.print(out);
642 return out;
643 }
644
645 inline std::ostream &operator<<(std::ostream &out, const StaticDataBoard &h)
646 {
647 h.print(out);
648 return out;
649 }
650
651 inline std::ostream &operator<<(std::ostream &out, const StaticData &h)
652 {
653 h.print(out);
654 return out;
655 }
656
657 inline std::ostream &operator<<(std::ostream &out, const Error &h)
658 {
659 h.print(out);
660 return out;
661 }
662};
663
664#endif
Note: See TracBrowser for help on using the repository browser.