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

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